xref: /illumos-gate/usr/src/uts/common/io/bnxe/bnxe_gld.c (revision 533affcbc7fc4d0c8132976ea454aaa715fe2307)
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 2014 QLogic Corporation
24  * The contents of this file are subject to the terms of the
25  * QLogic End User License (the "License").
26  * You may not use this file except in compliance with the License.
27  *
28  * You can obtain a copy of the License at
29  * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
30  * QLogic_End_User_Software_License.txt
31  * See the License for the specific language governing permissions
32  * and limitations under the License.
33  */
34 
35 /*
36  * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
37  * Copyright (c) 2017, Joyent, Inc.
38  * Copyright 2023 Oxide Computer Company
39  */
40 
41 #include "bnxe.h"
42 
43 #include <sys/mac.h>
44 #include <sys/mac_ether.h>
45 #include <sys/dlpi.h>
46 
47 #if !(defined(__S11) || defined(__S12))
48 #define mri_driver  mr_driver
49 #define mri_start   mr_start
50 #define mri_stop    mr_stop
51 #define mri_intr    mr_intr
52 #define mri_poll    mr_poll
53 #define mri_tx      mr_send
54 #define mgi_driver  mrg_driver
55 #define mgi_start   mrg_start
56 #define mgi_stop    mrg_stop
57 #define mgi_count   mrg_count
58 #define mgi_addmac  mrg_addmac
59 #define mgi_remmac  mrg_addmac
60 #define mr_gaddring mr_gadd_ring
61 #define mr_gremring mr_grem_ring
62 #endif /* not __S11 or __S12 */
63 
64 /*
65  * Reconfiguring the network devices parameters require net_config
66  * privilege starting Solaris 10.  Only root user is allowed to
67  * update device parameter in Solaris 9 and earlier version. Following
68  * declaration allows single binary image to run on all OS versions.
69  */
70 extern int secpolicy_net_config(const cred_t *, boolean_t);
71 extern int drv_priv(cred_t *);
72 #pragma weak secpolicy_net_config
73 #pragma weak drv_priv
74 
75 #ifdef MC_SETPROP
76 
77 char * bnxeLink_priv_props[] =
78 {
79     "_adv_2500fdx_cap",
80     "_en_2500fdx_cap",
81     "_adv_txpause_cap",
82     "_en_txpause_cap",
83     "_txpause",
84     "_adv_rxpause_cap",
85     "_en_rxpause_cap",
86     "_rxpause",
87     "_autoneg_flow",
88     "_checksum",
89     "_num_rings",
90     "_rx_descs",
91     "_rx_free_reclaim",
92     "_rx_copy_threshold",
93     "_tx_descs",
94     "_tx_free_reclaim",
95     "_tx_copy_threshold",
96     "_tx_ring_policy",
97     "_interrupt_coalesce",
98     "_rx_interrupt_coalesce_usec",
99     "_tx_interrupt_coalesce_usec",
100     "_disable_msix",
101     "_l2_fw_flow_ctrl",
102     "_autogreeen_enable",
103     "_lso_enable",
104     "_log_enable",
105     "_fcoe_enable",
106     NULL
107 };
108 
109 #endif /* MC_SETPROP */
110 
111 
112 static int BnxeMacStats(void *     pArg,
113                         uint_t     stat,
114                         uint64_t * pVal)
115 {
116     um_device_t * pUM = (um_device_t *)pArg;
117     lm_device_t * pLM;
118     b10_l2_chip_statistics_t b10_l2_stats;
119     int idx, rc = 0;
120 
121     if ((pUM == NULL) || (pVal == NULL))
122     {
123         return EINVAL;
124     }
125 
126     pLM = &pUM->lm_dev;
127 
128     BNXE_LOCK_ENTER_GLD(pUM);
129 
130     if (!pUM->plumbed)
131     {
132         BNXE_LOCK_EXIT_GLD(pUM);
133         return EAGAIN;
134     }
135 
136     *pVal = 0;
137 
138     switch (stat)
139     {
140     case MAC_STAT_IFSPEED:
141         *pVal = (pUM->props.link_speed * 1000000ULL);
142         break;
143 
144     case MAC_STAT_MULTIRCV:
145         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
146                                    L2_CHIP_STATISTICS_VER_NUM_1);
147         *pVal = b10_l2_stats.IfHCInMulticastPkts;
148         break;
149 
150     case MAC_STAT_BRDCSTRCV:
151         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
152                                    L2_CHIP_STATISTICS_VER_NUM_1);
153         *pVal = b10_l2_stats.IfHCInBroadcastPkts;
154         break;
155 
156     case MAC_STAT_MULTIXMT:
157         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
158                                    L2_CHIP_STATISTICS_VER_NUM_1);
159         *pVal = b10_l2_stats.IfHCOutMulticastPkts;
160         break;
161 
162     case MAC_STAT_BRDCSTXMT:
163         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
164                                    L2_CHIP_STATISTICS_VER_NUM_1);
165         *pVal = b10_l2_stats.IfHCOutBroadcastPkts;
166         break;
167 
168     case MAC_STAT_NORCVBUF:
169         lm_get_stats(pLM, LM_STATS_RCV_NO_BUFFER_DROP, (u64_t *)pVal);
170         break;
171 
172     case MAC_STAT_NOXMTBUF:
173         *pVal = 0;
174         LM_FOREACH_TSS_IDX(pLM, idx)
175         {
176             *pVal += pUM->txq[idx].txRecycle;
177         }
178         break;
179 
180     case MAC_STAT_IERRORS:
181     case ETHER_STAT_MACRCV_ERRORS:
182         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
183                                    L2_CHIP_STATISTICS_VER_NUM_1);
184         *pVal = b10_l2_stats.IfInErrors;
185         break;
186 
187     case MAC_STAT_OERRORS:
188         /* XXX not available */
189         break;
190 
191     case MAC_STAT_COLLISIONS:
192         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
193                                    L2_CHIP_STATISTICS_VER_NUM_1);
194         *pVal = b10_l2_stats.EtherStatsCollisions;
195         break;
196 
197     case MAC_STAT_RBYTES:
198         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
199                                    L2_CHIP_STATISTICS_VER_NUM_1);
200         *pVal = b10_l2_stats.IfHCInOctets;
201         break;
202 
203     case MAC_STAT_IPACKETS:
204         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
205                                    L2_CHIP_STATISTICS_VER_NUM_1);
206         *pVal = b10_l2_stats.IfHCInPkts;
207         break;
208 
209     case MAC_STAT_OBYTES:
210         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
211                                    L2_CHIP_STATISTICS_VER_NUM_1);
212         *pVal = b10_l2_stats.IfHCOutOctets;
213         break;
214 
215     case MAC_STAT_OPACKETS:
216         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
217                                    L2_CHIP_STATISTICS_VER_NUM_1);
218         *pVal = b10_l2_stats.IfHCOutPkts;
219         break;
220 
221     case ETHER_STAT_ALIGN_ERRORS:
222         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
223                                    L2_CHIP_STATISTICS_VER_NUM_1);
224         *pVal = b10_l2_stats.Dot3StatsAlignmentErrors;
225         break;
226 
227     case ETHER_STAT_FCS_ERRORS:
228         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
229                                    L2_CHIP_STATISTICS_VER_NUM_1);
230         *pVal = b10_l2_stats.Dot3StatsFCSErrors;
231         break;
232 
233     case ETHER_STAT_FIRST_COLLISIONS:
234         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
235                                    L2_CHIP_STATISTICS_VER_NUM_1);
236         *pVal = b10_l2_stats.Dot3StatsSingleCollisionFrames;
237         break;
238 
239     case ETHER_STAT_MULTI_COLLISIONS:
240         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
241                                    L2_CHIP_STATISTICS_VER_NUM_1);
242         *pVal = b10_l2_stats.Dot3StatsMultipleCollisionFrames;
243         break;
244 
245     case ETHER_STAT_DEFER_XMTS:
246         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
247                                    L2_CHIP_STATISTICS_VER_NUM_1);
248         *pVal = b10_l2_stats.Dot3StatsDeferredTransmissions;
249         break;
250 
251     case ETHER_STAT_TX_LATE_COLLISIONS:
252         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
253                                    L2_CHIP_STATISTICS_VER_NUM_1);
254         *pVal = b10_l2_stats.Dot3StatsLateCollisions;
255         break;
256 
257     case ETHER_STAT_EX_COLLISIONS:
258         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
259                                    L2_CHIP_STATISTICS_VER_NUM_1);
260         *pVal = b10_l2_stats.Dot3StatsExcessiveCollisions;
261         break;
262 
263     case ETHER_STAT_MACXMT_ERRORS:
264         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
265                                    L2_CHIP_STATISTICS_VER_NUM_1);
266         *pVal = b10_l2_stats.Dot3StatsInternalMacTransmitErrors;
267         break;
268 
269     case ETHER_STAT_CARRIER_ERRORS:
270         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
271                                    L2_CHIP_STATISTICS_VER_NUM_1);
272         *pVal = b10_l2_stats.Dot3StatsCarrierSenseErrors;
273         break;
274 
275     case ETHER_STAT_TOOLONG_ERRORS:
276         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
277                                    L2_CHIP_STATISTICS_VER_NUM_1);
278         *pVal = b10_l2_stats.EtherStatsOverrsizePkts;
279         break;
280 
281 #if (MAC_VERSION > 1)
282     case ETHER_STAT_TOOSHORT_ERRORS:
283         lm_stats_get_l2_chip_stats(pLM, &b10_l2_stats,
284                                    L2_CHIP_STATISTICS_VER_NUM_1);
285         *pVal = b10_l2_stats.EtherStatsUndersizePkts;
286         break;
287 #endif
288 
289     case ETHER_STAT_XCVR_ADDR:
290         *pVal = pLM->vars.phy_addr;
291         break;
292 
293     case ETHER_STAT_XCVR_ID:
294         *pVal = 0;
295         break;
296 
297     case ETHER_STAT_XCVR_INUSE:
298 	*pVal = (uint64_t)bnxe_phy_to_media(pUM);
299         break;
300 
301 #if (MAC_VERSION > 1)
302     case ETHER_STAT_CAP_10GFDX:
303         *pVal = 1;
304         break;
305 #endif
306 
307     case ETHER_STAT_CAP_1000FDX:
308         *pVal = 1;
309         break;
310 
311 #if 0
312     case ETHER_STAT_CAP_1000HDX:
313         //*pVal = linkconf->param_1000hdx;
314         *pVal = 0;
315         break;
316 #endif
317 
318     case ETHER_STAT_CAP_100FDX:
319         //*pVal = linkconf->param_100fdx;
320         *pVal = 1;
321         break;
322 
323     case ETHER_STAT_CAP_100HDX:
324         //*pVal = linkconf->param_100hdx;
325         *pVal = 1;
326         break;
327 
328     case ETHER_STAT_CAP_10FDX:
329         //*pVal = linkconf->param_10fdx;
330         *pVal = 1;
331         break;
332 
333     case ETHER_STAT_CAP_10HDX:
334         //*pVal = linkconf->param_10hdx;
335         *pVal = 1;
336         break;
337 
338     case ETHER_STAT_CAP_ASMPAUSE:
339         *pVal = 1;
340         break;
341 
342     case ETHER_STAT_CAP_PAUSE:
343         *pVal = 1;
344         break;
345 
346     case ETHER_STAT_CAP_AUTONEG:
347         *pVal = 1;
348         break;
349 
350 #if (MAC_VERSION > 1)
351     case ETHER_STAT_CAP_REMFAULT:
352         *pVal = 1;
353         break;
354 #endif
355 
356 #if (MAC_VERSION > 1)
357     case ETHER_STAT_ADV_CAP_10GFDX:
358         *pVal = pUM->curcfg.lnkcfg.param_10000fdx;
359         break;
360 #endif
361 
362     case ETHER_STAT_ADV_CAP_1000FDX:
363         *pVal = pUM->curcfg.lnkcfg.param_1000fdx;
364         break;
365 
366 #if 0
367     case ETHER_STAT_ADV_CAP_1000HDX:
368         //*pVal = pUM->curcfg.lnkcfg.param_1000hdx;
369         *pVal = 0;
370         break;
371 #endif
372 
373     case ETHER_STAT_ADV_CAP_100FDX:
374         *pVal = pUM->curcfg.lnkcfg.param_100fdx;
375         break;
376 
377     case ETHER_STAT_ADV_CAP_100HDX:
378         *pVal = pUM->curcfg.lnkcfg.param_100hdx;
379         break;
380 
381     case ETHER_STAT_ADV_CAP_10FDX:
382         *pVal = pUM->curcfg.lnkcfg.param_10fdx;
383         break;
384 
385     case ETHER_STAT_ADV_CAP_10HDX:
386         *pVal = pUM->curcfg.lnkcfg.param_10hdx;
387         break;
388 
389     case ETHER_STAT_ADV_CAP_ASMPAUSE:
390         *pVal = 1;
391         break;
392 
393     case ETHER_STAT_ADV_CAP_PAUSE:
394         *pVal = 1;
395         break;
396 
397     case ETHER_STAT_ADV_CAP_AUTONEG:
398         *pVal = pUM->curcfg.lnkcfg.link_autoneg;
399         break;
400 
401 #if (MAC_VERSION > 1)
402     case ETHER_STAT_ADV_REMFAULT:
403         *pVal = 1;
404         break;
405 #endif
406 
407 #if 0 /* LP caps not supported */
408 #if (MAC_VERSION > 1)
409     case ETHER_STAT_LP_CAP_10GFDX:
410         *pVal = pUM->remote.param_10000fdx;
411         break;
412 #endif
413 
414     case ETHER_STAT_LP_CAP_1000FDX:
415         *pVal = pUM->remote.param_1000fdx;
416         break;
417 
418 #if 0
419     case ETHER_STAT_LP_CAP_1000HDX:
420         //*pVal = pUM->remote.param_1000hdx;
421         *pVal = 0;
422         break;
423 #endif
424 
425     case ETHER_STAT_LP_CAP_100FDX:
426         *pVal = pUM->remote.param_100fdx;
427         break;
428 
429     case ETHER_STAT_LP_CAP_100HDX:
430         *pVal = pUM->remote.param_100hdx;
431         break;
432 
433     case ETHER_STAT_LP_CAP_10FDX:
434         *pVal = pUM->remote.param_10fdx;
435         break;
436 
437     case ETHER_STAT_LP_CAP_10HDX:
438         *pVal = pUM->remote.param_10hdx;
439         break;
440 
441 #if 0
442     case ETHER_STAT_LP_CAP_ASMPAUSE:
443         /* XXX implement LP_ASYM_PAUSE stat */
444         break;
445 
446     case ETHER_STAT_LP_CAP_PAUSE:
447         /* XXX implement LP_PAUSE stat */
448         break;
449 #endif
450 
451     case ETHER_STAT_LP_CAP_AUTONEG:
452         *pVal = pUM->remote.link_autoneg;
453         break;
454 
455     case ETHER_STAT_LP_REMFAULT:
456         /* XXX implement LP_REMFAULT stat */
457         break;
458 #endif /* LP caps not supported */
459 
460 #if 0
461     case ETHER_STAT_LINK_ASMPAUSE:
462         /* XXX implement ASMPAUSE stat */
463         break;
464 
465     case ETHER_STAT_LINK_PAUSE:
466         /* XXX implement PAUSE stat */
467         break;
468 #endif
469 
470     case ETHER_STAT_LINK_AUTONEG:
471         *pVal = pUM->curcfg.lnkcfg.link_autoneg;
472         break;
473 
474     case ETHER_STAT_LINK_DUPLEX:
475         *pVal = (pUM->props.link_duplex == B_TRUE) ?
476                     LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
477         break;
478 
479     default:
480         rc = ENOTSUP;
481     }
482 
483     BNXE_LOCK_EXIT_GLD(pUM);
484 
485     return rc;
486 }
487 
488 
489 
490 /*
491  * This routine is called by GLD to enable device for packet reception and
492  * enable interrupts.
493  */
494 static int BnxeMacStart(void * pArg)
495 {
496     um_device_t * pUM = (um_device_t *)pArg;
497 
498     BNXE_LOCK_ENTER_GLD(pUM);
499 
500     if (pUM->plumbed)
501     {
502         /* already started */
503         BNXE_LOCK_EXIT_GLD(pUM);
504         return EAGAIN;
505     }
506 
507     /* Always report the initial link state as unknown. */
508     mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN);
509 
510     if (BnxeHwStartL2(pUM))
511     {
512         BNXE_LOCK_EXIT_GLD(pUM);
513         return EIO;
514     }
515 
516     atomic_swap_32(&pUM->plumbed, B_TRUE);
517 
518     mutex_enter(&bnxeLoaderMutex);
519     bnxeNumPlumbed++;
520     mutex_exit(&bnxeLoaderMutex);
521 
522     BNXE_LOCK_EXIT_GLD(pUM);
523 
524     return 0;
525 }
526 
527 
528 /*
529  * This routine stops packet reception by clearing RX MASK register.  Also
530  * interrupts are disabled for this device.
531  */
532 static void BnxeMacStop(void * pArg)
533 {
534     um_device_t * pUM = (um_device_t *)pArg;
535 
536     BNXE_LOCK_ENTER_GLD(pUM);
537 
538     if (pUM->plumbed)
539     {
540         atomic_swap_32(&pUM->plumbed, B_FALSE);
541 
542         BnxeHwStopL2(pUM);
543 
544         /* Report the link state back to unknown. */
545         mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN);
546 
547         mutex_enter(&bnxeLoaderMutex);
548         bnxeNumPlumbed--;
549         mutex_exit(&bnxeLoaderMutex);
550     }
551 
552     BNXE_LOCK_EXIT_GLD(pUM);
553 }
554 
555 /* (flag) TRUE = on, FALSE = off */
556 static int BnxeMacPromiscuous(void *    pArg,
557                               boolean_t flag)
558 {
559     um_device_t * pUM = (um_device_t *)pArg;
560 
561     BNXE_LOCK_ENTER_GLD(pUM);
562 
563     if (!pUM->plumbed)
564     {
565         BNXE_LOCK_EXIT_GLD(pUM);
566         return EAGAIN;
567     }
568 
569     if (flag)
570     {
571         pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] |=
572             LM_RX_MASK_PROMISCUOUS_MODE;
573     }
574     else
575     {
576         pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] &=
577             ~LM_RX_MASK_PROMISCUOUS_MODE;
578     }
579 
580     BNXE_LOCK_ENTER_HWINIT(pUM);
581 
582     if (BnxeRxMask(pUM, LM_CLI_IDX_NDIS,
583                    pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS]) < 0)
584     {
585         BNXE_LOCK_EXIT_HWINIT(pUM);
586         BNXE_LOCK_EXIT_GLD(pUM);
587         return ECANCELED;
588     }
589 
590     BNXE_LOCK_EXIT_HWINIT(pUM);
591 
592     BNXE_LOCK_EXIT_GLD(pUM);
593 
594     return 0;
595 }
596 
597 
598 /*
599  * This function is used to enable or disable multicast packet reception for
600  * particular multicast addresses.
601  * (flag) TRUE = add, FALSE = remove
602  */
603 static int BnxeMacMulticast(void *          pArg,
604                             boolean_t       flag,
605                             const uint8_t * pMcastAddr)
606 {
607     um_device_t * pUM = (um_device_t *)pArg;
608     int rc;
609 
610     BNXE_LOCK_ENTER_GLD(pUM);
611 
612     if (!pUM->plumbed)
613     {
614         BNXE_LOCK_EXIT_GLD(pUM);
615         return EAGAIN;
616     }
617 
618     BNXE_LOCK_ENTER_HWINIT(pUM);
619     rc = BnxeMulticast(pUM, LM_CLI_IDX_NDIS, flag, pMcastAddr, B_TRUE);
620     BNXE_LOCK_EXIT_HWINIT(pUM);
621 
622     BNXE_LOCK_EXIT_GLD(pUM);
623 
624     return rc;
625 }
626 
627 
628 #ifdef BNXE_RINGS
629 
630 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
631 static int BnxeRxRingGroupAddMac(void *          groupHandle,
632                                  const uint8_t * pMacAddr,
633                                  uint64_t        flags)
634 #else
635 static int BnxeRxRingGroupAddMac(void *          groupHandle,
636                                  const uint8_t * pMacAddr)
637 #endif
638 {
639     RxQueueGroup * pRxQGroup = (RxQueueGroup *)groupHandle;
640     um_device_t *  pUM       = (um_device_t *)pRxQGroup->pUM;
641     //u32_t          idx       = pRxQGroup->idx;
642     int rc;
643 
644 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
645     _NOTE(ARGUNUSED(flags))
646 #endif
647 
648     BNXE_LOCK_ENTER_GLD(pUM);
649 
650     if (!pUM->plumbed)
651     {
652         BNXE_LOCK_EXIT_GLD(pUM);
653         return ECANCELED;
654     }
655 
656     /* Validate MAC address */
657     if (IS_ETH_MULTICAST(pMacAddr))
658     {
659         BnxeLogWarn(pUM, "Cannot program a mcast/bcast address as a MAC Address.");
660         BNXE_LOCK_EXIT_GLD(pUM);
661         return EINVAL;
662     }
663 
664     if (pUM->ucastTableLen == LM_MAX_UC_TABLE_SIZE)
665     {
666         BNXE_LOCK_EXIT_GLD(pUM);
667         return ENOMEM;
668     }
669 
670     BNXE_LOCK_ENTER_HWINIT(pUM);
671 
672     COPY_ETH_ADDRESS(pMacAddr, pUM->lm_dev.params.mac_addr);
673 
674     rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE,
675                         pUM->lm_dev.params.mac_addr);
676 
677     BNXE_LOCK_EXIT_HWINIT(pUM);
678 
679     if (rc < 0)
680     {
681         BNXE_LOCK_EXIT_GLD(pUM);
682         return ECANCELED;
683     }
684 
685     pUM->ucastTableLen++;
686 
687     BNXE_LOCK_EXIT_GLD(pUM);
688     return 0;
689 }
690 
691 
692 static int BnxeRxRingGroupRemMac(void *          groupHandle,
693                                  const uint8_t * pMacAddr)
694 {
695     RxQueueGroup * pRxQGroup = (RxQueueGroup *)groupHandle;
696     um_device_t *  pUM       = (um_device_t *)pRxQGroup->pUM;
697     //u32_t          idx       = pRxQGroup->idx;
698     int rc;
699 
700     BNXE_LOCK_ENTER_GLD(pUM);
701 
702     if (!pUM->plumbed)
703     {
704         BNXE_LOCK_EXIT_GLD(pUM);
705         return ECANCELED;
706     }
707 
708     if (pUM->ucastTableLen == 0)
709     {
710         BNXE_LOCK_EXIT_GLD(pUM);
711         return EINVAL;
712     }
713 
714     BNXE_LOCK_ENTER_HWINIT(pUM);
715 
716     if (!IS_ETH_ADDRESS_EQUAL(pMacAddr, pUM->lm_dev.params.mac_addr))
717     {
718         BnxeLogWarn(pUM, "Deleting MAC address that doesn't match default");
719         /* XXX */
720     }
721 
722     rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_FALSE,
723                         pUM->lm_dev.params.mac_addr);
724 
725     memset(pUM->lm_dev.params.mac_addr, 0, sizeof(pUM->lm_dev.params.mac_addr));
726 
727     BNXE_LOCK_EXIT_HWINIT(pUM);
728 
729     if (rc < 0)
730     {
731         BNXE_LOCK_EXIT_GLD(pUM);
732         return ECANCELED;
733     }
734 
735     pUM->ucastTableLen--;
736 
737     BNXE_LOCK_EXIT_GLD(pUM);
738     return 0;
739 }
740 
741 
742 static mblk_t * BnxeTxRingSend(void *   ringHandle,
743                                mblk_t * pMblk)
744 {
745     TxQueue *     pTxQ  = (TxQueue *)ringHandle;
746     um_device_t * pUM   = (um_device_t *)pTxQ->pUM;
747     u32_t         idx   = pTxQ->idx;
748     mblk_t *      pNextMblk;
749     int rc;
750 
751     while (pMblk)
752     {
753         pNextMblk = pMblk->b_next;
754         pMblk->b_next = NULL;
755 
756         rc = BnxeTxSendMblk(pUM, idx, pMblk, 0, 0);
757 
758         if (rc == BNXE_TX_GOODXMIT)
759         {
760             pMblk = pNextMblk;
761             continue;
762         }
763         else if (rc == BNXE_TX_DEFERPKT)
764         {
765             pMblk = pNextMblk;
766         }
767         else
768         {
769             pMblk->b_next = pNextMblk;
770         }
771 
772         break;
773     }
774 
775     return pMblk;
776 }
777 
778 #endif /* BNXE_RINGS */
779 
780 
781 static int BnxeMacUnicast(void *          pArg,
782                           const uint8_t * pMacAddr)
783 {
784     um_device_t * pUM = (um_device_t *)pArg;
785     int rc;
786 
787     BNXE_LOCK_ENTER_GLD(pUM);
788 
789     if (!pUM->plumbed)
790     {
791         memcpy(pUM->gldMac, pMacAddr, ETHERNET_ADDRESS_SIZE);
792         BNXE_LOCK_EXIT_GLD(pUM);
793         return 0;
794     }
795 
796     /* Validate MAC address */
797     if (IS_ETH_MULTICAST(pMacAddr))
798     {
799         BnxeLogWarn(pUM, "Cannot program a mcast/bcast address as a MAC Address.");
800         BNXE_LOCK_EXIT_GLD(pUM);
801         return EINVAL;
802     }
803 
804     BNXE_LOCK_ENTER_HWINIT(pUM);
805 
806     COPY_ETH_ADDRESS(pMacAddr, pUM->lm_dev.params.mac_addr);
807 
808     rc = BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE,
809                         pUM->lm_dev.params.mac_addr);
810 
811     BNXE_LOCK_EXIT_HWINIT(pUM);
812 
813     if (rc < 0)
814     {
815         BNXE_LOCK_EXIT_GLD(pUM);
816         return EAGAIN;
817     }
818 
819     BNXE_LOCK_EXIT_GLD(pUM);
820     return 0;
821 }
822 
823 
824 static mblk_t * BnxeMacTx(void *   pArg,
825                           mblk_t * pMblk)
826 {
827     um_device_t * pUM = (um_device_t *)pArg;
828     mblk_t *      pNextMblk;
829     int ring, rc;
830 
831     BNXE_LOCK_ENTER_GLDTX(pUM, RW_READER);
832 
833     if (!pUM->plumbed)
834     {
835         freemsgchain(pMblk);
836         BNXE_LOCK_EXIT_GLDTX(pUM);
837 
838         return NULL;
839     }
840 
841     while (pMblk)
842     {
843         ring = BnxeRouteTxRing(pUM, pMblk);
844 
845         pNextMblk = pMblk->b_next;
846         pMblk->b_next = NULL;
847 
848         //rc = BnxeTxSendMblk(pUM, NDIS_CID(&pUM->lm_dev), pMblk, 0, 0);
849         rc = BnxeTxSendMblk(pUM, ring, pMblk, 0, 0);
850 
851         if (rc == BNXE_TX_GOODXMIT)
852         {
853             pMblk = pNextMblk;
854             continue;
855         }
856         else if (rc == BNXE_TX_DEFERPKT)
857         {
858             pMblk = pNextMblk;
859         }
860         else
861         {
862             pMblk->b_next = pNextMblk;
863         }
864 
865         break;
866     }
867 
868     BNXE_LOCK_EXIT_GLDTX(pUM);
869 
870     return pMblk;
871 }
872 
873 
874 #ifdef MC_RESOURCES
875 
876 static void BnxeBlank(void * pArg,
877                       time_t tick_cnt,
878                       uint_t pkt_cnt)
879 {
880     um_device_t * pUM = (um_device_t *)pArg;
881 
882     if (!pUM->plumbed)
883     {
884         return;
885     }
886 
887     /* XXX
888      * Need to dynamically reconfigure the hw with new interrupt
889      * coalescing params...
890      */
891 }
892 
893 
894 static void BnxeMacResources(void * pArg)
895 {
896     um_device_t * pUM = (um_device_t *)pArg;
897     mac_rx_fifo_t mrf;
898     int idx;
899 
900     mrf.mrf_type              = MAC_RX_FIFO;
901     mrf.mrf_blank             = BnxeBlank;
902     mrf.mrf_arg               = (void *)pUM;
903     mrf.mrf_normal_blank_time = 25;
904     mrf.mrf_normal_pkt_count  = 8;
905 
906     LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx)
907     {
908         pUM->macRxResourceHandles[idx] =
909             mac_resource_add(pUM->pMac, (mac_resource_t *)&mrf);
910     }
911 }
912 
913 #endif /* MC_RESOURCES */
914 
915 
916 static boolean_t BnxeReadReg(um_device_t *          pUM,
917                              struct bnxe_reg_data * pData)
918 {
919     if (pData->offset & 0x3)
920     {
921         BnxeLogWarn(pUM, "Invalid register offset for GIOCBNXEREG ioctl");
922         return B_FALSE;
923     }
924 
925     LM_BAR_RD32_OFFSET(&pUM->lm_dev, 0, pData->offset, &pData->value);
926 
927     return B_TRUE;
928 }
929 
930 
931 static boolean_t BnxeWriteReg(um_device_t *          pUM,
932                               struct bnxe_reg_data * pData)
933 {
934     if (pData->offset & 0x3)
935     {
936         BnxeLogWarn(pUM, "Invalid register offset for SIOCBNXEREG ioctl");
937         return B_FALSE;
938     }
939 
940     LM_BAR_WR32_OFFSET(&pUM->lm_dev, 0, pData->offset, pData->value);
941 
942     return B_TRUE;
943 }
944 
945 
946 static boolean_t BnxeReadNvm(um_device_t *            pUM,
947                              struct bnxe_nvram_data * pData)
948 {
949     if (pData->offset & 0x3)
950     {
951         BnxeLogWarn(pUM, "Invalid register offset for GIOCBNXENVRM ioctl");
952         return B_FALSE;
953     }
954 
955     if (lm_nvram_read(&pUM->lm_dev,
956                       pData->offset,
957                       pData->value,
958                       (pData->num_of_u32 * sizeof(u32_t))) !=
959         LM_STATUS_SUCCESS)
960     {
961         return B_FALSE;
962     }
963 
964     return B_TRUE;
965 }
966 
967 
968 static boolean_t BnxeWriteNvm(um_device_t *            pUM,
969                               struct bnxe_nvram_data * pData)
970 {
971     if (pData->offset & 0x3)
972     {
973         BnxeLogWarn(pUM, "Invalid register offset for SIOCBNXENVRM ioctl");
974         return B_FALSE;
975     }
976 
977     if (lm_nvram_write(&pUM->lm_dev,
978                        pData->offset,
979                        pData->value,
980                        (pData->num_of_u32 * sizeof(u32_t))) !=
981         LM_STATUS_SUCCESS)
982     {
983         return B_FALSE;
984     }
985 
986     return B_TRUE;
987 }
988 
989 
990 static boolean_t BnxeReadPciCfg(um_device_t *          pUM,
991                                 struct bnxe_reg_data * pData)
992 {
993     pData->value = pci_config_get32(pUM->pPciCfg, (off_t)pData->offset);
994     return B_TRUE;
995 }
996 
997 typedef enum {
998     STATS_SHOW_TYPE_NUM,
999     STATS_SHOW_TYPE_STR,
1000     STATS_SHOW_TYPE_CNT,
1001     STATS_SHOW_TYPE_MAX
1002 } stats_show_type_t;
1003 
1004 typedef union _b10_stats_show_data_t
1005 {
1006     u32_t op; /* ioctl sub-commond */
1007 
1008     struct
1009     {
1010         u32_t num; /* return number of stats */
1011         u32_t len; /* length of each string item */
1012     } desc;
1013 
1014     /* variable length... */
1015     char str[1]; /* holds names of desc.num stats, each desc.len in length */
1016 
1017     struct
1018     {
1019         b10_l2_chip_statistics_v2_t l2_chip_stats;
1020         b10_l4_chip_statistics_t    l4_chip_stats;
1021         b10_l2_driver_statistics_t  l2_drv_stats;
1022         b10_l4_driver_statistics_t  l4_drv_stats;
1023     } cnt;
1024 } b10_stats_show_data_t;
1025 
1026 
1027 static boolean_t BnxeStatsShow(um_device_t *           pUM,
1028                                b10_stats_show_data_t * pStats,
1029                                u32_t                   statsLen)
1030 {
1031     stats_show_type_t op;
1032     const size_t stats_size = sizeof(pStats->cnt);
1033 
1034     /*
1035      * All stats names MUST conform to STATS_STR_LEN length!!!
1036      */
1037 
1038     #define STATS_STR_LEN 39
1039 
1040     /* XXX
1041      * Note: these strings must be updated whenever any of
1042      * b10_l2_chip_statistics_t, b10_l4_chip_statistics_t,
1043      * b10_l2_driver_statistics_t or b10_l4_driver_statistics_t
1044      * are changed, or additional statistics are required.
1045      */
1046 
1047     const char p_stat_str[] =
1048 
1049         // b10_l2_chip_statistics_t
1050 
1051         "l2_chip_stats_ver_num\0                 "
1052         "IfHCInOctets\0                          "
1053         "IfHCInBadOctets\0                       "
1054         "IfHCOutOctets\0                         "
1055         "IfHCOutBadOctets\0                      "
1056         "IfHCOutPkts\0                           "
1057         "IfHCInPkts\0                            "
1058         "IfHCInUcastPkts\0                       "
1059         "IfHCInMulticastPkts\0                   "
1060         "IfHCInBroadcastPkts\0                   "
1061         "IfHCOutUcastPkts\0                      "
1062         "IfHCOutMulticastPkts\0                  "
1063         "IfHCOutBroadcastPkts\0                  "
1064         "IfHCInUcastOctets\0                     "
1065         "IfHCInMulticastOctets\0                 "
1066         "IfHCInBroadcastOctets\0                 "
1067         "IfHCOutUcastOctets\0                    "
1068         "IfHCOutMulticastOctets\0                "
1069         "IfHCOutBroadcastOctets\0                "
1070         "IfHCOutDiscards\0                       "
1071         "IfHCInFalseCarrierErrors\0              "
1072         "Dot3StatsInternalMacTransmitErrors\0    "
1073         "Dot3StatsCarrierSenseErrors\0           "
1074         "Dot3StatsFCSErrors\0                    "
1075         "Dot3StatsAlignmentErrors\0              "
1076         "Dot3StatsSingleCollisionFrames\0        "
1077         "Dot3StatsMultipleCollisionFrames\0      "
1078         "Dot3StatsDeferredTransmissions\0        "
1079         "Dot3StatsExcessiveCollisions\0          "
1080         "Dot3StatsLateCollisions\0               "
1081         "EtherStatsCollisions\0                  "
1082         "EtherStatsFragments\0                   "
1083         "EtherStatsJabbers\0                     "
1084         "EtherStatsUndersizePkts\0               "
1085         "EtherStatsOverrsizePkts\0               "
1086         "EtherStatsPktsTx64Octets\0              "
1087         "EtherStatsPktsTx65Octetsto127Octets\0   "
1088         "EtherStatsPktsTx128Octetsto255Octets\0  "
1089         "EtherStatsPktsTx256Octetsto511Octets\0  "
1090         "EtherStatsPktsTx512Octetsto1023Octets\0 "
1091         "EtherStatsPktsTx1024Octetsto1522Octets\0"
1092         "EtherStatsPktsTxOver1522Octets\0        "
1093         "XonPauseFramesReceived\0                "
1094         "XoffPauseFramesReceived\0               "
1095         "OutXonSent\0                            "
1096         "OutXoffSent\0                           "
1097         "FlowControlDone\0                       "
1098         "MacControlFramesReceived\0              "
1099         "XoffStateEntered\0                      "
1100         "IfInFramesL2FilterDiscards\0            "
1101         "IfInTTL0Discards\0                      "
1102         "IfInxxOverflowDiscards\0                "
1103         "IfInMBUFDiscards\0                      "
1104         "IfInErrors\0                            "
1105         "IfInErrorsOctets\0                      "
1106         "IfInNoBrbBuffer\0                       "
1107 
1108         "Nig_brb_packet\0                        "
1109         "Nig_brb_truncate\0                      "
1110         "Nig_flow_ctrl_discard\0                 "
1111         "Nig_flow_ctrl_octets\0                  "
1112         "Nig_flow_ctrl_packet\0                  "
1113         "Nig_mng_discard\0                       "
1114         "Nig_mng_octet_inp\0                     "
1115         "Nig_mng_octet_out\0                     "
1116         "Nig_mng_packet_inp\0                    "
1117         "Nig_mng_packet_out\0                    "
1118         "Nig_pbf_octets\0                        "
1119         "Nig_pbf_packet\0                        "
1120         "Nig_safc_inp\0                          "
1121 
1122         "Tx_Lpi_Count\0                          "        // This counter counts the number of timers the debounced version of EEE link idle is asserted
1123 
1124         // b10_l4_chip_statistics_t
1125 
1126         "l4_chip_stats_ver_num\0                 "
1127         "NoTxCqes\0                              "
1128         "InTCP4Segments\0                        "
1129         "OutTCP4Segments\0                       "
1130         "RetransmittedTCP4Segments\0             "
1131         "InTCP4Errors\0                          "
1132         "InIP4Receives\0                         "
1133         "InIP4HeaderErrors\0                     "
1134         "InIP4Discards\0                         "
1135         "InIP4Delivers\0                         "
1136         "InIP4Octets\0                           "
1137         "OutIP4Octets\0                          "
1138         "InIP4TruncatedPackets\0                 "
1139         "InTCP6Segments\0                        "
1140         "OutTCP6Segments\0                       "
1141         "RetransmittedTCP6Segments\0             "
1142         "InTCP6Errors\0                          "
1143         "InIP6Receives\0                         "
1144         "InIP6HeaderErrors\0                     "
1145         "InIP6Discards\0                         "
1146         "InIP6Delivers\0                         "
1147         "InIP6Octets\0                           "
1148         "OutIP6Octets\0                          "
1149         "InIP6TruncatedPackets\0                 "
1150 
1151         // b10_l2_driver_statistics_t
1152 
1153         "l2_driver_stats_ver_num\0               "
1154         "RxIPv4FragCount\0                       "
1155         "RxIpCsErrorCount\0                      "
1156         "RxTcpCsErrorCount\0                     "
1157         "RxLlcSnapCount\0                        "
1158         "RxPhyErrorCount\0                       "
1159         "RxIpv6ExtCount\0                        "
1160         "TxNoL2Bd\0                              "
1161         "TxNoSqWqe\0                             "
1162         "TxL2AssemblyBufUse\0                    "
1163 
1164         // b10_l4_driver_statistics_t
1165 
1166         "l4_driver_stats_ver_num\0               "
1167         "CurrentlyIpv4Established\0              "
1168         "OutIpv4Resets\0                         "
1169         "OutIpv4Fin\0                            "
1170         "InIpv4Reset\0                           "
1171         "InIpv4Fin\0                             "
1172         "CurrentlyIpv6Established\0              "
1173         "OutIpv6Resets\0                         "
1174         "OutIpv6Fin\0                            "
1175         "InIpv6Reset\0                           "
1176         "InIpv6Fin\0                             "
1177         "RxIndicateReturnPendingCnt\0            "
1178         "RxIndicateReturnDoneCnt\0               "
1179         "RxActiveGenBufCnt\0                     "
1180         "TxNoL4Bd\0                              "
1181         "TxL4AssemblyBufUse\0                   "
1182 
1183         ;
1184 
1185     ASSERT_STATIC((sizeof(p_stat_str) / STATS_STR_LEN) ==
1186                   (stats_size / sizeof(u64_t)));
1187 
1188     op = *((stats_show_type_t *)pStats);
1189 
1190     switch (op)
1191     {
1192     case STATS_SHOW_TYPE_NUM:
1193 
1194         if (statsLen < sizeof(pStats->desc))
1195         {
1196             return B_FALSE;
1197         }
1198 
1199         pStats->desc.num = (stats_size / sizeof(u64_t));
1200         pStats->desc.len = STATS_STR_LEN;
1201 
1202         return B_TRUE;
1203 
1204     case STATS_SHOW_TYPE_STR:
1205 
1206         if (statsLen != sizeof(p_stat_str))
1207         {
1208             return B_FALSE;
1209         }
1210 
1211         memcpy(pStats->str, p_stat_str, sizeof(p_stat_str));
1212 
1213         return B_TRUE;
1214 
1215     case STATS_SHOW_TYPE_CNT:
1216 
1217         if (statsLen != stats_size)
1218         {
1219             return B_FALSE;
1220         }
1221 
1222         lm_stats_get_l2_chip_stats(&pUM->lm_dev,
1223                                    &pStats->cnt.l2_chip_stats,
1224                                    L2_CHIP_STATISTICS_VER_NUM_2);
1225 
1226         lm_stats_get_l4_chip_stats(&pUM->lm_dev,
1227                                    &pStats->cnt.l4_chip_stats);
1228 
1229         lm_stats_get_l2_driver_stats(&pUM->lm_dev
1230                                      ,&pStats->cnt.l2_drv_stats);
1231 
1232         lm_stats_get_l4_driver_stats(&pUM->lm_dev,
1233                                      &pStats->cnt.l4_drv_stats);
1234 
1235         return B_TRUE;
1236 
1237     default:
1238 
1239         return B_FALSE;
1240     }
1241 }
1242 
1243 static void BnxeMacIoctl(void *    pArg,
1244                          queue_t * pQ,
1245                          mblk_t *  pMblk)
1246 {
1247     um_device_t * pUM = (um_device_t *)pArg;
1248     struct iocblk * pIoctl;
1249     int rc;
1250 
1251     if ((pQ == NULL) || (pMblk == NULL))
1252     {
1253         return;
1254     }
1255 
1256     if (pMblk->b_datap->db_type != M_IOCTL)
1257     {
1258         miocnak(pQ, pMblk, 0, EINVAL);
1259         return;
1260     }
1261 
1262     pIoctl = (struct iocblk *)pMblk->b_rptr;
1263 
1264     BNXE_LOCK_ENTER_GLD(pUM);
1265 
1266     switch (pIoctl->ioc_cmd)
1267     {
1268     case GIOCBNXELLDP:
1269 
1270         if ((pIoctl->ioc_count != sizeof(b10_lldp_params_get_t)) ||
1271             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1272             (miocpullup(pMblk, sizeof(b10_lldp_params_get_t)) < 0))
1273         {
1274             miocnak(pQ, pMblk, 0, EINVAL);
1275             break;
1276         }
1277 
1278         if (((b10_lldp_params_get_t *)pMblk->b_cont->b_rptr)->ver_num !=
1279             LLDP_PARAMS_VER_NUM)
1280         {
1281             miocnak(pQ, pMblk, 0, EINVAL);
1282             break;
1283         }
1284 
1285         if (lm_dcbx_lldp_read_params(&pUM->lm_dev,
1286                          (b10_lldp_params_get_t *)pMblk->b_cont->b_rptr) !=
1287             LM_STATUS_SUCCESS)
1288         {
1289             miocnak(pQ, pMblk, 0,
1290                     (!IS_DCB_ENABLED(&pUM->lm_dev)) ? ENOTSUP : EINVAL);
1291             break;
1292         }
1293 
1294         miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1295         break;
1296 
1297     case GIOCBNXEDCBX:
1298 
1299         if ((pIoctl->ioc_count != sizeof(b10_dcbx_params_get_t)) ||
1300             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1301             (miocpullup(pMblk, sizeof(b10_dcbx_params_get_t)) < 0))
1302         {
1303             miocnak(pQ, pMblk, 0, EINVAL);
1304             break;
1305         }
1306 
1307         if (((b10_dcbx_params_get_t *)pMblk->b_cont->b_rptr)->ver_num !=
1308             DCBX_PARAMS_VER_NUM)
1309         {
1310             miocnak(pQ, pMblk, 0, EINVAL);
1311             break;
1312         }
1313 
1314         if (lm_dcbx_read_params(&pUM->lm_dev,
1315                          (b10_dcbx_params_get_t *)pMblk->b_cont->b_rptr) !=
1316             LM_STATUS_SUCCESS)
1317         {
1318             miocnak(pQ, pMblk, 0,
1319                     (!IS_DCB_ENABLED(&pUM->lm_dev)) ? ENOTSUP : EINVAL);
1320             break;
1321         }
1322 
1323         miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1324         break;
1325 
1326     case SIOCBNXEDCBX:
1327 
1328         /* XXX */
1329         miocnak(pQ, pMblk, 0, EINVAL);
1330         break;
1331 
1332     case GIOCBNXEREG:
1333 
1334         if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) ||
1335             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1336             (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0))
1337         {
1338             miocnak(pQ, pMblk, 0, EINVAL);
1339             break;
1340         }
1341 
1342         if (!BnxeReadReg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr))
1343         {
1344             miocnak(pQ, pMblk, 0, EINVAL);
1345         }
1346         else
1347         {
1348             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1349         }
1350 
1351         break;
1352 
1353     case SIOCBNXEREG:
1354 
1355         if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) ||
1356             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1357             (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0))
1358         {
1359             miocnak(pQ, pMblk, 0, EINVAL);
1360             break;
1361         }
1362 
1363         if (!BnxeWriteReg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr))
1364         {
1365             miocnak(pQ, pMblk, 0, EINVAL);
1366         }
1367         else
1368         {
1369             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1370         }
1371 
1372         break;
1373 
1374     case GIOCBNXENVRM:
1375 
1376         if ((pIoctl->ioc_count < sizeof(struct bnxe_nvram_data)) ||
1377             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1378             (miocpullup(pMblk, pIoctl->ioc_count) < 0))
1379         {
1380             miocnak(pQ, pMblk, 0, EINVAL);
1381             break;
1382         }
1383 
1384         if (!BnxeReadNvm(pUM, (struct bnxe_nvram_data *)pMblk->b_cont->b_rptr))
1385         {
1386             miocnak(pQ, pMblk, 0, EINVAL);
1387         }
1388         else
1389         {
1390             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1391         }
1392 
1393         break;
1394 
1395     case SIOCBNXENVRM:
1396 
1397         if ((pIoctl->ioc_count < sizeof(struct bnxe_nvram_data)) ||
1398             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1399             (miocpullup(pMblk, pIoctl->ioc_count) < 0))
1400         {
1401             miocnak(pQ, pMblk, 0, EINVAL);
1402             break;
1403         }
1404 
1405         if (!BnxeWriteNvm(pUM, (struct bnxe_nvram_data *)pMblk->b_cont->b_rptr))
1406         {
1407             miocnak(pQ, pMblk, 0, EINVAL);
1408         }
1409         else
1410         {
1411             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1412         }
1413 
1414         break;
1415 
1416     case GIOCBNXEPCI:
1417 
1418         if ((pIoctl->ioc_count != sizeof(struct bnxe_reg_data)) ||
1419             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1420             (miocpullup(pMblk, sizeof(struct bnxe_reg_data)) < 0))
1421         {
1422             miocnak(pQ, pMblk, 0, EINVAL);
1423             break;
1424         }
1425 
1426         if (!BnxeReadPciCfg(pUM, (struct bnxe_reg_data *)pMblk->b_cont->b_rptr))
1427         {
1428             miocnak(pQ, pMblk, 0, EINVAL);
1429         }
1430         else
1431         {
1432             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1433         }
1434 
1435         break;
1436 
1437     case GIOCBNXESTATS:
1438 
1439         /* min size = sizeof(op) in b10_stats_show_data_t */
1440         if ((pIoctl->ioc_count < sizeof(u32_t)) ||
1441             (pMblk->b_cont == NULL) || (pMblk->b_cont->b_rptr == NULL) ||
1442             (miocpullup(pMblk, pIoctl->ioc_count) < 0))
1443         {
1444             miocnak(pQ, pMblk, 0, EINVAL);
1445             break;
1446         }
1447 
1448         if (!BnxeStatsShow(pUM,
1449                            (b10_stats_show_data_t *)pMblk->b_cont->b_rptr,
1450                            pIoctl->ioc_count))
1451         {
1452             miocnak(pQ, pMblk, 0, EINVAL);
1453         }
1454         else
1455         {
1456             miocack(pQ, pMblk, pIoctl->ioc_count, 0);
1457         }
1458 
1459         break;
1460 
1461     default:
1462 
1463         miocnak(pQ, pMblk, 0, EINVAL);
1464         break;
1465     }
1466 
1467     BNXE_LOCK_EXIT_GLD(pUM);
1468 }
1469 
1470 
1471 #ifdef BNXE_RINGS
1472 
1473 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1474 static mblk_t * BnxeRxRingPoll(void * ringHandle,
1475                                int    numBytes,
1476                                int    numPkts)
1477 #else
1478 static mblk_t * BnxeRxRingPoll(void * ringHandle,
1479                                int    numBytes)
1480 #endif
1481 {
1482     RxQueue *     pRxQ  = (RxQueue *)ringHandle;
1483     um_device_t * pUM   = (um_device_t *)pRxQ->pUM;
1484     u32_t         idx   = pRxQ->idx;
1485     mblk_t *      pMblk = NULL;
1486     boolean_t     pktsRxed = 0;
1487     boolean_t     pktsTxed = 0;
1488 
1489 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1490     _NOTE(ARGUNUSED(numPkts))
1491 #endif
1492 
1493     if (numBytes <= 0)
1494     {
1495         return NULL;
1496     }
1497 
1498     if (pRxQ->inPollMode == B_FALSE)
1499     {
1500         BnxeLogWarn(pUM, "Polling on ring %d when NOT in poll mode!", idx);
1501         return NULL;
1502     }
1503 
1504     BNXE_LOCK_ENTER_INTR(pUM, idx);
1505 
1506     pRxQ->pollCnt++;
1507 
1508     BnxePollRxRing(pUM, idx, &pktsRxed, &pktsTxed);
1509 
1510     if (pktsTxed) BnxeTxRingProcess(pUM, idx);
1511     if (pktsRxed) pMblk = BnxeRxRingProcess(pUM, idx, TRUE, numBytes);
1512 
1513     /*
1514      * This is here for the off chance that all rings are in polling
1515      * mode and the default interrupt hasn't fired recently to handle
1516      * the sq.
1517      */
1518     lm_sq_post_pending(&pUM->lm_dev);
1519 
1520     BNXE_LOCK_EXIT_INTR(pUM, idx);
1521 
1522     return pMblk;
1523 }
1524 
1525 
1526 static int BnxeRxRingStart(mac_ring_driver_t ringHandle
1527 #if defined(__S11) || defined(__S12)
1528                            , uint64_t          genNumber
1529 #endif
1530                            )
1531 {
1532     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1533     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1534     u32_t         idx  = pRxQ->idx;
1535 
1536     BnxeLogDbg(pUM, "Starting Rx Ring %d", idx);
1537 
1538     BNXE_LOCK_ENTER_RX(pUM, idx);
1539 #if defined(__S11) || defined(__S12)
1540     pRxQ->genNumber      = genNumber;
1541 #endif
1542     pRxQ->inPollMode     = B_FALSE;
1543     pRxQ->intrDisableCnt = 0;
1544     pRxQ->intrEnableCnt  = 0;
1545     pRxQ->pollCnt        = 0;
1546     BNXE_LOCK_EXIT_RX(pUM, idx);
1547 
1548     return 0;
1549 }
1550 
1551 
1552 #if defined(__S11) || defined(__S12)
1553 
1554 static int BnxeRingStat(mac_ring_driver_t ringHandle,
1555                         uint_t            stat,
1556                         uint64_t *        val)
1557 {
1558     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1559     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1560 
1561     switch (stat)
1562     {
1563     case MAC_STAT_OERRORS:
1564     case MAC_STAT_OBYTES:
1565     case MAC_STAT_OPACKETS:
1566     case MAC_STAT_IERRORS:
1567     case MAC_STAT_RBYTES: /* MAC_STAT_IBYTES */
1568     case MAC_STAT_IPACKETS:
1569     default:
1570         return ENOTSUP;
1571     }
1572 
1573     return 0;
1574 }
1575 
1576 #endif /* __S11 or __S12 */
1577 
1578 
1579 #if defined(__S11) || defined(__S12)
1580 static int BnxeRxRingIntrEnable(mac_ring_driver_t ringHandle)
1581 #else
1582 static int BnxeRxRingIntrEnable(mac_intr_handle_t ringHandle)
1583 #endif
1584 {
1585     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1586     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1587 
1588     BnxeLogDbg(pUM, "Enabling Interrupt for Rx Ring %d", pRxQ->idx);
1589 
1590     /* polling not allowed on LM_NON_RSS_SB when overlapped with FCoE */
1591     if ((pRxQ->idx == LM_NON_RSS_SB(&pUM->lm_dev)) &&
1592         CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE) &&
1593         (pUM->rssIntr.intrCount == LM_MAX_RSS_CHAINS(&pUM->lm_dev)))
1594     {
1595         return 0; /* ok, already enabled */
1596     }
1597 
1598     BnxeIntrIguSbEnable(pUM, pRxQ->idx, B_FALSE);
1599 
1600     return 0;
1601 }
1602 
1603 
1604 #if defined(__S11) || defined(__S12)
1605 static int BnxeRxRingIntrDisable(mac_ring_driver_t ringHandle)
1606 #else
1607 static int BnxeRxRingIntrDisable(mac_intr_handle_t ringHandle)
1608 #endif
1609 {
1610     RxQueue *     pRxQ = (RxQueue *)ringHandle;
1611     um_device_t * pUM  = (um_device_t *)pRxQ->pUM;
1612 
1613     BnxeLogDbg(pUM, "Disabling Interrupt for Rx Ring %d", pRxQ->idx);
1614 
1615     /* polling not allowed on LM_NON_RSS_SB when overlapped with FCoE */
1616     if ((pRxQ->idx == LM_NON_RSS_SB(&pUM->lm_dev)) &&
1617         CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE) &&
1618         (pUM->rssIntr.intrCount == LM_MAX_RSS_CHAINS(&pUM->lm_dev)))
1619     {
1620         return -1; /* NO, keep enabled! */
1621     }
1622 
1623     BnxeIntrIguSbDisable(pUM, pRxQ->idx, B_FALSE);
1624 
1625     return 0;
1626 }
1627 
1628 
1629 /* callback function for MAC layer to register rings */
1630 static void BnxeFillRing(void *            arg,
1631                          mac_ring_type_t   ringType,
1632                          const int         ringGroupIndex,
1633                          const int         ringIndex,
1634                          mac_ring_info_t * pRingInfo,
1635                          mac_ring_handle_t ringHandle)
1636 {
1637     um_device_t * pUM = (um_device_t *)arg;
1638     RxQueue *     pRxQ;
1639     TxQueue *     pTxQ;
1640 
1641     switch (ringType)
1642     {
1643     case MAC_RING_TYPE_RX:
1644 
1645         BnxeLogInfo(pUM, "Initializing Rx Ring %d (Ring Group %d)",
1646                     ringIndex, ringGroupIndex);
1647 
1648         ASSERT(ringGroupIndex == 0);
1649         ASSERT(ringIndex < pUM->devParams.numRings);
1650 
1651         pRxQ = &pUM->rxq[ringIndex];
1652         pRxQ->ringHandle = ringHandle;
1653 
1654         pRingInfo->mri_driver = (mac_ring_driver_t)pRxQ;
1655         pRingInfo->mri_start  = BnxeRxRingStart;
1656         pRingInfo->mri_stop   = NULL;
1657 #if defined(__S11) || defined(__S12)
1658         pRingInfo->mri_stat   = BnxeRingStat;
1659 #endif
1660         pRingInfo->mri_poll   = BnxeRxRingPoll;
1661 
1662 #if !(defined(__S11) || defined(__S12))
1663         pRingInfo->mri_intr.mi_handle  = (mac_intr_handle_t)pRxQ;
1664 #endif
1665         pRingInfo->mri_intr.mi_enable  = (mac_intr_enable_t)BnxeRxRingIntrEnable;
1666         pRingInfo->mri_intr.mi_disable = (mac_intr_disable_t)BnxeRxRingIntrDisable;
1667 
1668         break;
1669 
1670     case MAC_RING_TYPE_TX:
1671 
1672         BnxeLogInfo(pUM, "Initializing Tx Ring %d (Ring Group %d)",
1673                     ringIndex, ringGroupIndex);
1674 
1675         ASSERT(ringGroupIndex == 0);
1676         ASSERT(ringIndex < pUM->devParams.numRings);
1677 
1678         pTxQ = &pUM->txq[ringIndex];
1679         pTxQ->ringHandle = ringHandle;
1680 
1681         pRingInfo->mri_driver = (mac_ring_driver_t)pTxQ;
1682         pRingInfo->mri_start  = NULL;
1683         pRingInfo->mri_stop   = NULL;
1684 #if defined(__S11) || defined(__S12)
1685         pRingInfo->mri_stat   = BnxeRingStat;
1686 #endif
1687         pRingInfo->mri_tx     = (mac_ring_send_t)BnxeTxRingSend;
1688 
1689         break;
1690 
1691     default:
1692         break;
1693     }
1694 }
1695 
1696 
1697 /* callback function for MAC layer to register groups */
1698 static void BnxeFillGroup(void *             arg,
1699                           mac_ring_type_t    ringType,
1700                           const int          ringGroupIndex,
1701                           mac_group_info_t * pGroupInfo,
1702                           mac_group_handle_t groupHandle)
1703 {
1704     um_device_t *  pUM = (um_device_t *)arg;
1705     RxQueueGroup * pRxQGroup;
1706 
1707     switch (ringType)
1708     {
1709     case MAC_RING_TYPE_RX:
1710 
1711         BnxeLogInfo(pUM, "Initializing Rx Group %d", ringGroupIndex);
1712 
1713         pRxQGroup = &pUM->rxqGroup[ringGroupIndex];
1714         pRxQGroup->groupHandle = groupHandle;
1715 
1716         pGroupInfo->mgi_driver = (mac_group_driver_t)pRxQGroup;
1717         pGroupInfo->mgi_start  = NULL;
1718         pGroupInfo->mgi_stop   = NULL;
1719         pGroupInfo->mgi_addmac = BnxeRxRingGroupAddMac;
1720         pGroupInfo->mgi_remmac = BnxeRxRingGroupRemMac;
1721         pGroupInfo->mgi_count  = (pUM->devParams.numRings /
1722                                   USER_OPTION_RX_RING_GROUPS_DEFAULT);
1723 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1724         pGroupInfo->mgi_flags  = MAC_GROUP_DEFAULT;
1725 #endif
1726 
1727         break;
1728 
1729     case MAC_RING_TYPE_TX:
1730     default:
1731         break;
1732     }
1733 }
1734 
1735 #endif /* BNXE_RINGS */
1736 
1737 
1738 static boolean_t BnxeMacGetCapability(void *      pArg,
1739                                       mac_capab_t capability,
1740                                       void *      pCapabilityData)
1741 {
1742     um_device_t * pUM = (um_device_t *)pArg;
1743     mac_capab_lso_t *   pCapLSO;
1744     mac_capab_rings_t * pCapRings;
1745 
1746     switch (capability)
1747     {
1748     case MAC_CAPAB_HCKSUM:
1749 
1750         *((u32_t *)pCapabilityData) = 0;
1751 
1752         if (pUM->devParams.enabled_oflds &
1753             (LM_OFFLOAD_TX_IP_CKSUM | LM_OFFLOAD_RX_IP_CKSUM))
1754         {
1755             *((u32_t *)pCapabilityData) |= HCKSUM_IPHDRCKSUM;
1756         }
1757 
1758         if (pUM->devParams.enabled_oflds &
1759             (LM_OFFLOAD_TX_TCP_CKSUM | LM_OFFLOAD_TX_UDP_CKSUM |
1760              LM_OFFLOAD_RX_TCP_CKSUM | LM_OFFLOAD_RX_UDP_CKSUM))
1761         {
1762             *((u32_t *)pCapabilityData) |= HCKSUM_INET_PARTIAL;
1763         }
1764 
1765         break;
1766 
1767     case MAC_CAPAB_LSO:
1768 
1769         pCapLSO = (mac_capab_lso_t *)pCapabilityData;
1770 
1771         if (pUM->devParams.lsoEnable)
1772         {
1773             pCapLSO->lso_flags                  = LSO_TX_BASIC_TCP_IPV4;
1774             pCapLSO->lso_basic_tcp_ipv4.lso_max = BNXE_LSO_MAXLEN;
1775             break;
1776         }
1777 
1778         return B_FALSE;
1779 
1780 #ifdef BNXE_RINGS
1781 
1782     case MAC_CAPAB_RINGS:
1783 
1784         if (!pUM->devParams.numRings)
1785         {
1786             return B_FALSE;
1787         }
1788 
1789         pCapRings = (mac_capab_rings_t *)pCapabilityData;
1790 
1791 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1792         pCapRings->mr_version    = MAC_RINGS_VERSION_1;
1793         pCapRings->mr_flags      = MAC_RINGS_FLAGS_NONE;
1794 #endif
1795         pCapRings->mr_group_type = MAC_GROUP_TYPE_STATIC;
1796         pCapRings->mr_rnum       = pUM->devParams.numRings;
1797         pCapRings->mr_rget       = BnxeFillRing;
1798         pCapRings->mr_gaddring   = NULL;
1799         pCapRings->mr_gremring   = NULL;
1800 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1801         pCapRings->mr_ggetringtc = NULL;
1802 #endif
1803 
1804         switch (pCapRings->mr_type)
1805         {
1806         case MAC_RING_TYPE_RX:
1807 
1808             pCapRings->mr_gnum = USER_OPTION_RX_RING_GROUPS_DEFAULT;
1809             pCapRings->mr_gget = BnxeFillGroup;
1810             break;
1811 
1812         case MAC_RING_TYPE_TX:
1813 
1814 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
1815             pCapRings->mr_gnum = 1;
1816 #else
1817             pCapRings->mr_gnum = 0;
1818 #endif
1819             pCapRings->mr_gget = NULL;
1820             break;
1821 
1822         default:
1823 
1824             return B_FALSE;
1825         }
1826 
1827         break;
1828 
1829 #endif /* BNXE_RINGS */
1830 
1831 #if !(defined(__S11) || defined(__S12))
1832 
1833     case MAC_CAPAB_POLL:
1834 
1835         /*
1836          * There's nothing for us to fill in, simply returning B_TRUE stating
1837          * that we support polling is sufficient.
1838          */
1839         break;
1840 
1841 #endif /* not __S11 or __S12 */
1842 
1843 #if defined(ILLUMOS)
1844     case MAC_CAPAB_TRANSCEIVER:
1845         return bnxe_fill_transceiver(pUM, pCapabilityData);
1846 #endif
1847 
1848     default:
1849 
1850         return B_FALSE;
1851     }
1852 
1853     return B_TRUE;
1854 }
1855 
1856 
1857 #ifdef MC_SETPROP
1858 
1859 static int BnxeSetPrivateProperty(um_device_t * pUM,
1860                                   const char *  pr_name,
1861                                   uint_t        pr_valsize,
1862                                   const void *  pr_val)
1863 {
1864     int err = 0;
1865     long result;
1866 
1867     if (strcmp(pr_name, "_en_2500fdx_cap") == 0)
1868     {
1869         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1870         {
1871             return EINVAL;
1872         }
1873 
1874         if ((result > 1) || (result < 0))
1875         {
1876             return EINVAL;
1877         }
1878 
1879         pUM->hwinit.lnkcfg.param_2500fdx = (uint32_t)result;
1880         pUM->curcfg.lnkcfg.param_2500fdx = (uint32_t)result;
1881         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1882     }
1883     else if (strcmp(pr_name, "_en_txpause_cap") == 0)
1884     {
1885         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1886         {
1887             return EINVAL;
1888         }
1889 
1890         if ((result > 1) || (result < 0))
1891         {
1892             return EINVAL;
1893         }
1894 
1895         pUM->hwinit.lnkcfg.param_txpause = (uint32_t)result;
1896         pUM->curcfg.lnkcfg.param_txpause = (uint32_t)result;
1897         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1898     }
1899     else if (strcmp(pr_name, "_en_rxpause_cap") == 0)
1900     {
1901         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1902         {
1903             return EINVAL;
1904         }
1905 
1906         if ((result > 1) || (result < 0))
1907         {
1908             return EINVAL;
1909         }
1910 
1911         pUM->hwinit.lnkcfg.param_rxpause = (uint32_t)result;
1912         pUM->curcfg.lnkcfg.param_rxpause = (uint32_t)result;
1913         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1914     }
1915     else if (strcmp(pr_name, "_autoneg_flow") == 0)
1916     {
1917         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1918         {
1919             return EINVAL;
1920         }
1921 
1922         if ((result > 1) || (result < 0))
1923         {
1924             return EINVAL;
1925         }
1926 
1927         pUM->hwinit.flow_autoneg = (uint32_t)result;
1928         pUM->curcfg.flow_autoneg = (uint32_t)result;
1929         if (pUM->plumbed) BnxeUpdatePhy(pUM);
1930     }
1931     else if (strcmp(pr_name, "_checksum") == 0)
1932     {
1933         if (pUM->plumbed)
1934         {
1935             return EBUSY;
1936         }
1937 
1938         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1939         {
1940             return EINVAL;
1941         }
1942 
1943         switch (result)
1944         {
1945         case USER_OPTION_CKSUM_NONE:
1946 
1947             pUM->devParams.enabled_oflds = LM_OFFLOAD_NONE;
1948             break;
1949 
1950         case USER_OPTION_CKSUM_L3:
1951 
1952             pUM->devParams.enabled_oflds = (LM_OFFLOAD_TX_IP_CKSUM |
1953                                             LM_OFFLOAD_RX_IP_CKSUM);
1954             break;
1955 
1956         case USER_OPTION_CKSUM_L3_L4:
1957 
1958             pUM->devParams.enabled_oflds = (LM_OFFLOAD_TX_IP_CKSUM  |
1959                                             LM_OFFLOAD_RX_IP_CKSUM  |
1960                                             LM_OFFLOAD_TX_TCP_CKSUM |
1961                                             LM_OFFLOAD_RX_TCP_CKSUM |
1962                                             LM_OFFLOAD_TX_UDP_CKSUM |
1963                                             LM_OFFLOAD_RX_UDP_CKSUM);
1964             break;
1965 
1966         default:
1967 
1968             return EINVAL;
1969         }
1970 
1971         pUM->devParams.checksum = (uint32_t)result;
1972     }
1973     else if (strcmp(pr_name, "_tx_ring_policy") == 0)
1974     {
1975         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
1976         {
1977             return EINVAL;
1978         }
1979 
1980         switch (result)
1981         {
1982         case BNXE_ROUTE_RING_NONE:
1983         case BNXE_ROUTE_RING_TCPUDP:
1984         case BNXE_ROUTE_RING_DEST_MAC:
1985         case BNXE_ROUTE_RING_MSG_PRIO:
1986 
1987             break;
1988 
1989         default:
1990 
1991             return EINVAL;
1992         }
1993 
1994         pUM->devParams.routeTxRingPolicy = (uint32_t)result;
1995     }
1996     else if (strcmp(pr_name, "_num_rings") == 0)
1997     {
1998         if (pUM->plumbed)
1999         {
2000             return EBUSY;
2001         }
2002 
2003         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2004         {
2005             return EINVAL;
2006         }
2007 
2008         if ((result < USER_OPTION_NUM_RINGS_MIN) ||
2009             (result > USER_OPTION_NUM_RINGS_MAX))
2010         {
2011             return EINVAL;
2012         }
2013 
2014         pUM->devParams.numRings = (uint32_t)result;
2015     }
2016     else if (strcmp(pr_name, "_rx_descs") == 0)
2017     {
2018         if (pUM->plumbed)
2019         {
2020             return EBUSY;
2021         }
2022 
2023         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2024         {
2025             return EINVAL;
2026         }
2027 
2028         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2029         {
2030             return EINVAL;
2031         }
2032 
2033         pUM->devParams.numRxDesc[LM_CLI_IDX_NDIS] = (uint32_t)result;
2034     }
2035     else if (strcmp(pr_name, "_rx_free_reclaim") == 0)
2036     {
2037         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2038         {
2039             return EINVAL;
2040         }
2041 
2042         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2043         {
2044             return EINVAL;
2045         }
2046 
2047         pUM->devParams.maxRxFree = (uint32_t)result;
2048     }
2049     else if (strcmp(pr_name, "_tx_descs") == 0)
2050     {
2051         if (pUM->plumbed)
2052         {
2053             return EBUSY;
2054         }
2055 
2056         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2057         {
2058             return EINVAL;
2059         }
2060 
2061         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2062         {
2063             return EINVAL;
2064         }
2065 
2066         pUM->devParams.numTxDesc[LM_CLI_IDX_NDIS] = (uint32_t)result;
2067     }
2068     else if (strcmp(pr_name, "_tx_free_reclaim") == 0)
2069     {
2070         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2071         {
2072             return EINVAL;
2073         }
2074 
2075         if ((result < USER_OPTION_BDS_MIN) || (result > USER_OPTION_BDS_MAX))
2076         {
2077             return EINVAL;
2078         }
2079 
2080         pUM->devParams.maxTxFree = (uint32_t)result;
2081     }
2082     else if (strcmp(pr_name, "_rx_copy_threshold") == 0)
2083     {
2084         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2085         {
2086             return EINVAL;
2087         }
2088 
2089         pUM->devParams.rxCopyThreshold = (uint32_t)result;
2090     }
2091     else if (strcmp(pr_name, "_tx_copy_threshold") == 0)
2092     {
2093         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2094         {
2095             return EINVAL;
2096         }
2097 
2098         pUM->devParams.txCopyThreshold = (uint32_t)result;
2099     }
2100     else if (strcmp(pr_name, "_interrupt_coalesce") == 0)
2101     {
2102         if (pUM->plumbed)
2103         {
2104             return EBUSY;
2105         }
2106 
2107         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2108         {
2109             return EINVAL;
2110         }
2111 
2112         if ((result > 1) || (result < 0))
2113         {
2114             return EINVAL;
2115         }
2116 
2117         pUM->devParams.intrCoalesce = (uint32_t)result;
2118     }
2119     else if (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0)
2120     {
2121         if (pUM->plumbed)
2122         {
2123             return EBUSY;
2124         }
2125 
2126         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2127         {
2128             return EINVAL;
2129         }
2130 
2131         if ((result < USER_OPTION_INTR_COALESCE_MIN) ||
2132             (result < USER_OPTION_INTR_COALESCE_MAX))
2133         {
2134             return EINVAL;
2135         }
2136 
2137         pUM->devParams.intrRxPerSec = (uint32_t)(1000000 / result);
2138     }
2139     else if (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0)
2140     {
2141         if (pUM->plumbed)
2142         {
2143             return EBUSY;
2144         }
2145 
2146         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2147         {
2148             return EINVAL;
2149         }
2150 
2151         if ((result < USER_OPTION_INTR_COALESCE_MIN) ||
2152             (result < USER_OPTION_INTR_COALESCE_MAX))
2153         {
2154             return EINVAL;
2155         }
2156 
2157         pUM->devParams.intrTxPerSec = (uint32_t)(1000000 / result);
2158     }
2159     else if (strcmp(pr_name, "_disable_msix") == 0)
2160     {
2161         if (pUM->plumbed)
2162         {
2163             return EBUSY;
2164         }
2165 
2166         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2167         {
2168             return EINVAL;
2169         }
2170 
2171         if ((result > 1) || (result < 0))
2172         {
2173             return EINVAL;
2174         }
2175 
2176         pUM->devParams.disableMsix = (uint32_t)result;
2177     }
2178     else if (strcmp(pr_name, "_l2_fw_flow_ctrl") == 0)
2179     {
2180         if (pUM->plumbed)
2181         {
2182             return EBUSY;
2183         }
2184 
2185         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2186         {
2187             return EINVAL;
2188         }
2189 
2190         if ((result > 1) || (result < 0))
2191         {
2192             return EINVAL;
2193         }
2194 
2195         pUM->devParams.l2_fw_flow_ctrl = (uint32_t)result;
2196     }
2197     else if (strcmp(pr_name, "_autogreeen_enable") == 0)
2198     {
2199         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2200         {
2201             return EINVAL;
2202         }
2203 
2204         if ((result > 1) || (result < 0))
2205         {
2206             return EINVAL;
2207         }
2208 
2209         pUM->devParams.autogreeenEnable = (uint32_t)result;
2210         if (pUM->plumbed) BnxeUpdatePhy(pUM);
2211     }
2212     else if (strcmp(pr_name, "_lso_enable") == 0)
2213     {
2214         if (pUM->plumbed)
2215         {
2216             return EBUSY;
2217         }
2218 
2219         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2220         {
2221             return EINVAL;
2222         }
2223 
2224         if ((result > 1) || (result < 0))
2225         {
2226             return EINVAL;
2227         }
2228 
2229         pUM->devParams.lsoEnable = (uint32_t)result;
2230     }
2231     else if (strcmp(pr_name, "_log_enable") == 0)
2232     {
2233         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2234         {
2235             return EINVAL;
2236         }
2237 
2238         if ((result > 1) || (result < 0))
2239         {
2240             return EINVAL;
2241         }
2242 
2243         pUM->devParams.logEnable = (uint32_t)result;
2244     }
2245     else if (strcmp(pr_name, "_fcoe_enable") == 0)
2246     {
2247         if (ddi_strtol(pr_val, (char **)NULL, 0, &result))
2248         {
2249             return EINVAL;
2250         }
2251 
2252         if ((result > 1) || (result < 0))
2253         {
2254             return EINVAL;
2255         }
2256 
2257         pUM->devParams.fcoeEnable = (uint32_t)result;
2258 
2259         if (BNXE_FCOE(pUM))
2260         {
2261             BnxeFcoeStartStop(pUM);
2262         }
2263     }
2264     else
2265     {
2266         err = ENOTSUP;
2267     }
2268 
2269     return err;
2270 }
2271 
2272 
2273 static int BnxeMacSetProperty(void *        barg,
2274                               const char *  pr_name,
2275                               mac_prop_id_t pr_num,
2276                               uint_t        pr_valsize,
2277                               const void *  pr_val)
2278 {
2279     um_device_t *   pUM = barg;
2280     boolean_t       reprogram = B_FALSE;
2281     boolean_t       rxpause;
2282     boolean_t       txpause;
2283     uint32_t        mtu;
2284     link_flowctrl_t fl;
2285     int err = 0;
2286 
2287     BNXE_LOCK_ENTER_GLD(pUM);
2288 
2289     switch (pr_num)
2290     {
2291     /* read-only props */
2292     case MAC_PROP_STATUS:
2293     case MAC_PROP_SPEED:
2294     case MAC_PROP_DUPLEX:
2295     case MAC_PROP_MEDIA:
2296 
2297     case MAC_PROP_ADV_10GFDX_CAP:
2298     case MAC_PROP_ADV_1000FDX_CAP:
2299     case MAC_PROP_ADV_1000HDX_CAP:
2300     case MAC_PROP_ADV_100FDX_CAP:
2301     case MAC_PROP_ADV_100HDX_CAP:
2302     case MAC_PROP_ADV_10FDX_CAP:
2303     case MAC_PROP_ADV_10HDX_CAP:
2304     case MAC_PROP_ADV_100T4_CAP:
2305 
2306     case MAC_PROP_EN_1000HDX_CAP:
2307     case MAC_PROP_EN_100T4_CAP:
2308 
2309     default:
2310 
2311         err = ENOTSUP;
2312         break;
2313 
2314     case MAC_PROP_EN_10GFDX_CAP:
2315 
2316         pUM->hwinit.lnkcfg.param_10000fdx = *(uint8_t *)pr_val;
2317         pUM->curcfg.lnkcfg.param_10000fdx = *(uint8_t *)pr_val;
2318         reprogram = B_TRUE;
2319         break;
2320 
2321     case MAC_PROP_EN_1000FDX_CAP:
2322 
2323         pUM->hwinit.lnkcfg.param_1000fdx = *(uint8_t *)pr_val;
2324         pUM->curcfg.lnkcfg.param_1000fdx = *(uint8_t *)pr_val;
2325         reprogram = B_TRUE;
2326         break;
2327 
2328     case MAC_PROP_EN_100FDX_CAP:
2329 
2330         pUM->hwinit.lnkcfg.param_100fdx = *(uint8_t *)pr_val;
2331         pUM->curcfg.lnkcfg.param_100fdx = *(uint8_t *)pr_val;
2332         reprogram = B_TRUE;
2333         break;
2334 
2335     case MAC_PROP_EN_100HDX_CAP:
2336 
2337         pUM->hwinit.lnkcfg.param_100hdx = *(uint8_t *)pr_val;
2338         pUM->curcfg.lnkcfg.param_100hdx = *(uint8_t *)pr_val;
2339         reprogram = B_TRUE;
2340         break;
2341 
2342     case MAC_PROP_EN_10FDX_CAP:
2343 
2344         pUM->hwinit.lnkcfg.param_10fdx = *(uint8_t *)pr_val;
2345         pUM->curcfg.lnkcfg.param_10fdx = *(uint8_t *)pr_val;
2346         reprogram = B_TRUE;
2347         break;
2348 
2349     case MAC_PROP_EN_10HDX_CAP:
2350 
2351         pUM->hwinit.lnkcfg.param_10hdx = *(uint8_t *)pr_val;
2352         pUM->curcfg.lnkcfg.param_10hdx = *(uint8_t *)pr_val;
2353         reprogram = B_TRUE;
2354         break;
2355 
2356     case MAC_PROP_AUTONEG:
2357 
2358         pUM->hwinit.lnkcfg.link_autoneg = *(uint8_t *)pr_val;
2359         pUM->curcfg.lnkcfg.link_autoneg = *(uint8_t *)pr_val;
2360         reprogram = B_TRUE;
2361         break;
2362 
2363     case MAC_PROP_FLOWCTRL:
2364 
2365         bcopy(pr_val, &fl, sizeof(fl));
2366 
2367         switch (fl)
2368         {
2369         case LINK_FLOWCTRL_NONE:
2370 
2371             rxpause = B_FALSE;
2372             txpause = B_FALSE;
2373             break;
2374 
2375         case LINK_FLOWCTRL_RX:
2376 
2377             rxpause = B_TRUE;
2378             txpause = B_FALSE;
2379             break;
2380 
2381         case LINK_FLOWCTRL_TX:
2382 
2383             rxpause = B_FALSE;
2384             txpause = B_TRUE;
2385             break;
2386 
2387         case LINK_FLOWCTRL_BI:
2388 
2389             rxpause = B_TRUE;
2390             txpause = B_TRUE;
2391             break;
2392 
2393         default:
2394 
2395             err = ENOTSUP;
2396             break;
2397         }
2398 
2399         if (err == 0)
2400         {
2401             pUM->hwinit.lnkcfg.param_rxpause = rxpause;
2402             pUM->hwinit.lnkcfg.param_txpause = txpause;
2403             pUM->curcfg.lnkcfg.param_rxpause = rxpause;
2404             pUM->curcfg.lnkcfg.param_txpause = txpause;
2405             reprogram = B_TRUE;
2406         }
2407 
2408         break;
2409 
2410     case MAC_PROP_MTU:
2411 
2412         if (pUM->plumbed)
2413         {
2414             err = EBUSY;
2415             break;
2416         }
2417 
2418         bcopy(pr_val, &mtu, sizeof (mtu));
2419 
2420         if ((mtu < USER_OPTION_MTU_MIN) || (mtu > USER_OPTION_MTU_MAX))
2421         {
2422             err = EINVAL;
2423             break;
2424         }
2425 
2426         if (pUM->devParams.mtu[LM_CLI_IDX_NDIS] == mtu)
2427         {
2428             break;
2429         }
2430 
2431         pUM->devParams.mtu[LM_CLI_IDX_NDIS] = mtu;
2432         err = mac_maxsdu_update(pUM->pMac, pUM->devParams.mtu[LM_CLI_IDX_NDIS]);
2433         pUM->lm_dev.params.mtu[LM_CLI_IDX_NDIS] = pUM->devParams.mtu[LM_CLI_IDX_NDIS];
2434         break;
2435 
2436     case MAC_PROP_PRIVATE:
2437 
2438         err = BnxeSetPrivateProperty(pUM, pr_name, pr_valsize, pr_val);
2439         break;
2440     }
2441 
2442     if (!err && reprogram)
2443     {
2444         if (pUM->plumbed) BnxeUpdatePhy(pUM);
2445     }
2446 
2447     BNXE_LOCK_EXIT_GLD(pUM);
2448     return err;
2449 }
2450 
2451 #endif /* MC_SETPROP */
2452 
2453 
2454 #ifdef MC_GETPROP
2455 
2456 static int BnxeGetPrivateProperty(um_device_t * pUM,
2457                                   const char *  pr_name,
2458                                   uint_t        pr_valsize,
2459                                   void *        pr_val)
2460 {
2461     BnxeLinkCfg * lnk_cfg = &pUM->curcfg.lnkcfg;
2462     BnxeLinkCfg * hw_cfg  = &pUM->hwinit.lnkcfg;
2463     int value;
2464     int err = 0;
2465 
2466     if (strcmp(pr_name, "_adv_2500fdx_cap") == 0)
2467     {
2468         value = lnk_cfg->param_2500fdx;
2469     }
2470     else if (strcmp(pr_name, "_en_2500fdx_cap") == 0)
2471     {
2472         value = hw_cfg->param_2500fdx;
2473     }
2474     else if (strcmp(pr_name, "_adv_txpause_cap") == 0)
2475     {
2476         value = lnk_cfg->param_txpause;
2477     }
2478     else if (strcmp(pr_name, "_en_txpause_cap") == 0)
2479     {
2480         value = hw_cfg->param_txpause;
2481     }
2482     else if (strcmp(pr_name, "_txpause") == 0)
2483     {
2484         value = pUM->props.link_txpause;
2485     }
2486     else if (strcmp(pr_name, "_adv_rxpause_cap") == 0)
2487     {
2488         value = lnk_cfg->param_rxpause;
2489     }
2490     else if (strcmp(pr_name, "_en_rxpause_cap") == 0)
2491     {
2492         value = hw_cfg->param_rxpause;
2493     }
2494     else if (strcmp(pr_name, "_rxpause") == 0)
2495     {
2496         value = pUM->props.link_rxpause;
2497     }
2498     else if (strcmp(pr_name, "_autoneg_flow") == 0)
2499     {
2500         value = pUM->hwinit.flow_autoneg;
2501     }
2502     else if (strcmp(pr_name, "_checksum") == 0)
2503     {
2504         value = pUM->devParams.checksum;
2505     }
2506     else if (strcmp(pr_name, "_tx_ring_policy") == 0)
2507     {
2508         value = pUM->devParams.routeTxRingPolicy;
2509     }
2510     else if (strcmp(pr_name, "_num_rings") == 0)
2511     {
2512         value = pUM->devParams.numRings;
2513     }
2514     else if (strcmp(pr_name, "_rx_descs") == 0)
2515     {
2516         value = pUM->devParams.numRxDesc[LM_CLI_IDX_NDIS];
2517     }
2518     else if (strcmp(pr_name, "_rx_free_reclaim") == 0)
2519     {
2520         value = pUM->devParams.maxRxFree;
2521     }
2522     else if (strcmp(pr_name, "_tx_descs") == 0)
2523     {
2524         value = pUM->devParams.numTxDesc[LM_CLI_IDX_NDIS];
2525     }
2526     else if (strcmp(pr_name, "_tx_free_reclaim") == 0)
2527     {
2528         value = pUM->devParams.maxTxFree;
2529     }
2530     else if (strcmp(pr_name, "_rx_copy_threshold") == 0)
2531     {
2532         value = pUM->devParams.rxCopyThreshold;
2533     }
2534     else if (strcmp(pr_name, "_tx_copy_threshold") == 0)
2535     {
2536         value = pUM->devParams.txCopyThreshold;
2537     }
2538     else if (strcmp(pr_name, "_interrupt_coalesce") == 0)
2539     {
2540         value = pUM->devParams.intrCoalesce;
2541     }
2542     else if (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0)
2543     {
2544         value = pUM->devParams.intrRxPerSec;
2545     }
2546     else if (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0)
2547     {
2548         value = pUM->devParams.intrTxPerSec;
2549     }
2550     else if (strcmp(pr_name, "_disable_msix") == 0)
2551     {
2552         value = pUM->devParams.disableMsix;
2553     }
2554     else if (strcmp(pr_name, "_l2_fw_flow_ctrl") == 0)
2555     {
2556         value = pUM->devParams.l2_fw_flow_ctrl;
2557     }
2558     else if (strcmp(pr_name, "_autogreeen_enable") == 0)
2559     {
2560         value = pUM->devParams.autogreeenEnable;
2561     }
2562     else if (strcmp(pr_name, "_lso_enable") == 0)
2563     {
2564         value = pUM->devParams.lsoEnable;
2565     }
2566     else if (strcmp(pr_name, "_log_enable") == 0)
2567     {
2568         value = pUM->devParams.logEnable;
2569     }
2570     else if (strcmp(pr_name, "_fcoe_enable") == 0)
2571     {
2572         value = pUM->devParams.fcoeEnable;
2573     }
2574     else
2575     {
2576         err = ENOTSUP;
2577     }
2578 
2579     if (!err)
2580     {
2581         (void)snprintf(pr_val, pr_valsize, "%d", value);
2582     }
2583 
2584     return err;
2585 }
2586 
2587 
2588 static int BnxeMacGetProperty(void *        barg,
2589                               const char *  pr_name,
2590                               mac_prop_id_t pr_num,
2591                               uint_t        pr_valsize,
2592                               void *        pr_val)
2593 {
2594     um_device_t *   pUM = barg;
2595     link_flowctrl_t link_flowctrl;
2596     link_state_t    link_state;
2597     link_duplex_t   link_duplex;
2598     uint64_t        link_speed;
2599     mac_ether_media_t link_media;
2600     BnxeLinkCfg * lnk_cfg = &pUM->curcfg.lnkcfg;
2601     BnxeLinkCfg * hw_cfg  = &pUM->hwinit.lnkcfg;
2602 
2603     switch (pr_num)
2604     {
2605     case MAC_PROP_MTU:
2606 
2607         ASSERT(pr_valsize >= sizeof(u32_t));
2608 
2609         bcopy(&pUM->devParams.mtu[LM_CLI_IDX_NDIS], pr_val, sizeof(u32_t));
2610         break;
2611 
2612     case MAC_PROP_DUPLEX:
2613 
2614         ASSERT(pr_valsize >= sizeof(link_duplex_t));
2615 
2616         link_duplex = pUM->props.link_duplex ?
2617                           LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
2618         bcopy(&link_duplex, pr_val, sizeof(link_duplex_t));
2619         break;
2620 
2621     case MAC_PROP_SPEED:
2622 
2623         ASSERT(pr_valsize >= sizeof(link_speed));
2624 
2625         link_speed = (pUM->props.link_speed * 1000000ULL);
2626         bcopy(&link_speed, pr_val, sizeof(link_speed));
2627         break;
2628 
2629     case MAC_PROP_STATUS:
2630 
2631         ASSERT(pr_valsize >= sizeof(link_state_t));
2632 
2633         link_state = pUM->props.link_speed ?
2634                          LINK_STATE_UP : LINK_STATE_DOWN;
2635         bcopy(&link_state, pr_val, sizeof(link_state_t));
2636         break;
2637 
2638     case MAC_PROP_MEDIA:
2639         ASSERT(pr_valsize >= sizeof(mac_ether_media_t));
2640 
2641 	link_media = bnxe_phy_to_media(pUM);
2642         bcopy(&link_media, pr_val, sizeof(mac_ether_media_t));
2643 	break;
2644 
2645     case MAC_PROP_AUTONEG:
2646 
2647         *(uint8_t *)pr_val = lnk_cfg->link_autoneg;
2648         break;
2649 
2650     case MAC_PROP_FLOWCTRL:
2651 
2652         ASSERT(pr_valsize >= sizeof(link_flowctrl_t));
2653 
2654         if (!lnk_cfg->param_rxpause && !lnk_cfg->param_txpause)
2655         {
2656             link_flowctrl = LINK_FLOWCTRL_NONE;
2657         }
2658         if (lnk_cfg->param_rxpause && !lnk_cfg->param_txpause)
2659         {
2660             link_flowctrl = LINK_FLOWCTRL_RX;
2661         }
2662         if (!lnk_cfg->param_rxpause && lnk_cfg->param_txpause)
2663         {
2664             link_flowctrl = LINK_FLOWCTRL_TX;
2665         }
2666         if (lnk_cfg->param_rxpause && lnk_cfg->param_txpause)
2667         {
2668             link_flowctrl = LINK_FLOWCTRL_BI;
2669         }
2670 
2671         bcopy(&link_flowctrl, pr_val, sizeof(link_flowctrl_t));
2672         break;
2673 
2674     case MAC_PROP_ADV_10GFDX_CAP:
2675 
2676         *(uint8_t *)pr_val = lnk_cfg->param_10000fdx;
2677         break;
2678 
2679     case MAC_PROP_EN_10GFDX_CAP:
2680 
2681         *(uint8_t *)pr_val = hw_cfg->param_10000fdx;
2682         break;
2683 
2684     case MAC_PROP_ADV_1000FDX_CAP:
2685 
2686         *(uint8_t *)pr_val = lnk_cfg->param_1000fdx;
2687         break;
2688 
2689     case MAC_PROP_EN_1000FDX_CAP:
2690 
2691         *(uint8_t *)pr_val = hw_cfg->param_1000fdx;
2692         break;
2693 
2694     case MAC_PROP_ADV_1000HDX_CAP:
2695     case MAC_PROP_EN_1000HDX_CAP:
2696 
2697         *(uint8_t *)pr_val = 0;
2698         break;
2699 
2700     case MAC_PROP_ADV_100FDX_CAP:
2701 
2702         *(uint8_t *)pr_val = lnk_cfg->param_100fdx;
2703         break;
2704 
2705     case MAC_PROP_EN_100FDX_CAP:
2706 
2707         *(uint8_t *)pr_val = hw_cfg->param_100fdx;
2708         break;
2709 
2710     case MAC_PROP_ADV_100HDX_CAP:
2711 
2712         *(uint8_t *)pr_val = lnk_cfg->param_100hdx;
2713         break;
2714 
2715     case MAC_PROP_EN_100HDX_CAP:
2716 
2717         *(uint8_t *)pr_val = hw_cfg->param_100hdx;
2718         break;
2719 
2720     case MAC_PROP_ADV_100T4_CAP:
2721     case MAC_PROP_EN_100T4_CAP:
2722 
2723         *(uint8_t *)pr_val = 0;
2724         break;
2725 
2726     case MAC_PROP_ADV_10FDX_CAP:
2727 
2728         *(uint8_t *)pr_val = lnk_cfg->param_10fdx;
2729         break;
2730 
2731     case MAC_PROP_EN_10FDX_CAP:
2732 
2733         *(uint8_t *)pr_val = hw_cfg->param_10fdx;
2734         break;
2735 
2736     case MAC_PROP_ADV_10HDX_CAP:
2737 
2738         *(uint8_t *)pr_val = lnk_cfg->param_10hdx;
2739         break;
2740 
2741     case MAC_PROP_EN_10HDX_CAP:
2742 
2743         *(uint8_t *)pr_val = hw_cfg->param_10hdx;
2744         break;
2745 
2746     case MAC_PROP_PRIVATE:
2747 
2748         return BnxeGetPrivateProperty(pUM,
2749                                       pr_name,
2750                                       pr_valsize,
2751                                       pr_val);
2752 
2753     default:
2754 
2755         return ENOTSUP;
2756     }
2757 
2758     return 0;
2759 }
2760 
2761 #endif /* MC_GETPROP */
2762 
2763 
2764 #ifdef MC_PROPINFO
2765 
2766 static void BnxeMacPrivatePropertyInfo(um_device_t *          pUM,
2767                                        const char *           pr_name,
2768                                        mac_prop_info_handle_t prh)
2769 {
2770     char valstr[64];
2771     BnxeLinkCfg * default_cfg = &bnxeLinkCfg;
2772     int default_val;
2773 
2774     bzero(valstr, sizeof (valstr));
2775 
2776     if ((strcmp(pr_name, "_adv_2500fdx_cap")            == 0) ||
2777         (strcmp(pr_name, "_adv_txpause_cap")            == 0) ||
2778         (strcmp(pr_name, "_txpause")                    == 0) ||
2779         (strcmp(pr_name, "_adv_rxpause_cap")            == 0) ||
2780         (strcmp(pr_name, "_rxpause")                    == 0) ||
2781         (strcmp(pr_name, "_checksum")                   == 0) ||
2782         (strcmp(pr_name, "_num_rings")                  == 0) ||
2783         (strcmp(pr_name, "_rx_descs")                   == 0) ||
2784         (strcmp(pr_name, "_tx_descs")                   == 0) ||
2785         (strcmp(pr_name, "_interrupt_coalesce")         == 0) ||
2786         (strcmp(pr_name, "_rx_interrupt_coalesce_usec") == 0) ||
2787         (strcmp(pr_name, "_tx_interrupt_coalesce_usec") == 0) ||
2788         (strcmp(pr_name, "_disable_msix")               == 0) ||
2789         (strcmp(pr_name, "_l2_fw_flow_ctrl")            == 0) ||
2790         (strcmp(pr_name, "_lso_enable")                 == 0))
2791     {
2792         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2793         return;
2794     }
2795 
2796     if (strcmp(pr_name, "_autoneg_flow") == 0)
2797     {
2798         default_val = B_TRUE;
2799     }
2800     else if (strcmp(pr_name, "_tx_ring_policy") == 0)
2801     {
2802         default_val = BNXE_ROUTE_RING_TCPUDP;
2803     }
2804     else if (strcmp(pr_name, "_rx_free_reclaim") == 0)
2805     {
2806         default_val = USER_OPTION_RX_MAX_FREE_DEFAULT;
2807     }
2808     else if (strcmp(pr_name, "_tx_free_reclaim") == 0)
2809     {
2810         default_val = USER_OPTION_TX_MAX_FREE_DEFAULT;
2811     }
2812     else if (strcmp(pr_name, "_rx_copy_threshold") == 0)
2813     {
2814         default_val = USER_OPTION_RX_DCOPY_THRESH_DEFAULT;
2815     }
2816     else if (strcmp(pr_name, "_tx_copy_threshold") == 0)
2817     {
2818         default_val = USER_OPTION_TX_DCOPY_THRESH_DEFAULT;
2819     }
2820     else if (strcmp(pr_name, "_autogreeen_enable") == 0)
2821     {
2822         default_val = B_TRUE;
2823     }
2824     else if (strcmp(pr_name, "_log_enable") == 0)
2825     {
2826         default_val = B_TRUE;
2827     }
2828     else if (strcmp(pr_name, "_fcoe_enable") == 0)
2829     {
2830         default_val = B_TRUE;
2831     }
2832     else
2833     {
2834         return;
2835     }
2836 
2837     snprintf(valstr, sizeof (valstr), "%d", default_val);
2838     mac_prop_info_set_default_str(prh, valstr);
2839 }
2840 
2841 
2842 static void BnxeMacPropertyInfo(void *                 barg,
2843                                 const char *           pr_name,
2844                                 mac_prop_id_t          pr_num,
2845                                 mac_prop_info_handle_t prh)
2846 {
2847     um_device_t * pUM = barg;
2848     link_flowctrl_t link_flowctrl;
2849     BnxeLinkCfg * default_cfg = &bnxeLinkCfg;
2850 
2851     switch (pr_num)
2852     {
2853     case MAC_PROP_STATUS:
2854     case MAC_PROP_SPEED:
2855     case MAC_PROP_DUPLEX:
2856 
2857     case MAC_PROP_ADV_10GFDX_CAP:
2858     case MAC_PROP_ADV_1000FDX_CAP:
2859     case MAC_PROP_ADV_1000HDX_CAP:
2860     case MAC_PROP_ADV_100FDX_CAP:
2861     case MAC_PROP_ADV_100HDX_CAP:
2862     case MAC_PROP_ADV_100T4_CAP:
2863     case MAC_PROP_ADV_10FDX_CAP:
2864     case MAC_PROP_ADV_10HDX_CAP:
2865 
2866     case MAC_PROP_EN_1000HDX_CAP:
2867     case MAC_PROP_EN_100T4_CAP:
2868 
2869         mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2870         break;
2871 
2872     case MAC_PROP_EN_10GFDX_CAP:
2873 
2874         mac_prop_info_set_default_uint8(prh, default_cfg->param_10000fdx);
2875         break;
2876 
2877     case MAC_PROP_EN_1000FDX_CAP:
2878 
2879         mac_prop_info_set_default_uint8(prh, default_cfg->param_1000fdx);
2880         break;
2881 
2882     case MAC_PROP_EN_100FDX_CAP:
2883 
2884         mac_prop_info_set_default_uint8(prh, default_cfg->param_100fdx);
2885         break;
2886 
2887     case MAC_PROP_EN_100HDX_CAP:
2888 
2889         mac_prop_info_set_default_uint8(prh, default_cfg->param_100hdx);
2890         break;
2891 
2892     case MAC_PROP_EN_10FDX_CAP:
2893 
2894         mac_prop_info_set_default_uint8(prh, default_cfg->param_10fdx);
2895         break;
2896 
2897     case MAC_PROP_EN_10HDX_CAP:
2898 
2899         mac_prop_info_set_default_uint8(prh, default_cfg->param_10hdx);
2900         break;
2901 
2902     case MAC_PROP_MTU:
2903 
2904         mac_prop_info_set_range_uint32(prh,
2905                                        USER_OPTION_MTU_MIN,
2906                                        USER_OPTION_MTU_MAX);
2907         break;
2908 
2909     case MAC_PROP_AUTONEG:
2910 
2911         mac_prop_info_set_default_uint8(prh, default_cfg->link_autoneg);
2912         break;
2913 
2914     case MAC_PROP_FLOWCTRL:
2915 
2916         if (!default_cfg->param_rxpause && !default_cfg->param_txpause)
2917         {
2918             link_flowctrl = LINK_FLOWCTRL_NONE;
2919         }
2920 
2921         if (default_cfg->param_rxpause && !default_cfg->param_txpause)
2922         {
2923             link_flowctrl = LINK_FLOWCTRL_RX;
2924         }
2925 
2926         if (!default_cfg->param_rxpause && default_cfg->param_txpause)
2927         {
2928             link_flowctrl = LINK_FLOWCTRL_TX;
2929         }
2930 
2931         if (default_cfg->param_rxpause && default_cfg->param_txpause)
2932         {
2933             link_flowctrl = LINK_FLOWCTRL_BI;
2934         }
2935 
2936         mac_prop_info_set_default_link_flowctrl(prh, link_flowctrl);
2937         break;
2938 
2939     case MAC_PROP_PRIVATE:
2940 
2941         BnxeMacPrivatePropertyInfo(pUM, pr_name, prh);
2942         break;
2943     }
2944 }
2945 
2946 #endif /* MC_PROPINFO */
2947 
2948 
2949 static mac_callbacks_t bnxe_callbacks =
2950 {
2951     (
2952       MC_IOCTL
2953 #ifdef MC_RESOURCES
2954     | MC_RESOURCES
2955 #endif
2956 #ifdef MC_SETPROP
2957     | MC_SETPROP
2958 #endif
2959 #ifdef MC_GETPROP
2960     | MC_GETPROP
2961 #endif
2962 #ifdef MC_PROPINFO
2963     | MC_PROPINFO
2964 #endif
2965     | MC_GETCAPAB
2966     ),
2967     BnxeMacStats,
2968     BnxeMacStart,
2969     BnxeMacStop,
2970     BnxeMacPromiscuous,
2971     BnxeMacMulticast,
2972     NULL,
2973     BnxeMacTx,
2974 #ifdef MC_RESOURCES
2975     BnxeMacResources,
2976 #else
2977     NULL,
2978 #endif
2979     BnxeMacIoctl,
2980     BnxeMacGetCapability,
2981 #ifdef MC_OPEN
2982     NULL,
2983     NULL,
2984 #endif
2985 #ifdef MC_SETPROP
2986     BnxeMacSetProperty,
2987 #endif
2988 #ifdef MC_GETPROP
2989     BnxeMacGetProperty,
2990 #endif
2991 #ifdef MC_PROPINFO
2992     BnxeMacPropertyInfo
2993 #endif
2994 };
2995 
2996 
2997 boolean_t BnxeGldInit(um_device_t * pUM)
2998 {
2999     mac_register_t * pMac;
3000     int rc;
3001 
3002     atomic_swap_32(&pUM->plumbed, B_FALSE);
3003 
3004     if ((pMac = mac_alloc(MAC_VERSION)) == NULL)
3005     {
3006         BnxeLogWarn(pUM, "Failed to allocate GLD MAC memory");
3007         return B_FALSE;
3008     }
3009 
3010     pMac->m_driver     = pUM;
3011     pMac->m_dip        = pUM->pDev;
3012     pMac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
3013     pMac->m_callbacks  = &bnxe_callbacks;
3014     pMac->m_min_sdu    = 0;
3015     pMac->m_max_sdu    = pUM->devParams.mtu[LM_CLI_IDX_NDIS];
3016     pMac->m_src_addr   = &(pUM->lm_dev.params.mac_addr[0]);
3017 
3018 #ifdef MC_OPEN
3019     pMac->m_margin = VLAN_TAGSZ;
3020 #endif
3021 
3022 #ifdef MC_SETPROP
3023     pMac->m_priv_props = bnxeLink_priv_props;
3024 #endif
3025 
3026 #if (defined(__S11) || defined(__S12)) && !defined(ILLUMOS)
3027     bnxe_callbacks.mc_unicst =
3028         (!pUM->devParams.numRings) ? BnxeMacUnicast : NULL;
3029 #else
3030     bnxe_callbacks.mc_unicst = BnxeMacUnicast;
3031 #endif
3032 
3033     rc = mac_register(pMac, &pUM->pMac);
3034 
3035     mac_free(pMac);
3036 
3037     if (rc != 0)
3038     {
3039         BnxeLogWarn(pUM, "Failed to register with GLD (%d)", rc);
3040         return B_FALSE;
3041     }
3042 
3043     /* Always report the initial link state as unknown. */
3044     mac_link_update(pUM->pMac, LINK_STATE_UNKNOWN);
3045 
3046     return B_TRUE;
3047 }
3048 
3049 
3050 boolean_t BnxeGldFini(um_device_t * pUM)
3051 {
3052     int cnt;
3053 
3054     if (pUM->plumbed)
3055     {
3056         BnxeLogWarn(pUM, "Detaching device from GLD that is started!");
3057         return B_FALSE;
3058     }
3059 
3060     /* We must not detach until all packets held by stack are retrieved. */
3061     if (!BnxeWaitForPacketsFromClient(pUM, LM_CLI_IDX_NDIS))
3062     {
3063         return B_FALSE;
3064     }
3065 
3066     if (pUM->pMac)
3067     {
3068         if (mac_unregister(pUM->pMac))
3069         {
3070             BnxeLogWarn(pUM, "Failed to unregister with the GLD");
3071             return B_FALSE;
3072         }
3073     }
3074 
3075     return B_TRUE;
3076 }
3077 
3078 
3079 void BnxeGldLink(um_device_t * pUM,
3080                  link_state_t  state)
3081 {
3082     mac_link_update(pUM->pMac, state);
3083 }
3084 
3085