xref: /illumos-gate/usr/src/uts/common/io/sfxge/sfxge_gld_v3.c (revision ea4c6b78cebe2a3687fa43deeedf6212a124d817)
1 /*
2  * Copyright (c) 2008-2016 Solarflare Communications Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  * The views and conclusions contained in the software and documentation are
27  * those of the authors and should not be interpreted as representing official
28  * policies, either expressed or implied, of the FreeBSD Project.
29  */
30 
31 #include <sys/types.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/stream.h>
35 #include <sys/strsun.h>
36 #include <sys/strsubr.h>
37 #include <sys/dlpi.h>
38 #include <sys/ksynch.h>
39 #include <sys/cpuvar.h>
40 #include <sys/cpu.h>
41 #include <sys/vlan.h>
42 
43 #include <inet/tcp.h>
44 
45 #include "sfxge.h"
46 
47 void
48 sfxge_gld_link_update(sfxge_t *sp)
49 {
50 	sfxge_mac_t *smp = &(sp->s_mac);
51 	link_state_t link;
52 
53 	switch (smp->sm_link_mode) {
54 	case EFX_LINK_UNKNOWN:
55 		link = LINK_STATE_UNKNOWN;
56 		break;
57 	case EFX_LINK_DOWN:
58 		link = LINK_STATE_DOWN;
59 		break;
60 	default:
61 		link = LINK_STATE_UP;
62 	}
63 
64 	mac_link_update(sp->s_mh, link);
65 }
66 
67 void
68 sfxge_gld_mtu_update(sfxge_t *sp)
69 {
70 #ifdef _USE_MTU_UPDATE
71 	(void) mac_maxsdu_update(sp->s_mh, sp->s_mtu);
72 #else
73 	_NOTE(ARGUNUSED(sp));
74 #endif
75 }
76 
77 void
78 sfxge_gld_rx_post(sfxge_t *sp, unsigned int index, mblk_t *mp)
79 {
80 	_NOTE(ARGUNUSED(index))
81 
82 	mac_rx(sp->s_mh, NULL, mp);
83 }
84 
85 
86 void
87 sfxge_gld_rx_push(sfxge_t *sp)
88 {
89 	_NOTE(ARGUNUSED(sp))
90 }
91 
92 
93 static uint64_t
94 sfxge_phy_dfl_cap_test64(sfxge_t *sp, uint32_t field)
95 {
96 	return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT, field, NULL) ?
97 	    1ull : 0ull);
98 }
99 
100 
101 static uint64_t
102 sfxge_phy_cur_cap_test64(sfxge_t *sp, uint32_t field)
103 {
104 	return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_CURRENT, field, NULL) ?
105 	    1ull : 0ull);
106 }
107 
108 static uint64_t
109 sfxge_phy_lp_cap_test64(sfxge_t *sp, uint32_t field)
110 {
111 	return (sfxge_phy_lp_cap_test(sp, field) ? 1ull : 0ull);
112 }
113 
114 static int
115 sfxge_gld_getstat(void *arg, unsigned int id, uint64_t *valp)
116 {
117 	sfxge_t *sp = arg;
118 	efx_nic_t *enp = sp->s_enp;
119 	int rc;
120 
121 	if (sp->s_mac.sm_state != SFXGE_MAC_STARTED) {
122 		rc = ENODEV;
123 		goto fail1;
124 	}
125 
126 	switch (id) {
127 	case MAC_STAT_IFSPEED: {
128 		unsigned int speed;
129 
130 		sfxge_mac_link_speed_get(sp, &speed);
131 
132 		*valp = (uint64_t)speed * 1000000ull;
133 		break;
134 	}
135 	case ETHER_STAT_LINK_DUPLEX: {
136 		sfxge_link_duplex_t duplex;
137 
138 		sfxge_mac_link_duplex_get(sp, &duplex);
139 
140 		switch (duplex) {
141 		case SFXGE_LINK_DUPLEX_UNKNOWN:
142 			*valp = LINK_DUPLEX_UNKNOWN;
143 			break;
144 
145 		case SFXGE_LINK_DUPLEX_HALF:
146 			*valp = LINK_DUPLEX_HALF;
147 			break;
148 
149 		case SFXGE_LINK_DUPLEX_FULL:
150 			*valp = LINK_DUPLEX_FULL;
151 			break;
152 
153 		default:
154 			ASSERT(B_FALSE);
155 			break;
156 		}
157 		break;
158 	}
159 
160 	case ETHER_STAT_CAP_40GFDX:
161 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_40000FDX);
162 		break;
163 	case ETHER_STAT_CAP_10GFDX:
164 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10000FDX);
165 		break;
166 	case ETHER_STAT_CAP_1000FDX:
167 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000FDX);
168 		break;
169 	case ETHER_STAT_CAP_1000HDX:
170 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000HDX);
171 		break;
172 	case ETHER_STAT_CAP_100FDX:
173 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100FDX);
174 		break;
175 	case ETHER_STAT_CAP_100HDX:
176 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100HDX);
177 		break;
178 	case ETHER_STAT_CAP_10FDX:
179 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10FDX);
180 		break;
181 	case ETHER_STAT_CAP_10HDX:
182 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10HDX);
183 		break;
184 	case ETHER_STAT_CAP_ASMPAUSE:
185 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_ASYM);
186 		break;
187 	case ETHER_STAT_CAP_PAUSE:
188 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_PAUSE);
189 		break;
190 	case ETHER_STAT_CAP_AUTONEG:
191 		*valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_AN);
192 		break;
193 	case ETHER_STAT_ADV_CAP_40GFDX:
194 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_40000FDX);
195 		break;
196 	case ETHER_STAT_ADV_CAP_10GFDX:
197 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10000FDX);
198 		break;
199 	case ETHER_STAT_ADV_CAP_1000FDX:
200 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000FDX);
201 		break;
202 	case ETHER_STAT_ADV_CAP_1000HDX:
203 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000HDX);
204 		break;
205 	case ETHER_STAT_ADV_CAP_100FDX:
206 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100FDX);
207 		break;
208 	case ETHER_STAT_ADV_CAP_100HDX:
209 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100HDX);
210 		break;
211 	case ETHER_STAT_ADV_CAP_10FDX:
212 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10FDX);
213 		break;
214 	case ETHER_STAT_ADV_CAP_10HDX:
215 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10HDX);
216 		break;
217 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
218 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_ASYM);
219 		break;
220 	case ETHER_STAT_ADV_CAP_PAUSE:
221 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_PAUSE);
222 		break;
223 	case ETHER_STAT_ADV_CAP_AUTONEG:
224 		*valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_AN);
225 		break;
226 	case ETHER_STAT_LP_CAP_40GFDX:
227 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_40000FDX);
228 		break;
229 	case ETHER_STAT_LP_CAP_10GFDX:
230 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10000FDX);
231 		break;
232 	case ETHER_STAT_LP_CAP_1000FDX:
233 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000FDX);
234 		break;
235 	case ETHER_STAT_LP_CAP_1000HDX:
236 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000HDX);
237 		break;
238 	case ETHER_STAT_LP_CAP_100FDX:
239 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100FDX);
240 		break;
241 	case ETHER_STAT_LP_CAP_100HDX:
242 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100HDX);
243 		break;
244 	case ETHER_STAT_LP_CAP_10FDX:
245 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10FDX);
246 		break;
247 	case ETHER_STAT_LP_CAP_10HDX:
248 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10HDX);
249 		break;
250 	case ETHER_STAT_LP_CAP_ASMPAUSE:
251 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_ASYM);
252 		break;
253 	case ETHER_STAT_LP_CAP_PAUSE:
254 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_PAUSE);
255 		break;
256 	case ETHER_STAT_LP_CAP_AUTONEG:
257 		*valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_AN);
258 		break;
259 
260 	case ETHER_STAT_XCVR_ADDR: {
261 		const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp);
262 		*valp = encp->enc_port;
263 		break;
264 	}
265 	case ETHER_STAT_XCVR_ID: {
266 		uint32_t oui;
267 
268 		if ((rc = efx_phy_oui_get(sp->s_enp, &oui)) != 0)
269 			goto fail2;
270 		*valp = oui;
271 		break;
272 	}
273 	case MAC_STAT_MULTIRCV:
274 		sfxge_mac_stat_get(sp, EFX_MAC_RX_MULTICST_PKTS, valp);
275 		break;
276 
277 	case MAC_STAT_BRDCSTRCV:
278 		sfxge_mac_stat_get(sp, EFX_MAC_RX_BRDCST_PKTS, valp);
279 		break;
280 
281 	case MAC_STAT_MULTIXMT:
282 		sfxge_mac_stat_get(sp, EFX_MAC_TX_MULTICST_PKTS, valp);
283 		break;
284 
285 	case MAC_STAT_BRDCSTXMT:
286 		sfxge_mac_stat_get(sp, EFX_MAC_TX_BRDCST_PKTS, valp);
287 		break;
288 
289 	case MAC_STAT_IERRORS:
290 		sfxge_mac_stat_get(sp, EFX_MAC_RX_ERRORS, valp);
291 		break;
292 
293 	case MAC_STAT_OERRORS:
294 		sfxge_mac_stat_get(sp, EFX_MAC_TX_ERRORS, valp);
295 		break;
296 
297 	case MAC_STAT_RBYTES:
298 		sfxge_mac_stat_get(sp, EFX_MAC_RX_OCTETS, valp);
299 		break;
300 
301 	case MAC_STAT_IPACKETS:
302 		sfxge_mac_stat_get(sp, EFX_MAC_RX_PKTS, valp);
303 		break;
304 
305 	case MAC_STAT_OBYTES:
306 		sfxge_mac_stat_get(sp, EFX_MAC_TX_OCTETS, valp);
307 		break;
308 
309 	case MAC_STAT_OPACKETS:
310 		sfxge_mac_stat_get(sp, EFX_MAC_TX_PKTS, valp);
311 		break;
312 
313 	case MAC_STAT_NORCVBUF:
314 		sfxge_mac_stat_get(sp, EFX_MAC_RX_DROP_EVENTS, valp);
315 		break;
316 
317 	case ETHER_STAT_FCS_ERRORS:
318 		sfxge_mac_stat_get(sp, EFX_MAC_RX_FCS_ERRORS, valp);
319 		break;
320 
321 	default:
322 		rc = ENOTSUP;
323 		goto fail3;
324 	}
325 
326 	return (0);
327 fail3:
328 	DTRACE_PROBE(fail3);
329 fail2:
330 	DTRACE_PROBE(fail2);
331 fail1:
332 	DTRACE_PROBE1(fail1, int, rc);
333 
334 	return (rc);
335 }
336 
337 static int
338 sfxge_gld_start(void *arg)
339 {
340 	sfxge_t *sp = arg;
341 	int rc;
342 
343 	if ((rc = sfxge_start(sp, B_FALSE)) != 0)
344 		goto fail1;
345 
346 	return (0);
347 
348 fail1:
349 	DTRACE_PROBE1(fail1, int, rc);
350 
351 	return (rc);
352 }
353 
354 static void
355 sfxge_gld_stop(void *arg)
356 {
357 	sfxge_t *sp = arg;
358 
359 	sfxge_stop(sp);
360 }
361 
362 static int
363 sfxge_gld_setpromisc(void *arg, boolean_t on)
364 {
365 	sfxge_t *sp = arg;
366 
367 	return sfxge_mac_promisc_set(sp,
368 	    (on) ? SFXGE_PROMISC_ALL_PHYS : SFXGE_PROMISC_OFF);
369 }
370 
371 static int
372 sfxge_gld_multicst(void *arg, boolean_t add, const uint8_t *addr)
373 {
374 	sfxge_t *sp = arg;
375 	int rc;
376 
377 	if (add) {
378 		if ((rc = sfxge_mac_multicst_add(sp, addr)) != 0)
379 			goto fail1;
380 	} else {
381 		if ((rc = sfxge_mac_multicst_remove(sp, addr)) != 0)
382 			goto fail2;
383 	}
384 
385 	return (0);
386 
387 fail2:
388 	DTRACE_PROBE(fail2);
389 fail1:
390 	DTRACE_PROBE1(fail1, int, rc);
391 	return (rc);
392 }
393 
394 static int
395 sfxge_gld_unicst(void *arg, const uint8_t *addr)
396 {
397 	sfxge_t *sp = arg;
398 	int rc;
399 
400 	if ((rc = sfxge_mac_unicst_set(sp, (uint8_t *)addr)) != 0)
401 		goto fail1;
402 
403 	return (0);
404 
405 fail1:
406 	DTRACE_PROBE1(fail1, int, rc);
407 
408 	return (rc);
409 }
410 
411 static void
412 sfxge_gld_ioctl(void *arg, queue_t *wq, mblk_t *mp)
413 {
414 	sfxge_t *sp = arg;
415 
416 	sfxge_ioctl(sp, wq, mp);
417 }
418 
419 
420 static mblk_t *
421 sfxge_gld_tx(void *arg, mblk_t *mp)
422 {
423 	sfxge_t *sp = arg;
424 	mblk_t *next;
425 
426 	/* Walk the packet chain */
427 	do {
428 		/* Break the packet out of the chain */
429 		next = mp->b_next;
430 		mp->b_next = NULL;
431 
432 		if (next != NULL)
433 			prefetch_read_many(next);
434 
435 		/* Post the packet in the appropriate transmit queue */
436 		if (sfxge_tx_packet_add(sp, mp) == ENOSPC) {
437 			mp->b_next = next;
438 			return (mp);
439 		}
440 
441 		mp = next;
442 	} while (mp != NULL);
443 
444 	return (NULL);
445 }
446 
447 /*
448  * This must not be static, in order to be tunable by /etc/system.
449  * (Static declarations may be optmized away by the compiler.)
450  */
451 boolean_t	sfxge_lso = B_TRUE;
452 
453 static boolean_t
454 sfxge_gld_getcapab(void *arg, mac_capab_t cap, void *cap_arg)
455 {
456 	int rc;
457 
458 	_NOTE(ARGUNUSED(arg))
459 
460 	switch (cap) {
461 	case MAC_CAPAB_LSO: {
462 		mac_capab_lso_t *lsop = cap_arg;
463 
464 		/* Check whether LSO is disabled */
465 		if (!sfxge_lso) {
466 			rc = ENOTSUP;
467 			goto fail1;
468 		}
469 
470 		DTRACE_PROBE(lso);
471 
472 		lsop->lso_flags = LSO_TX_BASIC_TCP_IPV4;
473 		lsop->lso_basic_tcp_ipv4.lso_max = TCP_MAX_LSO_LENGTH;
474 		break;
475 	}
476 	case MAC_CAPAB_HCKSUM: {
477 		uint32_t *hcksump = cap_arg;
478 
479 		DTRACE_PROBE(cksum);
480 
481 		*hcksump = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
482 		break;
483 	}
484 	default:
485 		rc = ENOTSUP;
486 		goto fail1;
487 	}
488 
489 	return (B_TRUE);
490 
491 fail1:
492 	DTRACE_PROBE1(fail1, int, rc);
493 
494 	return (B_FALSE);
495 }
496 
497 /*
498  * GLDv3 driver-private property names must be preceded by an underscore - see
499  * mc_getprop(9E).
500  */
501 #define	SFXGE_PRIV_PROP_NAME(s) ("_" #s)
502 
503 #define	SFXGE_XSTR(s) SFXGE_STR(s)
504 #define	SFXGE_STR(s) #s
505 
506 static void
507 sfxge_gld_priv_prop_info(sfxge_t *sp, const char *name,
508     mac_prop_info_handle_t handle)
509 {
510 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) {
511 		mac_prop_info_set_default_uint32(handle,
512 		    SFXGE_RX_COALESCE_OFF);
513 		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
514 		return;
515 	}
516 
517 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) {
518 		mac_prop_info_set_default_uint32(handle, ncpus);
519 		mac_prop_info_set_range_uint32(handle, 1,
520 		    (uint32_t)sp->s_intr.si_nalloc);
521 		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
522 		return;
523 	}
524 
525 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) {
526 		mac_prop_info_set_default_uint32(handle,
527 		    SFXGE_DEFAULT_MODERATION);
528 		mac_prop_info_set_range_uint32(handle,
529 		    0, efx_nic_cfg_get(sp->s_enp)->enc_evq_timer_max_us);
530 		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
531 		return;
532 	}
533 
534 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(mon_polling)) == 0) {
535 		mac_prop_info_set_default_uint8(handle, 0);
536 		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
537 		return;
538 	}
539 
540 #if EFSYS_OPT_MCDI_LOGGING
541 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(mcdi_logging)) == 0) {
542 		mac_prop_info_set_default_uint8(handle, 0);
543 		mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
544 		return;
545 	}
546 #endif
547 	DTRACE_PROBE(unknown_priv_prop);
548 }
549 
550 
551 static int
552 sfxge_gld_priv_prop_get(sfxge_t *sp, const char *name,
553     unsigned int size, void *valp)
554 {
555 	long val;
556 	int rc;
557 
558 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) {
559 		sfxge_rx_coalesce_mode_t mode;
560 
561 		sfxge_rx_coalesce_mode_get(sp, &mode);
562 
563 		val = (long)mode;
564 		goto done;
565 	}
566 
567 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) {
568 		unsigned int count;
569 
570 		if (sfxge_rx_scale_count_get(sp, &count) != 0)
571 			count = 0;
572 
573 		val = (long)count;
574 		goto done;
575 	}
576 
577 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) {
578 		unsigned int us;
579 
580 		sfxge_ev_moderation_get(sp, &us);
581 
582 		val = (long)us;
583 		goto done;
584 	}
585 
586 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(mon_polling)) == 0) {
587 		val = (long)sp->s_mon.sm_polling;
588 		goto done;
589 	}
590 
591 #if EFSYS_OPT_MCDI_LOGGING
592 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(mcdi_logging)) == 0) {
593 		val = (long)sp->s_mcdi_logging;
594 		goto done;
595 	}
596 #endif
597 
598 	rc = ENOTSUP;
599 	goto fail1;
600 
601 done:
602 	(void) snprintf(valp, size, "%ld", val);
603 
604 	return (0);
605 
606 fail1:
607 	DTRACE_PROBE1(fail1, int, rc);
608 
609 	return (rc);
610 }
611 
612 
613 static int
614 sfxge_gld_priv_prop_set(sfxge_t *sp, const char *name, unsigned int size,
615     const void *valp)
616 {
617 	long val;
618 	int rc = 0;
619 
620 	_NOTE(ARGUNUSED(size))
621 
622 	(void) ddi_strtol(valp, (char **)NULL, 0, &val);
623 
624 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) {
625 		if ((rc = sfxge_rx_coalesce_mode_set(sp,
626 		    (sfxge_rx_coalesce_mode_t)val)) != 0)
627 			goto fail1;
628 
629 		goto done;
630 	}
631 
632 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) {
633 		if ((rc = sfxge_rx_scale_count_set(sp, (unsigned int)val)) != 0)
634 			goto fail1;
635 
636 		goto done;
637 	}
638 
639 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) {
640 		if ((rc = sfxge_ev_moderation_set(sp, (unsigned int) val)) != 0)
641 			goto fail1;
642 
643 		goto done;
644 	}
645 
646 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(mon_polling)) == 0) {
647 		sp->s_mon.sm_polling = (int)val;
648 		goto done;
649 	}
650 
651 #if EFSYS_OPT_MCDI_LOGGING
652 	if (strcmp(name, SFXGE_PRIV_PROP_NAME(mcdi_logging)) == 0) {
653 		sp->s_mcdi_logging = (int)val;
654 		goto done;
655 	}
656 #endif
657 
658 
659 	rc = ENOTSUP;
660 	goto fail1;
661 
662 done:
663 	return (0);
664 
665 fail1:
666 	DTRACE_PROBE1(fail1, int, rc);
667 
668 	return (rc);
669 }
670 
671 
672 #if EFSYS_OPT_MCDI_LOGGING
673 #define	SFXGE_N_NAMED_PROPS	4
674 #else
675 #define	SFXGE_N_NAMED_PROPS	3
676 #endif
677 
678 static void
679 sfxge_gld_priv_prop_init(sfxge_t *sp)
680 {
681 	sfxge_mac_priv_prop_t *mac_priv_props;
682 	unsigned int nprops = 0;
683 
684 	/*
685 	 * We have named_props (3 or 4) named properties and the structure must
686 	 * be finished by a NULL pointer.
687 	 */
688 	sp->s_mac_priv_props_alloc = SFXGE_N_NAMED_PROPS + 1;
689 	sp->s_mac_priv_props = kmem_zalloc(sizeof (sfxge_mac_priv_prop_t) *
690 	    sp->s_mac_priv_props_alloc,
691 	    KM_SLEEP);
692 
693 	/*
694 	 * Driver-private property names start with an underscore - see
695 	 * mc_getprop(9E).
696 	 */
697 
698 	mac_priv_props = sp->s_mac_priv_props;
699 
700 	*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
701 	(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
702 	    SFXGE_PRIV_PROP_NAME(rx_coalesce_mode));
703 	mac_priv_props++;
704 	nprops++;
705 
706 	*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
707 	(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
708 	    SFXGE_PRIV_PROP_NAME(rx_scale_count));
709 	mac_priv_props++;
710 	nprops++;
711 
712 	*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
713 	(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
714 	    SFXGE_PRIV_PROP_NAME(intr_moderation));
715 	mac_priv_props++;
716 	nprops++;
717 
718 #if EFSYS_OPT_MCDI_LOGGING
719 	*mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP);
720 	(void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1,
721 	    SFXGE_PRIV_PROP_NAME(mcdi_logging));
722 	mac_priv_props++;
723 	nprops++;
724 #endif
725 
726 	ASSERT3U((nprops + 1), ==, sp->s_mac_priv_props_alloc);
727 
728 	/* Terminated by a NULL pointer */
729 	*mac_priv_props = NULL;
730 }
731 
732 static void
733 sfxge_gld_priv_prop_fini(sfxge_t *sp)
734 {
735 	char **mac_priv_props;
736 	unsigned int id;
737 
738 	mac_priv_props = sp->s_mac_priv_props;
739 
740 	for (id = 0; id < SFXGE_N_NAMED_PROPS; id++) {
741 		kmem_free(*mac_priv_props, MAXLINKPROPNAME);
742 		mac_priv_props++;
743 	}
744 
745 	kmem_free(sp->s_mac_priv_props, sizeof (sfxge_mac_priv_prop_t) *
746 	    sp->s_mac_priv_props_alloc);
747 	sp->s_mac_priv_props = NULL;
748 }
749 
750 
751 static int
752 sfxge_gld_getprop(void *arg, const char *name, mac_prop_id_t id,
753     unsigned int size, void *valp)
754 {
755 	sfxge_t *sp = arg;
756 	uint32_t flag = EFX_PHY_CAP_CURRENT;
757 	uint8_t *v8 = ((uint8_t *)valp);
758 	int rc;
759 
760 	/* check size */
761 	switch (id) {
762 	case MAC_PROP_DUPLEX:
763 		if (size < sizeof (link_duplex_t)) {
764 			rc = EINVAL;
765 			goto fail1;
766 		}
767 		break;
768 	case MAC_PROP_FLOWCTRL:
769 		if (size < sizeof (link_flowctrl_t)) {
770 			rc = EINVAL;
771 			goto fail1;
772 		}
773 		break;
774 	case MAC_PROP_SPEED:
775 	case MAC_PROP_STATUS:
776 		if (size < sizeof (uint64_t)) {
777 			rc = EINVAL;
778 			goto fail1;
779 		}
780 		break;
781 	case MAC_PROP_MTU:
782 		if (size < sizeof (uint32_t)) {
783 			rc = EINVAL;
784 			goto fail1;
785 		}
786 		break;
787 	case MAC_PROP_EN_AUTONEG:
788 	case MAC_PROP_AUTONEG:
789 	case MAC_PROP_EN_40GFDX_CAP:
790 	case MAC_PROP_ADV_40GFDX_CAP:
791 	case MAC_PROP_EN_10GFDX_CAP:
792 	case MAC_PROP_ADV_10GFDX_CAP:
793 	case MAC_PROP_EN_1000FDX_CAP:
794 	case MAC_PROP_ADV_1000FDX_CAP:
795 	case MAC_PROP_EN_1000HDX_CAP:
796 	case MAC_PROP_ADV_1000HDX_CAP:
797 	case MAC_PROP_EN_100FDX_CAP:
798 	case MAC_PROP_ADV_100FDX_CAP:
799 	case MAC_PROP_EN_100HDX_CAP:
800 	case MAC_PROP_ADV_100HDX_CAP:
801 	case MAC_PROP_EN_10FDX_CAP:
802 	case MAC_PROP_ADV_10FDX_CAP:
803 	case MAC_PROP_EN_10HDX_CAP:
804 	case MAC_PROP_ADV_10HDX_CAP:
805 		if (size < sizeof (uint8_t)) {
806 			rc = EINVAL;
807 			goto fail1;
808 		}
809 		break;
810 	case MAC_PROP_PRIVATE:
811 		/* sfxge_gld_priv_prop_get should do any size checking */
812 		break;
813 	default:
814 		rc = ENOTSUP;
815 		goto fail1;
816 	}
817 
818 	switch (id) {
819 	case MAC_PROP_DUPLEX: {
820 		sfxge_link_duplex_t duplex;
821 
822 		sfxge_mac_link_duplex_get(sp, &duplex);
823 
824 		switch (duplex) {
825 		case SFXGE_LINK_DUPLEX_UNKNOWN:
826 			*((link_duplex_t *)valp) = LINK_DUPLEX_UNKNOWN;
827 			break;
828 
829 		case SFXGE_LINK_DUPLEX_HALF:
830 			*((link_duplex_t *)valp) = LINK_DUPLEX_HALF;
831 			break;
832 
833 		case SFXGE_LINK_DUPLEX_FULL:
834 			*((link_duplex_t *)valp) = LINK_DUPLEX_FULL;
835 			break;
836 
837 		default:
838 			ASSERT(B_FALSE);
839 			break;
840 		}
841 
842 		break;
843 	}
844 	case MAC_PROP_SPEED: {
845 		unsigned int speed;
846 
847 		sfxge_mac_link_speed_get(sp, &speed);
848 
849 		*((uint64_t *)valp) = (uint64_t)speed * 1000000ull;
850 
851 		break;
852 	}
853 	case MAC_PROP_STATUS: {
854 		boolean_t up;
855 
856 		sfxge_mac_link_check(sp, &up);
857 
858 		*((link_state_t *)valp) = (up) ?
859 		    LINK_STATE_UP : LINK_STATE_DOWN;
860 
861 		break;
862 	}
863 	case MAC_PROP_EN_AUTONEG:
864 	case MAC_PROP_AUTONEG:
865 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_AN, NULL);
866 		break;
867 	case MAC_PROP_EN_40GFDX_CAP:
868 	case MAC_PROP_ADV_40GFDX_CAP:
869 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_40000FDX, NULL);
870 		break;
871 	case MAC_PROP_EN_10GFDX_CAP:
872 	case MAC_PROP_ADV_10GFDX_CAP:
873 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10000FDX, NULL);
874 		break;
875 	case MAC_PROP_EN_1000FDX_CAP:
876 	case MAC_PROP_ADV_1000FDX_CAP:
877 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000FDX, NULL);
878 		break;
879 	case MAC_PROP_EN_1000HDX_CAP:
880 	case MAC_PROP_ADV_1000HDX_CAP:
881 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000HDX, NULL);
882 		break;
883 	case MAC_PROP_EN_100FDX_CAP:
884 	case MAC_PROP_ADV_100FDX_CAP:
885 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100FDX, NULL);
886 		break;
887 	case MAC_PROP_EN_100HDX_CAP:
888 	case MAC_PROP_ADV_100HDX_CAP:
889 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100HDX, NULL);
890 		break;
891 	case MAC_PROP_EN_10FDX_CAP:
892 	case MAC_PROP_ADV_10FDX_CAP:
893 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10FDX, NULL);
894 		break;
895 	case MAC_PROP_EN_10HDX_CAP:
896 	case MAC_PROP_ADV_10HDX_CAP:
897 		*v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10HDX, NULL);
898 		break;
899 	case MAC_PROP_MTU:
900 		*((uint32_t *)valp) = (uint32_t)(sp->s_mtu);
901 		break;
902 
903 	case MAC_PROP_FLOWCTRL: {
904 		unsigned int fcntl;
905 
906 		sfxge_mac_fcntl_get(sp, &fcntl);
907 
908 		switch (fcntl) {
909 		case 0:
910 			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_NONE;
911 			break;
912 
913 		case EFX_FCNTL_GENERATE:
914 			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_RX;
915 			break;
916 
917 		case EFX_FCNTL_RESPOND:
918 			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_TX;
919 			break;
920 
921 		case (EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND):
922 			*((link_flowctrl_t *)valp) = LINK_FLOWCTRL_BI;
923 			break;
924 
925 		default:
926 			ASSERT(B_FALSE);
927 			break;
928 		}
929 		break;
930 	}
931 	case MAC_PROP_PRIVATE:
932 		if ((rc = sfxge_gld_priv_prop_get(sp, name, size, valp)) != 0)
933 			goto fail2;
934 		break;
935 	default:
936 		rc = ENOTSUP;
937 		goto fail3;
938 	}
939 
940 	return (0);
941 
942 fail3:
943 	DTRACE_PROBE(fail3);
944 
945 fail2:
946 	DTRACE_PROBE(fail2);
947 
948 fail1:
949 	DTRACE_PROBE1(fail1, int, rc);
950 
951 	return (rc);
952 }
953 
954 
955 static int
956 sfxge_gld_setprop(void *arg, const char *name, mac_prop_id_t id,
957     unsigned int size, const void *valp)
958 {
959 	sfxge_t *sp = arg;
960 	int v8 =  *(uint8_t *)valp;
961 	int rc;
962 
963 	/* get size checks out fo the way */
964 	switch (id) {
965 	/*
966 	 * On Sol11 (no updates) dladm seems to be using MAC_PROP_AUTONEG to set
967 	 * the autoneg parameter. This does not match the scheme suggested in
968 	 * mac(9E) but as they both map to the same think in the driver and in
969 	 * dladm it doesn't matter.
970 	 */
971 	case MAC_PROP_AUTONEG:
972 	case MAC_PROP_EN_AUTONEG:
973 	case MAC_PROP_EN_40GFDX_CAP:
974 	case MAC_PROP_EN_10GFDX_CAP:
975 	case MAC_PROP_EN_1000FDX_CAP:
976 	case MAC_PROP_EN_1000HDX_CAP:
977 	case MAC_PROP_EN_100FDX_CAP:
978 	case MAC_PROP_EN_100HDX_CAP:
979 	case MAC_PROP_EN_10FDX_CAP:
980 	case MAC_PROP_EN_10HDX_CAP:
981 		if (size < sizeof (uint8_t)) {
982 			rc = EINVAL;
983 			goto fail1;
984 		}
985 		break;
986 	case MAC_PROP_MTU:
987 		if (size < sizeof (uint32_t)) {
988 			rc = EINVAL;
989 			goto fail1;
990 		}
991 		break;
992 	case MAC_PROP_FLOWCTRL:
993 		if (size < sizeof (link_flowctrl_t)) {
994 			rc = EINVAL;
995 			goto fail1;
996 		}
997 		break;
998 	case MAC_PROP_PRIVATE:
999 		/* sfxge_gld_priv_prop_set should do any size checking */
1000 		break;
1001 	default:
1002 		rc = ENOTSUP;
1003 		goto fail1;
1004 	}
1005 
1006 	switch (id) {
1007 	/*
1008 	 * It is unclear which of MAC_PROP_AUTONEG and MAC_PROP_EN_AUTONEG is
1009 	 * used.  Try both.
1010 	 */
1011 	case MAC_PROP_AUTONEG:
1012 	case MAC_PROP_EN_AUTONEG:
1013 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_AN, v8)) != 0)
1014 			goto fail2;
1015 		break;
1016 	case MAC_PROP_EN_40GFDX_CAP:
1017 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_40000FDX, v8)) != 0)
1018 			goto fail2;
1019 		break;
1020 	case MAC_PROP_EN_10GFDX_CAP: {
1021 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10000FDX, v8)) != 0)
1022 			goto fail2;
1023 		break;
1024 	}
1025 	case MAC_PROP_EN_1000FDX_CAP: {
1026 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000FDX, v8)) != 0)
1027 			goto fail2;
1028 		break;
1029 	}
1030 	case MAC_PROP_EN_1000HDX_CAP: {
1031 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000HDX, v8)) != 0)
1032 			goto fail2;
1033 		break;
1034 	}
1035 	case MAC_PROP_EN_100FDX_CAP: {
1036 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100FDX, v8)) != 0)
1037 			goto fail2;
1038 		break;
1039 	}
1040 	case MAC_PROP_EN_100HDX_CAP: {
1041 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100HDX, v8)) != 0)
1042 			goto fail2;
1043 		break;
1044 	}
1045 	case MAC_PROP_EN_10FDX_CAP: {
1046 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10FDX, v8)) != 0)
1047 			goto fail2;
1048 		break;
1049 	}
1050 	case MAC_PROP_EN_10HDX_CAP: {
1051 		if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10HDX, v8)) != 0)
1052 			goto fail2;
1053 		break;
1054 	}
1055 	case MAC_PROP_MTU: {
1056 		size_t mtu = (size_t)(*((uint32_t *)valp));
1057 
1058 		if (mtu > EFX_MAC_SDU_MAX) {
1059 			rc = EINVAL;
1060 			goto fail2;
1061 		}
1062 
1063 		sp->s_mtu = mtu;
1064 
1065 		DTRACE_PROBE(restart_mtu);
1066 		(void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK,
1067 		    "MTU changing", (uint32_t)mtu);
1068 
1069 		break;
1070 	}
1071 	case MAC_PROP_FLOWCTRL: {
1072 		unsigned int fcntl = 0;
1073 
1074 		switch (*((link_flowctrl_t *)valp)) {
1075 		case LINK_FLOWCTRL_NONE:
1076 			fcntl = 0;
1077 			break;
1078 
1079 		case LINK_FLOWCTRL_RX:
1080 			fcntl = EFX_FCNTL_GENERATE;
1081 			break;
1082 
1083 		case LINK_FLOWCTRL_TX:
1084 			fcntl = EFX_FCNTL_RESPOND;
1085 			break;
1086 
1087 		case LINK_FLOWCTRL_BI:
1088 			fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND;
1089 			break;
1090 
1091 		default:
1092 			rc = EINVAL;
1093 			goto fail2;
1094 		}
1095 
1096 		if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0)
1097 			goto fail3;
1098 
1099 		break;
1100 	}
1101 	case MAC_PROP_PRIVATE:
1102 		if ((rc = sfxge_gld_priv_prop_set(sp, name, size, valp)) != 0)
1103 			goto fail4;
1104 
1105 		break;
1106 	default:
1107 		rc = ENOTSUP;
1108 		goto fail5;
1109 	}
1110 
1111 	return (0);
1112 
1113 fail5:
1114 	DTRACE_PROBE(fail5);
1115 
1116 fail4:
1117 	DTRACE_PROBE(fail4);
1118 
1119 fail3:
1120 	DTRACE_PROBE(fail3);
1121 
1122 fail2:
1123 	DTRACE_PROBE(fail2);
1124 
1125 fail1:
1126 	DTRACE_PROBE1(fail1, int, rc);
1127 
1128 	return (rc);
1129 }
1130 
1131 static void
1132 sfxge_gld_propinfo(void *arg, const char *name, mac_prop_id_t id,
1133     mac_prop_info_handle_t handle)
1134 {
1135 	sfxge_t *sp = arg;
1136 	efx_phy_cap_type_t phy_cap = EFX_PHY_CAP_INVALID;
1137 	switch (id) {
1138 		case MAC_PROP_DUPLEX:
1139 			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
1140 			return;
1141 		case MAC_PROP_FLOWCTRL:
1142 			mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
1143 			mac_prop_info_set_default_link_flowctrl(handle,
1144 			    LINK_FLOWCTRL_BI);
1145 			return;
1146 		case MAC_PROP_SPEED:
1147 			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
1148 			return;
1149 		case MAC_PROP_STATUS:
1150 			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
1151 			return;
1152 		case MAC_PROP_MTU: {
1153 			uint32_t mtu_default;
1154 			mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
1155 			mtu_default = ddi_prop_get_int(DDI_DEV_T_ANY,
1156 			    sp->s_dip, DDI_PROP_DONTPASS, "mtu", ETHERMTU);
1157 			mac_prop_info_set_default_uint32(handle, mtu_default);
1158 			return;
1159 			}
1160 		case MAC_PROP_PRIVATE:
1161 			sfxge_gld_priv_prop_info(sp, name, handle);
1162 			return;
1163 		case MAC_PROP_EN_AUTONEG:
1164 		case MAC_PROP_AUTONEG:
1165 			phy_cap = EFX_PHY_CAP_AN;
1166 			break;
1167 		case MAC_PROP_EN_10GFDX_CAP:
1168 		case MAC_PROP_ADV_10GFDX_CAP:
1169 			phy_cap = EFX_PHY_CAP_10000FDX;
1170 			break;
1171 		case MAC_PROP_EN_1000FDX_CAP:
1172 		case MAC_PROP_ADV_1000FDX_CAP:
1173 			phy_cap = EFX_PHY_CAP_1000FDX;
1174 			break;
1175 		case MAC_PROP_EN_1000HDX_CAP:
1176 		case MAC_PROP_ADV_1000HDX_CAP:
1177 			phy_cap = EFX_PHY_CAP_1000HDX;
1178 			break;
1179 		case MAC_PROP_EN_100FDX_CAP:
1180 		case MAC_PROP_ADV_100FDX_CAP:
1181 			phy_cap = EFX_PHY_CAP_100FDX;
1182 			break;
1183 		case MAC_PROP_EN_100HDX_CAP:
1184 		case MAC_PROP_ADV_100HDX_CAP:
1185 			phy_cap = EFX_PHY_CAP_100HDX;
1186 			break;
1187 		case MAC_PROP_EN_10FDX_CAP:
1188 		case MAC_PROP_ADV_10FDX_CAP:
1189 			phy_cap = EFX_PHY_CAP_10FDX;
1190 			break;
1191 		case MAC_PROP_EN_10HDX_CAP:
1192 		case MAC_PROP_ADV_10HDX_CAP:
1193 			phy_cap = EFX_PHY_CAP_10HDX;
1194 			break;
1195 		default:
1196 			DTRACE_PROBE(unknown_prop);
1197 			return;
1198 	}
1199 	if (phy_cap != EFX_PHY_CAP_INVALID) {
1200 		boolean_t rw;
1201 		uint8_t cap_default;
1202 		cap_default = sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT,
1203 		    phy_cap, &rw);
1204 		if (rw == B_TRUE)
1205 			mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW);
1206 		else
1207 			mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ);
1208 		mac_prop_info_set_default_uint8(handle, cap_default);
1209 	}
1210 }
1211 
1212 int
1213 sfxge_gld_register(sfxge_t *sp)
1214 {
1215 	mac_callbacks_t *mcp;
1216 	mac_register_t *mrp;
1217 	mac_handle_t mh;
1218 	uint8_t addr[ETHERADDRL];
1219 	int rc;
1220 
1221 	if ((mrp = mac_alloc(MAC_VERSION)) == NULL) {
1222 		rc = ENOTSUP;
1223 		goto fail1;
1224 	}
1225 
1226 	mrp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1227 	mrp->m_driver = sp;
1228 	mrp->m_dip = sp->s_dip;
1229 
1230 	/* Set up the callbacks */
1231 	mcp = &(sp->s_mc);
1232 	bzero(mcp, sizeof (mac_callbacks_t));
1233 
1234 	mcp->mc_getstat = sfxge_gld_getstat;
1235 	mcp->mc_start = sfxge_gld_start;
1236 	mcp->mc_stop = sfxge_gld_stop;
1237 	mcp->mc_setpromisc = sfxge_gld_setpromisc;
1238 	mcp->mc_multicst = sfxge_gld_multicst;
1239 	mcp->mc_unicst = sfxge_gld_unicst;
1240 	mcp->mc_tx = sfxge_gld_tx;
1241 
1242 	mcp->mc_callbacks |= MC_IOCTL;
1243 	mcp->mc_ioctl = sfxge_gld_ioctl;
1244 
1245 	mcp->mc_callbacks |= MC_GETCAPAB;
1246 	mcp->mc_getcapab = sfxge_gld_getcapab;
1247 
1248 	mcp->mc_callbacks |= MC_SETPROP;
1249 	mcp->mc_setprop = sfxge_gld_setprop;
1250 
1251 	mcp->mc_callbacks |= MC_GETPROP;
1252 	mcp->mc_getprop = sfxge_gld_getprop;
1253 
1254 	mcp->mc_callbacks |= MC_PROPINFO;
1255 	mcp->mc_propinfo = sfxge_gld_propinfo;
1256 
1257 	mrp->m_callbacks = mcp;
1258 
1259 	mrp->m_src_addr = addr;
1260 
1261 	if ((rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_BIA,
1262 	    mrp->m_src_addr)) != 0)
1263 		goto fail2;
1264 
1265 	mrp->m_min_sdu = 0;
1266 	mrp->m_max_sdu = sp->s_mtu;
1267 
1268 	mrp->m_margin = VLAN_TAGSZ;
1269 
1270 	/* Set up the private properties */
1271 	/* NOTE: m_priv_props added in s10u9 */
1272 	mrp->m_priv_props = sp->s_mac_priv_props;
1273 	sfxge_gld_priv_prop_init(sp);
1274 
1275 	/* NOTE: m_flags added in s11.0 */
1276 	/* NOTE: m_multicast_sdu added in s11.0 */
1277 
1278 	/* Register the interface */
1279 	if ((rc = mac_register(mrp, &mh)) != 0)
1280 		goto fail3;
1281 
1282 	/* Free the stack registration object */
1283 	kmem_free(mrp, sizeof (mac_register_t));
1284 
1285 	sp->s_mh = mh;
1286 
1287 	return (0);
1288 fail3:
1289 	DTRACE_PROBE(fail3);
1290 fail2:
1291 	DTRACE_PROBE(fail2);
1292 
1293 	/* Free the stack registration object */
1294 	mac_free(mrp);
1295 
1296 	/* Tear down the private properties */
1297 	sfxge_gld_priv_prop_fini(sp);
1298 
1299 	/* Clear the callbacks */
1300 	bzero(&(sp->s_mc), sizeof (mac_callbacks_t));
1301 
1302 fail1:
1303 	DTRACE_PROBE1(fail1, int, rc);
1304 
1305 	return (rc);
1306 }
1307 
1308 int
1309 sfxge_gld_unregister(sfxge_t *sp)
1310 {
1311 	mac_handle_t mh = sp->s_mh;
1312 	int rc;
1313 
1314 	if ((rc = mac_unregister(mh)) != 0)
1315 		goto fail1;
1316 
1317 	sp->s_mh = NULL;
1318 
1319 	/* Tear down the private properties */
1320 	sfxge_gld_priv_prop_fini(sp);
1321 
1322 	/* Clear the callbacks */
1323 	bzero(&(sp->s_mc), sizeof (mac_callbacks_t));
1324 
1325 	return (0);
1326 
1327 fail1:
1328 	DTRACE_PROBE1(fail1, int, rc);
1329 
1330 	return (rc);
1331 }
1332