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