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