1 /*
2 * Copyright 2014-2017 Cavium, Inc.
3 * The contents of this file are subject to the terms of the Common Development
4 * and Distribution License, v.1, (the "License").
5 *
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the License at available
9 * at http://opensource.org/licenses/CDDL-1.0
10 *
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 /*
16 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
17 * Copyright (c) 2019, Joyent, Inc.
18 * Copyright 2023 Oxide Computer Company
19 */
20
21 #include "bnxgld.h"
22 #include "bnxhwi.h"
23 #include "bnxsnd.h"
24 #include "bnxrcv.h"
25 #include "bnxcfg.h"
26
27 #include <sys/mac_provider.h>
28 #include <sys/mac_ether.h>
29 #include <sys/dlpi.h>
30 #include <sys/policy.h>
31
32 /*
33 * Name: bnx_m_start
34 *
35 * Input: ptr to driver device structure.
36 *
37 * Return: DDI_SUCCESS or DDI_FAILURE
38 *
39 * Description:
40 * This routine is called by GLD to enable device for
41 * packet reception and enable interrupts.
42 */
43 static int
bnx_m_start(void * arg)44 bnx_m_start(void *arg)
45 {
46 int rc;
47 um_device_t *umdevice;
48
49 umdevice = (um_device_t *)arg;
50
51 mutex_enter(&umdevice->os_param.gld_mutex);
52
53 if (umdevice->dev_start == B_TRUE) {
54 /* We're already started. Success! */
55 rc = 0;
56 goto done;
57 }
58
59 /* Always report the initial link state as unknown. */
60 bnx_gld_link(umdevice, LINK_STATE_UNKNOWN);
61
62 umdevice->link_updates_ok = B_TRUE;
63
64 if (bnx_hdwr_acquire(umdevice)) {
65 rc = EIO;
66 goto done;
67 }
68
69 umdevice->dev_start = B_TRUE;
70
71 rc = 0;
72
73 done:
74 mutex_exit(&umdevice->os_param.gld_mutex);
75
76 return (rc);
77 }
78
79 /*
80 * Name: bnx_m_stop
81 *
82 * Input: ptr to driver device structure.
83 *
84 * Return: DDI_SUCCESS or DDI_FAILURE
85 *
86 * Description:
87 * This routine stops packet reception by clearing RX MASK
88 * register. Also interrupts are disabled for this device.
89 */
90 static void
bnx_m_stop(void * arg)91 bnx_m_stop(void *arg)
92 {
93 um_device_t *umdevice;
94
95 umdevice = (um_device_t *)arg;
96
97 mutex_enter(&umdevice->os_param.gld_mutex);
98
99 if (umdevice->dev_start == B_TRUE) {
100 umdevice->dev_start = B_FALSE;
101 umdevice->link_updates_ok = B_FALSE;
102
103 bnx_hdwr_release(umdevice);
104
105 /* Report the link state back to unknown. */
106 bnx_gld_link(umdevice, LINK_STATE_UNKNOWN);
107
108 umdevice->dev_var.indLink = 0;
109 umdevice->dev_var.indMedium = 0;
110 }
111
112 mutex_exit(&umdevice->os_param.gld_mutex);
113 }
114
115
116
117 /*
118 * Name: bnx_m_unicast
119 *
120 * Input: ptr to driver device structure,
121 * pointer to buffer containing MAC address.
122 *
123 * Return: DDI_SUCCESS or DDI_FAILURE
124 *
125 * Description:
126 */
127 static int
bnx_m_unicast(void * arg,const uint8_t * macaddr)128 bnx_m_unicast(void *arg, const uint8_t *macaddr)
129 {
130 int rc;
131 um_device_t *umdevice;
132 lm_device_t *lmdevice;
133
134 umdevice = (um_device_t *)arg;
135 lmdevice = &(umdevice->lm_dev);
136
137 mutex_enter(&umdevice->os_param.gld_mutex);
138
139 /* Validate MAC address */
140 if (IS_ETH_MULTICAST(macaddr)) {
141 cmn_err(CE_WARN, "%s: Attempt to program a multicast / "
142 "broadcast address as a MAC address.", umdevice->dev_name);
143 rc = EINVAL;
144 goto done;
145 }
146
147 if (umdevice->dev_start == B_TRUE) {
148 if (lm_set_mac_addr(lmdevice, 0,
149 &(lmdevice->params.mac_addr[0])) != LM_STATUS_SUCCESS) {
150 cmn_err(CE_WARN, "%s: failed to program MAC address.",
151 umdevice->dev_name);
152 rc = EIO;
153 goto done;
154 }
155 }
156
157 bcopy(macaddr, &(lmdevice->params.mac_addr[0]), ETHERADDRL);
158
159 rc = 0;
160
161 done:
162 mutex_exit(&umdevice->os_param.gld_mutex);
163
164 return (rc);
165 }
166
167 static int
bnx_mc_add(um_device_t * umdevice,const uint8_t * const mc_addr)168 bnx_mc_add(um_device_t *umdevice, const uint8_t *const mc_addr)
169 {
170 int rc;
171 int index;
172 lm_status_t lmstatus;
173 lm_device_t *lmdevice;
174
175 lmdevice = &(umdevice->lm_dev);
176
177 index = bnx_find_mchash_collision(&(lmdevice->mc_table), mc_addr);
178 if (index == -1) {
179 lmstatus = lm_add_mc(lmdevice, (u8_t *)mc_addr);
180 if (lmstatus == LM_STATUS_SUCCESS) {
181 umdevice->dev_var.rx_filter_mask |=
182 LM_RX_MASK_ACCEPT_MULTICAST;
183 rc = 0;
184 } else {
185 rc = ENOMEM;
186 }
187 } else {
188 lmdevice->mc_table.addr_arr[index].ref_cnt++;
189 rc = 0;
190 }
191
192 return (rc);
193 }
194
195 static int
bnx_mc_del(um_device_t * umdevice,const uint8_t * const mc_addr)196 bnx_mc_del(um_device_t *umdevice, const uint8_t *const mc_addr)
197 {
198 int rc;
199 int index;
200 lm_status_t lmstatus;
201 lm_device_t *lmdevice;
202
203 lmdevice = &(umdevice->lm_dev);
204
205 index = bnx_find_mchash_collision(&(lmdevice->mc_table), mc_addr);
206 if (index == -1) {
207 rc = ENXIO;
208 } else {
209 lmstatus = lm_del_mc(lmdevice,
210 lmdevice->mc_table.addr_arr[index].mc_addr);
211 if (lmstatus == LM_STATUS_SUCCESS) {
212 if (lmdevice->mc_table.entry_cnt == 0) {
213 umdevice->dev_var.rx_filter_mask &=
214 ~LM_RX_MASK_ACCEPT_MULTICAST;
215 }
216
217 rc = 0;
218 } else {
219 rc = ENXIO;
220 }
221 }
222
223 return (rc);
224 }
225
226
227
228 /*
229 * Name: bnx_m_multicast
230 *
231 * Input: ptr to driver device structure,
232 * boolean describing whether to enable or disable this address,
233 * pointer to buffer containing multicast address.
234 *
235 * Return: DDI_SUCCESS or DDI_FAILURE
236 *
237 * Description:
238 * This function is used to enable or disable multicast packet
239 * reception for particular multicast addresses.
240 */
241 static int
bnx_m_multicast(void * arg,boolean_t multiflag,const uint8_t * multicastaddr)242 bnx_m_multicast(void * arg, boolean_t multiflag, const uint8_t *multicastaddr)
243 {
244 um_device_t *umdevice;
245 int rc;
246
247 umdevice = (um_device_t *)arg;
248
249 mutex_enter(&umdevice->os_param.gld_mutex);
250
251 if (umdevice->dev_start != B_TRUE) {
252 rc = EAGAIN;
253 goto done;
254 }
255
256 switch (multiflag) {
257 case B_TRUE:
258 rc = bnx_mc_add(umdevice, multicastaddr);
259 break;
260
261 case B_FALSE:
262 rc = bnx_mc_del(umdevice, multicastaddr);
263 break;
264
265 default:
266 rc = EINVAL;
267 break;
268 }
269
270 done:
271 mutex_exit(&umdevice->os_param.gld_mutex);
272
273 return (rc);
274 }
275
276
277
278 /*
279 * Name: bnx_m_promiscuous
280 *
281 * Input: ptr to driver device structure,
282 * boolean describing whether to enable or disable promiscuous mode.
283 *
284 * Return: DDI_SUCCESS or DDI_FAILURE
285 *
286 * Description:
287 * This function enables promiscuous mode for this device.
288 * 'flags' argument determines the type of mode being set,
289 * "PROMISC_PHY" enables reception of all packet types including
290 * bad/error packets. "PROMISC_MULTI" mode will enable all
291 * multicast packets, unicasts and broadcast packets to be
292 * received. "PROMISC_NONE" will enable only broadcast and
293 * unicast packets.
294 */
295 static int
bnx_m_promiscuous(void * arg,boolean_t promiscflag)296 bnx_m_promiscuous(void *arg, boolean_t promiscflag)
297 {
298 int rc;
299 um_device_t *umdevice;
300
301 umdevice = (um_device_t *)arg;
302
303 mutex_enter(&umdevice->os_param.gld_mutex);
304
305 if (umdevice->dev_start != B_TRUE) {
306 rc = EAGAIN;
307 goto done;
308 }
309
310 switch (promiscflag) {
311 case B_TRUE:
312 umdevice->dev_var.rx_filter_mask |=
313 LM_RX_MASK_PROMISCUOUS_MODE;
314 break;
315
316 case B_FALSE:
317 umdevice->dev_var.rx_filter_mask &=
318 ~LM_RX_MASK_PROMISCUOUS_MODE;
319 break;
320
321 default:
322 rc = EINVAL;
323 goto done;
324 }
325
326 (void) lm_set_rx_mask(&(umdevice->lm_dev), RX_FILTER_USER_IDX0,
327 umdevice->dev_var.rx_filter_mask);
328
329 rc = 0;
330
331 done:
332 mutex_exit(&umdevice->os_param.gld_mutex);
333
334 return (rc);
335 }
336
337
338 static mblk_t *
bnx_m_tx(void * arg,mblk_t * mp)339 bnx_m_tx(void *arg, mblk_t *mp)
340 {
341 int rc;
342 mblk_t *nmp;
343 um_device_t *umdevice;
344
345 umdevice = (um_device_t *)arg;
346
347 rw_enter(&umdevice->os_param.gld_snd_mutex, RW_READER);
348
349 if (umdevice->dev_start != B_TRUE ||
350 umdevice->nddcfg.link_speed == 0) {
351 freemsgchain(mp);
352 mp = NULL;
353 goto done;
354 }
355
356 nmp = NULL;
357
358 while (mp) {
359 /* Save the next pointer, in case we do double copy. */
360 nmp = mp->b_next;
361 mp->b_next = NULL;
362
363 rc = bnx_xmit_ring_xmit_mblk(umdevice, 0, mp);
364
365 if (rc == BNX_SEND_GOODXMIT) {
366 mp = nmp;
367 continue;
368 }
369
370 if (rc == BNX_SEND_DEFERPKT)
371 mp = nmp;
372 else
373 mp->b_next = nmp;
374
375 break;
376 }
377
378 done:
379 rw_exit(&umdevice->os_param.gld_snd_mutex);
380
381 return (mp);
382 }
383
384
385 static u64_t
shift_left32(u32_t val)386 shift_left32(u32_t val)
387 {
388 lm_u64_t tmp;
389
390 /* FIXME -- Get rid of shift_left32() */
391
392 tmp.as_u32.low = 0;
393 tmp.as_u32.high = val;
394
395 return (tmp.as_u64);
396 }
397
398 static mac_ether_media_t
bnx_um_to_media(um_device_t * um)399 bnx_um_to_media(um_device_t *um)
400 {
401 if (um->nddcfg.link_speed == 0) {
402 return (ETHER_MEDIA_NONE);
403 }
404
405 /*
406 * bnx only supports 2.5G and 1G fiber. It does not support 100BASE-FX.
407 * Similarly, it is too old to support 2500BASE-T and the NetExtreme II
408 * programmer's guide makes it clear it only ever supported 100BASE-TX
409 * and never -T2 or -T4.
410 */
411 if (um->dev_var.isfiber) {
412 switch (um->nddcfg.link_speed) {
413 case 2500:
414 return (ETHER_MEDIA_2500BASE_X);
415 case 1000:
416 return (ETHER_MEDIA_1000BASE_X);
417 default:
418 break;
419 }
420 } else {
421 switch (um->nddcfg.link_speed) {
422 case 1000:
423 return (ETHER_MEDIA_1000BASE_T);
424 case 100:
425 return (ETHER_MEDIA_100BASE_TX);
426 case 10:
427 return (ETHER_MEDIA_10BASE_T);
428 default:
429 break;
430 }
431 }
432
433 return (ETHER_MEDIA_UNKNOWN);
434 }
435
436 /*
437 * Name: bnx_m_stats
438 *
439 * Input: ptr to mac info structure, ptr to gld_stats struct
440 *
441 * Return: DDI_SUCCESS or DDI_FAILURE
442 *
443 * Description: bnx_m_stats() populates gld_stats structure elements
444 * from latest data from statistic block.
445 */
446 static int
bnx_m_stats(void * arg,uint_t stat,uint64_t * val)447 bnx_m_stats(void * arg, uint_t stat, uint64_t *val)
448 {
449 int rc;
450 um_device_t *umdevice;
451 lm_device_t *lmdevice;
452 const bnx_lnk_cfg_t *linkconf;
453
454 umdevice = (um_device_t *)arg;
455
456 if (umdevice == NULL || val == NULL) {
457 return (EINVAL);
458 }
459
460 lmdevice = &(umdevice->lm_dev);
461
462 /* FIXME -- Fix STATS collections */
463
464 if (umdevice->dev_var.isfiber) {
465 linkconf = &bnx_serdes_config;
466 } else {
467 linkconf = &bnx_copper_config;
468 }
469
470 mutex_enter(&umdevice->os_param.gld_mutex);
471
472 if (umdevice->dev_start != B_TRUE) {
473 rc = EAGAIN;
474 goto done;
475 }
476
477 *val = 0;
478 switch (stat) {
479 case MAC_STAT_IFSPEED:
480 *val = umdevice->nddcfg.link_speed * 1000000ull;
481 break;
482 case MAC_STAT_MULTIRCV:
483 *val += shift_left32(
484 lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_hi);
485 *val +=
486 lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_lo;
487 break;
488 case MAC_STAT_BRDCSTRCV:
489 *val += shift_left32(
490 lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_hi);
491 *val +=
492 lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_lo;
493 break;
494 case MAC_STAT_MULTIXMT:
495 *val += shift_left32(
496 lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_hi);
497 *val +=
498 lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_lo;
499 break;
500 case MAC_STAT_BRDCSTXMT:
501 *val += shift_left32(
502 lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_hi);
503 *val +=
504 lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_lo;
505 break;
506 case MAC_STAT_NORCVBUF:
507 *val = lmdevice->vars.stats_virt->stat_IfInMBUFDiscards;
508 break;
509 case ETHER_STAT_MACRCV_ERRORS:
510 case MAC_STAT_IERRORS:
511 *val = lmdevice->vars.stats_virt->stat_Dot3StatsFCSErrors +
512 lmdevice->vars.stats_virt->stat_Dot3StatsAlignmentErrors +
513 lmdevice->vars.stats_virt->stat_EtherStatsUndersizePkts +
514 lmdevice->vars.stats_virt->stat_EtherStatsOverrsizePkts;
515 break;
516 case MAC_STAT_OERRORS:
517 *val = lmdevice->vars.stats_virt->
518 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
519 break;
520 case MAC_STAT_COLLISIONS:
521 *val = lmdevice->vars.stats_virt->stat_EtherStatsCollisions;
522 break;
523 case MAC_STAT_RBYTES:
524 *val += shift_left32(
525 lmdevice->vars.stats_virt->stat_IfHCInOctets_hi);
526 *val +=
527 lmdevice->vars.stats_virt->stat_IfHCInOctets_lo;
528 break;
529 case MAC_STAT_IPACKETS:
530 *val += shift_left32(lmdevice->vars.stats_virt->
531 stat_IfHCInUcastPkts_hi);
532 *val += lmdevice->vars.stats_virt->stat_IfHCInUcastPkts_lo;
533
534 *val += shift_left32(lmdevice->vars.stats_virt->
535 stat_IfHCInMulticastPkts_hi);
536 *val += lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_lo;
537
538 *val += shift_left32(lmdevice->vars.stats_virt->
539 stat_IfHCInBroadcastPkts_hi);
540 *val += lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_lo;
541 break;
542 case MAC_STAT_OBYTES:
543 *val += shift_left32(
544 lmdevice->vars.stats_virt->stat_IfHCOutOctets_hi);
545 *val +=
546 lmdevice->vars.stats_virt->stat_IfHCOutOctets_lo;
547 break;
548 case MAC_STAT_OPACKETS:
549 *val += shift_left32(lmdevice->vars.stats_virt->
550 stat_IfHCOutUcastPkts_hi);
551 *val += lmdevice->vars.stats_virt->stat_IfHCOutUcastPkts_lo;
552
553 *val += shift_left32(lmdevice->vars.stats_virt->
554 stat_IfHCOutMulticastPkts_hi);
555 *val += lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_lo;
556
557 *val += shift_left32(lmdevice->vars.stats_virt->
558 stat_IfHCOutBroadcastPkts_hi);
559 *val += lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_lo;
560 break;
561 case ETHER_STAT_ALIGN_ERRORS:
562 *val = lmdevice->vars.stats_virt->stat_Dot3StatsAlignmentErrors;
563 break;
564 case ETHER_STAT_FCS_ERRORS:
565 *val = lmdevice->vars.stats_virt->stat_Dot3StatsFCSErrors;
566 break;
567 case ETHER_STAT_FIRST_COLLISIONS:
568 *val = lmdevice->vars.stats_virt->
569 stat_Dot3StatsSingleCollisionFrames;
570 break;
571 case ETHER_STAT_MULTI_COLLISIONS:
572 *val = lmdevice->vars.stats_virt->
573 stat_Dot3StatsMultipleCollisionFrames;
574 break;
575 case ETHER_STAT_DEFER_XMTS:
576 *val = lmdevice->vars.stats_virt->
577 stat_Dot3StatsDeferredTransmissions;
578 break;
579 case ETHER_STAT_TX_LATE_COLLISIONS:
580 *val = lmdevice->vars.stats_virt->
581 stat_Dot3StatsLateCollisions;
582 break;
583 case ETHER_STAT_EX_COLLISIONS:
584 *val = lmdevice->vars.stats_virt->
585 stat_Dot3StatsExcessiveCollisions;
586 break;
587 case ETHER_STAT_MACXMT_ERRORS:
588 *val = lmdevice->vars.stats_virt->
589 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
590 break;
591 case ETHER_STAT_CARRIER_ERRORS:
592 *val = lmdevice->vars.stats_virt->
593 stat_Dot3StatsCarrierSenseErrors;
594 break;
595 case ETHER_STAT_TOOLONG_ERRORS:
596 *val = lmdevice->vars.stats_virt->
597 stat_EtherStatsOverrsizePkts;
598 break;
599 #if (MAC_VERSION > 1)
600 case ETHER_STAT_TOOSHORT_ERRORS:
601 *val = lmdevice->vars.stats_virt->
602 stat_EtherStatsUndersizePkts;
603 break;
604 #endif
605 case ETHER_STAT_XCVR_ADDR:
606 *val = lmdevice->params.phy_addr;
607 break;
608 case ETHER_STAT_XCVR_ID:
609 *val = lmdevice->hw_info.phy_id;
610 break;
611 case ETHER_STAT_XCVR_INUSE:
612 *val = (uint64_t)bnx_um_to_media(umdevice);
613 break;
614 case ETHER_STAT_CAP_1000FDX:
615 *val = 1;
616 break;
617 case ETHER_STAT_CAP_1000HDX:
618 *val = linkconf->param_1000hdx;
619 break;
620 case ETHER_STAT_CAP_100FDX:
621 *val = linkconf->param_100fdx;
622 break;
623 case ETHER_STAT_CAP_100HDX:
624 *val = linkconf->param_100hdx;
625 break;
626 case ETHER_STAT_CAP_10FDX:
627 *val = linkconf->param_10fdx;
628 break;
629 case ETHER_STAT_CAP_10HDX:
630 *val = linkconf->param_10hdx;
631 break;
632 case ETHER_STAT_CAP_ASMPAUSE:
633 *val = 1;
634 break;
635 case ETHER_STAT_CAP_PAUSE:
636 *val = 1;
637 break;
638 case ETHER_STAT_CAP_AUTONEG:
639 *val = 1;
640 break;
641 #if (MAC_VERSION > 1)
642 case ETHER_STAT_CAP_REMFAULT:
643 *val = 1;
644 break;
645 #endif
646 case ETHER_STAT_ADV_CAP_1000FDX:
647 *val = umdevice->curcfg.lnkcfg.param_1000fdx;
648 break;
649 case ETHER_STAT_ADV_CAP_1000HDX:
650 *val = umdevice->curcfg.lnkcfg.param_1000hdx;
651 break;
652 case ETHER_STAT_ADV_CAP_100FDX:
653 *val = umdevice->curcfg.lnkcfg.param_100fdx;
654 break;
655 case ETHER_STAT_ADV_CAP_100HDX:
656 *val = umdevice->curcfg.lnkcfg.param_100hdx;
657 break;
658 case ETHER_STAT_ADV_CAP_10FDX:
659 *val = umdevice->curcfg.lnkcfg.param_10fdx;
660 break;
661 case ETHER_STAT_ADV_CAP_10HDX:
662 *val = umdevice->curcfg.lnkcfg.param_10hdx;
663 break;
664 case ETHER_STAT_ADV_CAP_ASMPAUSE:
665 *val = 1;
666 break;
667 case ETHER_STAT_ADV_CAP_PAUSE:
668 *val = 1;
669 break;
670 case ETHER_STAT_ADV_CAP_AUTONEG:
671 *val = umdevice->curcfg.lnkcfg.link_autoneg;
672 break;
673 #if (MAC_VERSION > 1)
674 case ETHER_STAT_ADV_REMFAULT:
675 *val = 1;
676 break;
677 #endif
678 case ETHER_STAT_LP_CAP_1000FDX:
679 *val = umdevice->remote.param_1000fdx;
680 break;
681 case ETHER_STAT_LP_CAP_1000HDX:
682 *val = umdevice->remote.param_1000hdx;
683 break;
684 case ETHER_STAT_LP_CAP_100FDX:
685 *val = umdevice->remote.param_100fdx;
686 break;
687 case ETHER_STAT_LP_CAP_100HDX:
688 *val = umdevice->remote.param_100hdx;
689 break;
690 case ETHER_STAT_LP_CAP_10FDX:
691 *val = umdevice->remote.param_10fdx;
692 break;
693 case ETHER_STAT_LP_CAP_10HDX:
694 *val = umdevice->remote.param_10hdx;
695 break;
696 case ETHER_STAT_LP_CAP_ASMPAUSE:
697 /* FIXME -- Implement LP_ASYM_PAUSE stat */
698 break;
699 case ETHER_STAT_LP_CAP_PAUSE:
700 /* FIXME -- Implement LP_PAUSE stat */
701 break;
702 case ETHER_STAT_LP_CAP_AUTONEG:
703 *val = umdevice->remote.link_autoneg;
704 break;
705 #if (MAC_VERSION > 1)
706 case ETHER_STAT_LP_REMFAULT:
707 /* FIXME -- Implement LP_REMFAULT stat */
708 break;
709 #endif
710 case ETHER_STAT_LINK_ASMPAUSE:
711 /* FIXME -- Implement ASMPAUSE stat */
712 break;
713 case ETHER_STAT_LINK_PAUSE:
714 /* FIXME -- Implement PAUSE stat */
715 break;
716 case ETHER_STAT_LINK_AUTONEG:
717 *val = umdevice->curcfg.lnkcfg.link_autoneg;
718 break;
719 case ETHER_STAT_LINK_DUPLEX:
720 *val = umdevice->nddcfg.link_duplex == B_TRUE ?
721 LINK_DUPLEX_FULL: LINK_DUPLEX_HALF;
722 break;
723 default:
724 rc = ENOTSUP;
725 }
726
727 rc = 0;
728
729 done:
730 mutex_exit(&umdevice->os_param.gld_mutex);
731
732 return (rc);
733 }
734
735 static boolean_t
bnx_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)736 bnx_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
737 {
738 um_device_t *umdevice;
739
740 umdevice = (um_device_t *)arg;
741
742 switch (cap) {
743 case MAC_CAPAB_HCKSUM: {
744 uint32_t *txflags = cap_data;
745
746 *txflags = 0;
747
748 if (umdevice->dev_var.enabled_oflds &
749 (LM_OFFLOAD_TX_IP_CKSUM | LM_OFFLOAD_RX_IP_CKSUM)) {
750 *txflags |= HCKSUM_IPHDRCKSUM;
751 }
752
753 if (umdevice->dev_var.enabled_oflds &
754 (LM_OFFLOAD_TX_TCP_CKSUM | LM_OFFLOAD_TX_UDP_CKSUM |
755 LM_OFFLOAD_RX_TCP_CKSUM | LM_OFFLOAD_RX_UDP_CKSUM)) {
756 *txflags |= HCKSUM_INET_FULL_V4;
757 }
758 break;
759 }
760 default:
761 return (B_FALSE);
762 }
763
764 return (B_TRUE);
765 }
766
767 static int
bnx_refresh_rx_tx_pkts(um_device_t * umdevice)768 bnx_refresh_rx_tx_pkts(um_device_t *umdevice)
769 {
770 if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_HDWR_REGISTER) {
771 bnx_hdwr_fini(umdevice);
772 /*
773 * Initialize the adapter resource. Mainly allocating memory
774 * needed by the driver, such as packet descriptors, shared
775 * memory, etc.
776 */
777 if (lm_init_resc(&(umdevice->lm_dev)) != LM_STATUS_SUCCESS) {
778 return (EIO);
779 }
780
781 if (bnx_txpkts_init(umdevice)) {
782 return (EIO);
783 }
784
785 if (bnx_rxpkts_init(umdevice)) {
786 return (EIO);
787 }
788 }
789 return (0);
790 }
791
792 static int
bnx_set_priv_prop(um_device_t * umdevice,const char * pr_name,uint_t pr_valsize,const void * pr_val)793 bnx_set_priv_prop(um_device_t *umdevice, const char *pr_name,
794 uint_t pr_valsize, const void *pr_val)
795 {
796 boolean_t refresh = B_FALSE;
797 long result;
798 int err = 0;
799
800 if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) {
801 if (lm_get_medium(&umdevice->lm_dev) != LM_MEDIUM_TYPE_FIBER) {
802 return (ENOTSUP);
803 }
804 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
805 return (EINVAL);
806 }
807 if (result != 1 && result != 0) {
808 return (EINVAL);
809 }
810 if (umdevice->hwinit.lnkcfg.param_2500fdx != (uint32_t)result) {
811 umdevice->hwinit.lnkcfg.param_2500fdx =
812 (uint32_t)result;
813 umdevice->curcfg.lnkcfg.param_2500fdx =
814 (uint32_t)result;
815 bnx_update_phy(umdevice);
816 }
817 } else if (strcmp(pr_name, "_checksum") == 0) {
818 if (umdevice->dev_start == B_TRUE) {
819 return (EBUSY);
820 }
821 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
822 return (EINVAL);
823 }
824 switch (result) {
825 case USER_OPTION_CKSUM_TX_ONLY:
826 umdevice->dev_var.enabled_oflds =
827 LM_OFFLOAD_TX_IP_CKSUM |
828 LM_OFFLOAD_TX_TCP_CKSUM |
829 LM_OFFLOAD_TX_UDP_CKSUM;
830 break;
831
832 case USER_OPTION_CKSUM_RX_ONLY:
833 umdevice->dev_var.enabled_oflds =
834 LM_OFFLOAD_RX_IP_CKSUM |
835 LM_OFFLOAD_RX_TCP_CKSUM |
836 LM_OFFLOAD_RX_UDP_CKSUM;
837 break;
838
839 case USER_OPTION_CKSUM_TX_RX:
840 umdevice->dev_var.enabled_oflds =
841 LM_OFFLOAD_TX_IP_CKSUM |
842 LM_OFFLOAD_RX_IP_CKSUM |
843 LM_OFFLOAD_TX_TCP_CKSUM |
844 LM_OFFLOAD_RX_TCP_CKSUM |
845 LM_OFFLOAD_TX_UDP_CKSUM |
846 LM_OFFLOAD_RX_UDP_CKSUM;
847 break;
848
849 case USER_OPTION_CKSUM_NONE:
850 umdevice->dev_var.enabled_oflds =
851 LM_OFFLOAD_NONE;
852 break;
853
854 default:
855 return (EINVAL);
856 }
857 } else if (strcmp(pr_name, "_tx_descriptor_count") == 0) {
858 if (umdevice->dev_start == B_TRUE) {
859 return (EBUSY);
860 }
861 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
862 return (EINVAL);
863 }
864 if (result < USER_OPTION_TX_DESC_CNT_MIN ||
865 result > USER_OPTION_TX_DESC_CNT_MAX) {
866 return (EINVAL);
867 }
868 _TX_QINFO(umdevice, 0).desc_cnt = result;
869 umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] =
870 result / MAX_BD_PER_PAGE;
871 if (result % MAX_BD_PER_PAGE) {
872 umdevice->lm_dev.params.l2_tx_bd_page_cnt[0]++;
873 }
874 if (umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] > 127) {
875 umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] = 127;
876 }
877 refresh = B_TRUE;
878 } else if (strcmp(pr_name, "_rx_descriptor_count") == 0) {
879 if (umdevice->dev_start == B_TRUE) {
880 return (EBUSY);
881 }
882 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
883 return (EINVAL);
884 }
885 if (result < USER_OPTION_RX_DESC_CNT_MIN ||
886 result > USER_OPTION_RX_DESC_CNT_MAX) {
887 return (EINVAL);
888 }
889 umdevice->lm_dev.params.l2_rx_desc_cnt[0] = result;
890 result = (result * BNX_RECV_MAX_FRAGS) / MAX_BD_PER_PAGE;
891 umdevice->lm_dev.params.l2_rx_bd_page_cnt[0] = result;
892 if (result % MAX_BD_PER_PAGE) {
893 umdevice->lm_dev.params.l2_rx_bd_page_cnt[0]++;
894 }
895 refresh = B_TRUE;
896 }
897 #if 0
898 /* Initialized by init_hc() */
899 else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) {
900 if (umdevice->dev_start == B_TRUE) {
901 return (EBUSY);
902 }
903 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
904 return (EINVAL);
905 }
906 if (result < USER_OPTION_TICKS_MIN ||
907 result > USER_OPTION_TICKS_MAX) {
908 return (EINVAL);
909 }
910 umdevice->lm_dev.params.tx_ticks = result;
911 } else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) {
912 if (umdevice->dev_start == B_TRUE) {
913 return (EBUSY);
914 }
915 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
916 return (EINVAL);
917 }
918 if (result < USER_OPTION_TICKS_INT_MIN ||
919 result > USER_OPTION_TICKS_INT_MAX) {
920 return (EINVAL);
921 }
922 umdevice->lm_dev.params.tx_ticks_int = result;
923 } else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) {
924 if (umdevice->dev_start == B_TRUE) {
925 return (EBUSY);
926 }
927 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
928 return (EINVAL);
929 }
930 if (result < USER_OPTION_TICKS_MIN ||
931 result > USER_OPTION_TICKS_MAX) {
932 return (EINVAL);
933 }
934 umdevice->lm_dev.params.rx_ticks = result;
935 } else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) {
936 if (umdevice->dev_start == B_TRUE) {
937 return (EBUSY);
938 }
939 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
940 return (EINVAL);
941 }
942 if (result < USER_OPTION_TICKS_INT_MIN ||
943 result > USER_OPTION_TICKS_INT_MAX) {
944 return (EINVAL);
945 }
946 umdevice->lm_dev.params.rx_ticks_int = result;
947 } else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) {
948 if (umdevice->dev_start == B_TRUE) {
949 return (EBUSY);
950 }
951 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
952 return (EINVAL);
953 }
954 if (result < USER_OPTION_FRAMES_MIN ||
955 result > USER_OPTION_FRAMES_MAX) {
956 return (EINVAL);
957 }
958 umdevice->lm_dev.params.tx_quick_cons_trip = result;
959 } else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) {
960 if (umdevice->dev_start == B_TRUE) {
961 return (EBUSY);
962 }
963 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
964 return (EINVAL);
965 }
966 if (result < USER_OPTION_FRAMES_MIN ||
967 result > USER_OPTION_FRAMES_MAX) {
968 return (EINVAL);
969 }
970 umdevice->lm_dev.params.tx_quick_cons_trip_int = result;
971 } else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) {
972 if (umdevice->dev_start == B_TRUE) {
973 return (EBUSY);
974 }
975 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
976 return (EINVAL);
977 }
978 if (result < USER_OPTION_FRAMES_MIN ||
979 result > USER_OPTION_FRAMES_MAX) {
980 return (EINVAL);
981 }
982 umdevice->lm_dev.params.rx_quick_cons_trip = result;
983 } else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) {
984 if (umdevice->dev_start == B_TRUE) {
985 return (EBUSY);
986 }
987 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
988 return (EINVAL);
989 }
990 if (result < USER_OPTION_FRAMES_MIN ||
991 result > USER_OPTION_FRAMES_MAX) {
992 return (EINVAL);
993 }
994 umdevice->lm_dev.params.rx_quick_cons_trip_int = result;
995 } else if (strcmp(pr_name, "_statticks") == 0) {
996 if (umdevice->dev_start == B_TRUE) {
997 return (EBUSY);
998 }
999 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) {
1000 return (EINVAL);
1001 }
1002 if (result < USER_OPTION_STATSTICKS_MIN ||
1003 result > USER_OPTION_STATSTICKS_MAX) {
1004 return (EINVAL);
1005 }
1006 umdevice->lm_dev.params.stats_ticks = result;
1007 }
1008 #endif
1009 else if (strcmp(pr_name, "_disable_msix") == 0) {
1010 err = ENOTSUP;
1011 } else {
1012 err = ENOTSUP;
1013 }
1014
1015 if (!err && refresh) {
1016 err = bnx_refresh_rx_tx_pkts(umdevice);
1017 }
1018 return (err);
1019 }
1020
1021
1022 static int
bnx_m_setprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)1023 bnx_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1024 uint_t pr_valsize, const void *pr_val)
1025 {
1026 um_device_t *umdevice = arg;
1027 boolean_t reprogram = B_FALSE;
1028 boolean_t rxpause;
1029 boolean_t txpause;
1030 uint32_t mtu;
1031 link_flowctrl_t fl;
1032 int err = 0;
1033
1034 mutex_enter(&umdevice->os_param.gld_mutex);
1035
1036 if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) {
1037 if (pr_num == MAC_PROP_EN_100FDX_CAP ||
1038 pr_num == MAC_PROP_EN_100HDX_CAP ||
1039 pr_num == MAC_PROP_EN_10FDX_CAP ||
1040 pr_num == MAC_PROP_EN_10HDX_CAP) {
1041 mutex_exit(&umdevice->os_param.gld_mutex);
1042 return (ENOTSUP);
1043 }
1044 }
1045
1046 switch (pr_num) {
1047 /* read-only properties */
1048 case MAC_PROP_ADV_1000FDX_CAP:
1049 case MAC_PROP_ADV_1000HDX_CAP:
1050 case MAC_PROP_ADV_100FDX_CAP:
1051 case MAC_PROP_ADV_100HDX_CAP:
1052 case MAC_PROP_ADV_10FDX_CAP:
1053 case MAC_PROP_ADV_10HDX_CAP:
1054 case MAC_PROP_STATUS:
1055 case MAC_PROP_SPEED:
1056 case MAC_PROP_DUPLEX:
1057 case MAC_PROP_MEDIA:
1058 default:
1059
1060 err = ENOTSUP;
1061 break;
1062
1063
1064 /* BEGIN CSTYLED */
1065 #define BNX_SETPROP_CASE(cap, param) \
1066 case cap: \
1067 if (umdevice->hwinit.lnkcfg.param != *(uint8_t *)pr_val) { \
1068 umdevice->hwinit.lnkcfg.param = *(uint8_t *)pr_val; \
1069 umdevice->curcfg.lnkcfg.param = *(uint8_t *)pr_val; \
1070 reprogram = B_TRUE; \
1071 } \
1072 break
1073 /* END CSTYLED */
1074
1075
1076 BNX_SETPROP_CASE(MAC_PROP_EN_1000FDX_CAP, param_1000fdx);
1077 BNX_SETPROP_CASE(MAC_PROP_EN_1000HDX_CAP, param_1000hdx);
1078 BNX_SETPROP_CASE(MAC_PROP_EN_100FDX_CAP, param_100fdx);
1079 BNX_SETPROP_CASE(MAC_PROP_EN_100HDX_CAP, param_100hdx);
1080 BNX_SETPROP_CASE(MAC_PROP_EN_10FDX_CAP, param_10fdx);
1081 BNX_SETPROP_CASE(MAC_PROP_EN_10HDX_CAP, param_10hdx);
1082 BNX_SETPROP_CASE(MAC_PROP_AUTONEG, link_autoneg);
1083
1084 case MAC_PROP_FLOWCTRL:
1085 bcopy(pr_val, &fl, sizeof (fl));
1086 switch (fl) {
1087 case LINK_FLOWCTRL_NONE:
1088
1089 rxpause = B_FALSE;
1090 txpause = B_FALSE;
1091 break;
1092
1093 case LINK_FLOWCTRL_RX:
1094
1095 rxpause = B_TRUE;
1096 txpause = B_FALSE;
1097 break;
1098
1099 case LINK_FLOWCTRL_TX:
1100
1101 rxpause = B_FALSE;
1102 txpause = B_TRUE;
1103 break;
1104
1105 case LINK_FLOWCTRL_BI:
1106
1107 rxpause = B_TRUE;
1108 txpause = B_TRUE;
1109 break;
1110
1111 default:
1112
1113 err = ENOTSUP;
1114 break;
1115 }
1116
1117 if (err == 0) {
1118 if (umdevice->hwinit.lnkcfg.param_tx_pause !=
1119 txpause ||
1120 umdevice->hwinit.lnkcfg.param_rx_pause !=
1121 rxpause) {
1122 umdevice->hwinit.lnkcfg.param_tx_pause =
1123 txpause;
1124 umdevice->hwinit.lnkcfg.param_rx_pause =
1125 rxpause;
1126 umdevice->curcfg.lnkcfg.param_tx_pause =
1127 txpause;
1128 umdevice->curcfg.lnkcfg.param_rx_pause =
1129 rxpause;
1130 reprogram = B_TRUE;
1131 }
1132 }
1133
1134 break;
1135
1136 case MAC_PROP_MTU:
1137 if (umdevice->dev_start == B_TRUE) {
1138 err = EBUSY;
1139 break;
1140 }
1141
1142 bcopy(pr_val, &mtu, sizeof (mtu));
1143
1144 if (mtu < USER_OPTION_MTU_MIN ||
1145 mtu > USER_OPTION_MTU_MAX) {
1146 err = EINVAL;
1147 break;
1148 }
1149
1150 if (umdevice->dev_var.mtu == mtu) {
1151 break;
1152 }
1153
1154 umdevice->dev_var.mtu = mtu;
1155 umdevice->lm_dev.params.mtu = umdevice->dev_var.mtu
1156 + sizeof (struct ether_header) + VLAN_TAGSZ;
1157
1158 if (bnx_refresh_rx_tx_pkts(umdevice) != 0) {
1159 err = EIO;
1160 } else {
1161 reprogram = B_TRUE;
1162 }
1163 break;
1164
1165 case MAC_PROP_PRIVATE:
1166 err = bnx_set_priv_prop(umdevice, pr_name, pr_valsize,
1167 pr_val);
1168 reprogram = B_TRUE;
1169 break;
1170 }
1171
1172 if (!err && reprogram) {
1173 bnx_update_phy(umdevice);
1174 }
1175
1176 mutex_exit(&umdevice->os_param.gld_mutex);
1177
1178 return (err);
1179 }
1180
1181 static int
bnx_get_priv_prop(um_device_t * umdevice,const char * pr_name,uint_t pr_valsize,void * pr_val)1182 bnx_get_priv_prop(um_device_t *umdevice, const char *pr_name,
1183 uint_t pr_valsize, void *pr_val)
1184 {
1185 int value;
1186
1187 if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) {
1188 if (lm_get_medium(&umdevice->lm_dev) !=
1189 LM_MEDIUM_TYPE_FIBER) {
1190 return (ENOTSUP);
1191 }
1192 value = umdevice->curcfg.lnkcfg.param_2500fdx;
1193 } else if (strcmp(pr_name, "_checksum") == 0) {
1194 value = umdevice->dev_var.enabled_oflds;
1195 } else if (strcmp(pr_name, "_tx_descriptor_count") == 0) {
1196 value = _TX_QINFO(umdevice, 0).desc_cnt;
1197 } else if (strcmp(pr_name, "_rx_descriptor_count") == 0) {
1198 value = umdevice->lm_dev.params.l2_rx_desc_cnt[0];
1199 } else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) {
1200 value = umdevice->lm_dev.params.tx_ticks;
1201 } else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) {
1202 value = umdevice->lm_dev.params.tx_ticks_int;
1203 } else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) {
1204 value = umdevice->lm_dev.params.rx_ticks;
1205 } else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) {
1206 value = umdevice->lm_dev.params.rx_ticks_int;
1207 } else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) {
1208 value = umdevice->lm_dev.params.tx_quick_cons_trip;
1209 } else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) {
1210 value = umdevice->lm_dev.params.tx_quick_cons_trip_int;
1211 } else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) {
1212 value = umdevice->lm_dev.params.rx_quick_cons_trip;
1213 } else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) {
1214 value = umdevice->lm_dev.params.rx_quick_cons_trip_int;
1215 } else if (strcmp(pr_name, "_statticks") == 0) {
1216 value = umdevice->lm_dev.params.stats_ticks;
1217 } else if (strcmp(pr_name, "_disable_msix") == 0) {
1218 value = umdevice->dev_var.disableMsix;
1219 } else {
1220 return (ENOTSUP);
1221 }
1222
1223 (void) snprintf(pr_val, pr_valsize, "%d", value);
1224 return (0);
1225
1226 }
1227
1228 static int
bnx_m_getprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)1229 bnx_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1230 uint_t pr_valsize, void *pr_val)
1231 {
1232 um_device_t *umdevice = arg;
1233 link_duplex_t link_duplex;
1234 uint64_t link_speed;
1235 link_state_t link_state;
1236 link_flowctrl_t fl;
1237 mac_ether_media_t media;
1238
1239 if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) {
1240 if (pr_num == MAC_PROP_EN_100FDX_CAP ||
1241 pr_num == MAC_PROP_EN_100HDX_CAP ||
1242 pr_num == MAC_PROP_EN_10FDX_CAP ||
1243 pr_num == MAC_PROP_EN_10HDX_CAP) {
1244 return (ENOTSUP);
1245 }
1246 }
1247
1248 switch (pr_num) {
1249 case MAC_PROP_DUPLEX:
1250 link_duplex = umdevice->nddcfg.link_duplex == B_TRUE ?
1251 LINK_DUPLEX_FULL: LINK_DUPLEX_HALF;
1252
1253 ASSERT(pr_valsize >= sizeof (link_duplex_t));
1254
1255 bcopy(&link_duplex, pr_val, sizeof (link_duplex_t));
1256 break;
1257
1258 case MAC_PROP_SPEED:
1259 link_speed = umdevice->nddcfg.link_speed * 1000000ull;
1260
1261 ASSERT(pr_valsize >= sizeof (link_speed));
1262
1263 bcopy(&link_speed, pr_val, sizeof (link_speed));
1264 break;
1265
1266 case MAC_PROP_STATUS:
1267 link_state = umdevice->nddcfg.link_speed ?
1268 LINK_STATE_UP : LINK_STATE_DOWN;
1269
1270 ASSERT(pr_valsize >= sizeof (link_state_t));
1271
1272 bcopy(&link_state, pr_val, sizeof (link_state));
1273 break;
1274
1275 case MAC_PROP_MEDIA:
1276 media = bnx_um_to_media(umdevice);
1277
1278 ASSERT(pr_valsize >= sizeof (mac_ether_media_t));
1279
1280 bcopy(&media, pr_val, sizeof (link_state));
1281 break;
1282
1283 case MAC_PROP_AUTONEG:
1284 *(uint8_t *)pr_val =
1285 umdevice->curcfg.lnkcfg.link_autoneg;
1286 break;
1287
1288 case MAC_PROP_FLOWCTRL:
1289 ASSERT(pr_valsize >= sizeof (fl));
1290
1291 boolean_t txpause =
1292 umdevice->curcfg.lnkcfg.param_tx_pause;
1293 boolean_t rxpause =
1294 umdevice->curcfg.lnkcfg.param_rx_pause;
1295 if (txpause) {
1296 if (rxpause) {
1297 fl = LINK_FLOWCTRL_BI;
1298 } else {
1299 fl = LINK_FLOWCTRL_TX;
1300 }
1301 } else {
1302 if (rxpause) {
1303 fl = LINK_FLOWCTRL_RX;
1304 } else {
1305 fl = LINK_FLOWCTRL_NONE;
1306 }
1307 }
1308 bcopy(&fl, pr_val, sizeof (fl));
1309 break;
1310
1311 case MAC_PROP_ADV_1000FDX_CAP:
1312 *(uint8_t *)pr_val =
1313 umdevice->curcfg.lnkcfg.param_1000fdx;
1314 break;
1315
1316 case MAC_PROP_EN_1000FDX_CAP:
1317 *(uint8_t *)pr_val =
1318 umdevice->curcfg.lnkcfg.param_1000fdx;
1319 break;
1320
1321 case MAC_PROP_ADV_1000HDX_CAP:
1322 *(uint8_t *)pr_val =
1323 umdevice->curcfg.lnkcfg.param_1000hdx;
1324 break;
1325
1326 case MAC_PROP_EN_1000HDX_CAP:
1327 *(uint8_t *)pr_val =
1328 umdevice->curcfg.lnkcfg.param_1000hdx;
1329 break;
1330
1331 case MAC_PROP_ADV_100FDX_CAP:
1332 *(uint8_t *)pr_val =
1333 umdevice->curcfg.lnkcfg.param_100fdx;
1334 break;
1335
1336 case MAC_PROP_EN_100FDX_CAP:
1337 *(uint8_t *)pr_val =
1338 umdevice->curcfg.lnkcfg.param_100fdx;
1339 break;
1340
1341 case MAC_PROP_ADV_100HDX_CAP:
1342 *(uint8_t *)pr_val =
1343 umdevice->curcfg.lnkcfg.param_100hdx;
1344 break;
1345
1346 case MAC_PROP_EN_100HDX_CAP:
1347 *(uint8_t *)pr_val =
1348 umdevice->curcfg.lnkcfg.param_100hdx;
1349 break;
1350
1351 case MAC_PROP_ADV_10FDX_CAP:
1352 *(uint8_t *)pr_val =
1353 umdevice->curcfg.lnkcfg.param_10fdx;
1354 break;
1355
1356 case MAC_PROP_EN_10FDX_CAP:
1357 *(uint8_t *)pr_val =
1358 umdevice->curcfg.lnkcfg.param_10fdx;
1359 break;
1360
1361 case MAC_PROP_ADV_10HDX_CAP:
1362 *(uint8_t *)pr_val =
1363 umdevice->curcfg.lnkcfg.param_10hdx;
1364 break;
1365
1366 case MAC_PROP_EN_10HDX_CAP:
1367 *(uint8_t *)pr_val =
1368 umdevice->curcfg.lnkcfg.param_10hdx;
1369 break;
1370
1371 case MAC_PROP_PRIVATE:
1372 return (bnx_get_priv_prop(umdevice, pr_name, pr_valsize,
1373 pr_val));
1374
1375 default:
1376
1377 return (ENOTSUP);
1378
1379 }
1380
1381 return (0);
1382
1383 }
1384
1385 static void
bnx_priv_propinfo(um_device_t * umdevice,const char * pr_name,mac_prop_info_handle_t prh)1386 bnx_priv_propinfo(um_device_t *umdevice, const char *pr_name,
1387 mac_prop_info_handle_t prh)
1388 {
1389 char valstr[64];
1390 int value;
1391
1392 if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) {
1393 if (lm_get_medium(&umdevice->lm_dev) != LM_MEDIUM_TYPE_FIBER) {
1394 return;
1395 }
1396 value = umdevice->curcfg.lnkcfg.param_2500fdx;
1397 } else if (strcmp(pr_name, "_checksum") == 0) {
1398 value = umdevice->dev_var.enabled_oflds;
1399 } else if (strcmp(pr_name, "_tx_descriptor_count") == 0) {
1400 value = _TX_QINFO(umdevice, 0).desc_cnt;
1401 } else if (strcmp(pr_name, "_rx_descriptor_count") == 0) {
1402 value = umdevice->lm_dev.params.l2_rx_desc_cnt[0];
1403 } else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) {
1404 value = umdevice->lm_dev.params.tx_ticks;
1405 } else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) {
1406 value = umdevice->lm_dev.params.tx_ticks_int;
1407 } else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) {
1408 value = umdevice->lm_dev.params.rx_ticks;
1409 } else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) {
1410 value = umdevice->lm_dev.params.rx_ticks_int;
1411 } else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) {
1412 value = umdevice->lm_dev.params.tx_quick_cons_trip;
1413 } else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) {
1414 value = umdevice->lm_dev.params.tx_quick_cons_trip_int;
1415 } else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) {
1416 value = umdevice->lm_dev.params.rx_quick_cons_trip;
1417 } else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) {
1418 value = umdevice->lm_dev.params.rx_quick_cons_trip_int;
1419 } else if (strcmp(pr_name, "_statticks") == 0) {
1420 value = umdevice->lm_dev.params.stats_ticks;
1421 } else if (strcmp(pr_name, "_disable_msix") == 0) {
1422 value = umdevice->dev_var.disableMsix;
1423 } else {
1424 return;
1425 }
1426
1427 (void) snprintf(valstr, sizeof (valstr), "%d", value);
1428 mac_prop_info_set_default_str(prh, valstr);
1429
1430 }
1431
1432 static void
bnx_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)1433 bnx_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1434 mac_prop_info_handle_t prh)
1435 {
1436 um_device_t *umdevice = arg;
1437
1438 if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) {
1439 if (pr_num == MAC_PROP_EN_100FDX_CAP ||
1440 pr_num == MAC_PROP_ADV_100FDX_CAP ||
1441 pr_num == MAC_PROP_EN_100HDX_CAP ||
1442 pr_num == MAC_PROP_ADV_100HDX_CAP ||
1443 pr_num == MAC_PROP_EN_10FDX_CAP ||
1444 pr_num == MAC_PROP_ADV_10FDX_CAP ||
1445 pr_num == MAC_PROP_EN_10HDX_CAP ||
1446 pr_num == MAC_PROP_ADV_10HDX_CAP) {
1447 mac_prop_info_set_default_uint8(prh, 0);
1448 return;
1449 }
1450 }
1451 switch (pr_num) {
1452 case MAC_PROP_ADV_1000FDX_CAP:
1453 case MAC_PROP_ADV_1000HDX_CAP:
1454 case MAC_PROP_ADV_100FDX_CAP:
1455 case MAC_PROP_ADV_100HDX_CAP:
1456 case MAC_PROP_ADV_10FDX_CAP:
1457 case MAC_PROP_ADV_10HDX_CAP:
1458 case MAC_PROP_STATUS:
1459 case MAC_PROP_SPEED:
1460 case MAC_PROP_DUPLEX:
1461
1462 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1463 break;
1464
1465 case MAC_PROP_EN_1000FDX_CAP:
1466
1467 mac_prop_info_set_default_uint8(prh, 1);
1468 break;
1469
1470 case MAC_PROP_EN_1000HDX_CAP:
1471 case MAC_PROP_EN_100FDX_CAP:
1472 case MAC_PROP_EN_100HDX_CAP:
1473 case MAC_PROP_EN_10FDX_CAP:
1474 case MAC_PROP_EN_10HDX_CAP:
1475
1476 if (lm_get_medium(&umdevice->lm_dev) ==
1477 LM_MEDIUM_TYPE_FIBER) {
1478 mac_prop_info_set_default_uint8(prh, 0);
1479 } else {
1480 mac_prop_info_set_default_uint8(prh, 1);
1481 }
1482 break;
1483
1484 case MAC_PROP_AUTONEG:
1485
1486 mac_prop_info_set_default_uint8(prh, 1);
1487 break;
1488
1489 case MAC_PROP_FLOWCTRL:
1490
1491 mac_prop_info_set_default_link_flowctrl(prh,
1492 LINK_FLOWCTRL_BI);
1493 break;
1494
1495 case MAC_PROP_MTU:
1496
1497 mac_prop_info_set_range_uint32(prh,
1498 USER_OPTION_MTU_MIN, USER_OPTION_MTU_MAX);
1499 break;
1500
1501 case MAC_PROP_PRIVATE:
1502
1503 bnx_priv_propinfo(umdevice, pr_name, prh);
1504 break;
1505 default:
1506 break;
1507 }
1508 }
1509
1510 static mac_callbacks_t bnx_callbacks = {
1511 (MC_GETCAPAB | MC_SETPROP | MC_GETPROP| MC_PROPINFO),
1512 bnx_m_stats,
1513 bnx_m_start,
1514 bnx_m_stop,
1515 bnx_m_promiscuous,
1516 bnx_m_multicast,
1517 bnx_m_unicast,
1518 bnx_m_tx,
1519 NULL,
1520 NULL,
1521 bnx_m_getcapab,
1522 NULL,
1523 NULL,
1524 bnx_m_setprop,
1525 bnx_m_getprop,
1526 bnx_m_propinfo
1527 };
1528
1529
1530
1531 /*
1532 * Name: bnx_gld_init
1533 *
1534 * Input: ptr to device structure.
1535 *
1536 * Return: DDI_SUCCESS or DDI_FAILURE
1537 *
1538 * Description:
1539 * This routine populates mac info structure for this device
1540 * instance and registers device with GLD.
1541 */
1542 int
bnx_gld_init(um_device_t * const umdevice)1543 bnx_gld_init(um_device_t *const umdevice)
1544 {
1545 mac_register_t *macp;
1546 int rc;
1547
1548 umdevice->dev_start = B_FALSE;
1549
1550 mutex_init(&umdevice->os_param.gld_mutex, NULL,
1551 MUTEX_DRIVER, DDI_INTR_PRI(umdevice->intrPriority));
1552
1553 rw_init(&umdevice->os_param.gld_snd_mutex, NULL, RW_DRIVER, NULL);
1554
1555 macp = mac_alloc(MAC_VERSION);
1556 if (macp == NULL) {
1557 cmn_err(CE_WARN,
1558 "%s: Failed to allocate GLD MAC memory.\n",
1559 umdevice->dev_name);
1560 goto error;
1561 }
1562
1563 macp->m_driver = umdevice;
1564 macp->m_dip = umdevice->os_param.dip;
1565 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1566 macp->m_callbacks = &bnx_callbacks;
1567 macp->m_min_sdu = 0;
1568 macp->m_max_sdu = umdevice->dev_var.mtu;
1569 macp->m_src_addr = &(umdevice->lm_dev.params.mac_addr[0]);
1570
1571 macp->m_margin = VLAN_TAG_SIZE;
1572
1573 /*
1574 * Call mac_register() after initializing all
1575 * the required elements of mac_t struct.
1576 */
1577 rc = mac_register(macp, &umdevice->os_param.macp);
1578
1579 mac_free(macp);
1580
1581 if (rc != 0) {
1582 cmn_err(CE_WARN,
1583 "%s: Failed to register with GLD.\n",
1584 umdevice->dev_name);
1585 goto error;
1586 }
1587
1588 /* Always report the initial link state as unknown. */
1589 bnx_gld_link(umdevice, LINK_STATE_UNKNOWN);
1590
1591 return (0);
1592
1593 error:
1594 rw_destroy(&umdevice->os_param.gld_snd_mutex);
1595 mutex_destroy(&umdevice->os_param.gld_mutex);
1596
1597 return (-1);
1598 }
1599
1600 void
bnx_gld_link(um_device_t * const umdevice,const link_state_t linkup)1601 bnx_gld_link(um_device_t * const umdevice, const link_state_t linkup)
1602 {
1603 mac_link_update(umdevice->os_param.macp, linkup);
1604 }
1605
1606 int
bnx_gld_fini(um_device_t * const umdevice)1607 bnx_gld_fini(um_device_t * const umdevice)
1608 {
1609 if (umdevice->dev_start != B_FALSE) {
1610 cmn_err(CE_WARN,
1611 "%s: Detaching device from GLD that is still started!!!\n",
1612 umdevice->dev_name);
1613 return (-1);
1614 }
1615
1616 if (mac_unregister(umdevice->os_param.macp)) {
1617 cmn_err(CE_WARN,
1618 "%s: Failed to unregister with the GLD.\n",
1619 umdevice->dev_name);
1620 return (-1);
1621 }
1622
1623 rw_destroy(&umdevice->os_param.gld_snd_mutex);
1624 mutex_destroy(&umdevice->os_param.gld_mutex);
1625
1626 return (0);
1627 }
1628