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
sfxge_gld_link_update(sfxge_t * sp)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
sfxge_gld_mtu_update(sfxge_t * sp)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
sfxge_gld_rx_post(sfxge_t * sp,unsigned int index,mblk_t * mp)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
sfxge_gld_rx_push(sfxge_t * sp)87 sfxge_gld_rx_push(sfxge_t *sp)
88 {
89 _NOTE(ARGUNUSED(sp))
90 }
91
92
93 static uint64_t
sfxge_phy_dfl_cap_test64(sfxge_t * sp,uint32_t field)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
sfxge_phy_cur_cap_test64(sfxge_t * sp,uint32_t field)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
sfxge_phy_lp_cap_test64(sfxge_t * sp,uint32_t field)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
sfxge_gld_getstat(void * arg,unsigned int id,uint64_t * valp)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
sfxge_gld_start(void * arg)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
sfxge_gld_stop(void * arg)355 sfxge_gld_stop(void *arg)
356 {
357 sfxge_t *sp = arg;
358
359 sfxge_stop(sp);
360 }
361
362 static int
sfxge_gld_setpromisc(void * arg,boolean_t on)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
sfxge_gld_multicst(void * arg,boolean_t add,const uint8_t * addr)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
sfxge_gld_unicst(void * arg,const uint8_t * addr)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
sfxge_gld_ioctl(void * arg,queue_t * wq,mblk_t * mp)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 *
sfxge_gld_tx(void * arg,mblk_t * mp)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
sfxge_gld_getcapab(void * arg,mac_capab_t cap,void * cap_arg)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
sfxge_gld_priv_prop_info(sfxge_t * sp,const char * name,mac_prop_info_handle_t handle)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
sfxge_gld_priv_prop_get(sfxge_t * sp,const char * name,unsigned int size,void * valp)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
sfxge_gld_priv_prop_set(sfxge_t * sp,const char * name,unsigned int size,const void * valp)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
sfxge_gld_priv_prop_init(sfxge_t * sp)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
sfxge_gld_priv_prop_fini(sfxge_t * sp)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
sfxge_gld_getprop(void * arg,const char * name,mac_prop_id_t id,unsigned int size,void * valp)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
sfxge_gld_setprop(void * arg,const char * name,mac_prop_id_t id,unsigned int size,const void * valp)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
sfxge_gld_propinfo(void * arg,const char * name,mac_prop_id_t id,mac_prop_info_handle_t handle)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
sfxge_gld_register(sfxge_t * sp)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
sfxge_gld_unregister(sfxge_t * sp)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