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(c) 2007-2010 Intel Corporation. All rights reserved.
24 */
25
26 /*
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
29 * Copyright 2014 Pluribus Networks Inc.
30 * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved.
31 * Copyright (c) 2017, Joyent, Inc.
32 * Copyright 2023 Oxide Computer Company
33 */
34
35 #include "igb_sw.h"
36
37 int
igb_m_stat(void * arg,uint_t stat,uint64_t * val)38 igb_m_stat(void *arg, uint_t stat, uint64_t *val)
39 {
40 igb_t *igb = (igb_t *)arg;
41 struct e1000_hw *hw = &igb->hw;
42 igb_stat_t *igb_ks;
43 uint32_t low_val, high_val;
44
45 igb_ks = (igb_stat_t *)igb->igb_ks->ks_data;
46
47 mutex_enter(&igb->gen_lock);
48
49 if (igb->igb_state & IGB_SUSPENDED) {
50 mutex_exit(&igb->gen_lock);
51 return (ECANCELED);
52 }
53
54 switch (stat) {
55 case MAC_STAT_IFSPEED:
56 *val = igb->link_speed * 1000000ull;
57 break;
58
59 case MAC_STAT_MULTIRCV:
60 igb->stat_mprc += E1000_READ_REG(hw, E1000_MPRC);
61 *val = igb->stat_mprc;
62 break;
63
64 case MAC_STAT_BRDCSTRCV:
65 igb->stat_bprc += E1000_READ_REG(hw, E1000_BPRC);
66 *val = igb->stat_bprc;
67 break;
68
69 case MAC_STAT_MULTIXMT:
70 igb->stat_mptc += E1000_READ_REG(hw, E1000_MPTC);
71 *val = igb->stat_mptc;
72 break;
73
74 case MAC_STAT_BRDCSTXMT:
75 igb->stat_bptc += E1000_READ_REG(hw, E1000_BPTC);
76 *val = igb->stat_bptc;
77 break;
78
79 case MAC_STAT_NORCVBUF:
80 igb->stat_rnbc += E1000_READ_REG(hw, E1000_RNBC);
81 *val = igb->stat_rnbc;
82 break;
83
84 case MAC_STAT_IERRORS:
85 igb->stat_rxerrc += E1000_READ_REG(hw, E1000_RXERRC);
86 igb->stat_algnerrc += E1000_READ_REG(hw, E1000_ALGNERRC);
87 igb_ks->rlec.value.ui64 +=
88 E1000_READ_REG(hw, E1000_RLEC);
89 igb->stat_crcerrs += E1000_READ_REG(hw, E1000_CRCERRS);
90 igb->stat_cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
91 *val = igb->stat_rxerrc +
92 igb->stat_algnerrc +
93 igb_ks->rlec.value.ui64 +
94 igb->stat_crcerrs +
95 igb->stat_cexterr;
96 break;
97
98 case MAC_STAT_NOXMTBUF:
99 *val = 0;
100 break;
101
102 case MAC_STAT_OERRORS:
103 igb->stat_ecol += E1000_READ_REG(hw, E1000_ECOL);
104 *val = igb->stat_ecol;
105 break;
106
107 case MAC_STAT_COLLISIONS:
108 igb->stat_colc += E1000_READ_REG(hw, E1000_COLC);
109 *val = igb->stat_colc;
110 break;
111
112 case MAC_STAT_RBYTES:
113 /*
114 * The 64-bit register will reset whenever the upper
115 * 32 bits are read. So we need to read the lower
116 * 32 bits first, then read the upper 32 bits.
117 */
118 low_val = E1000_READ_REG(hw, E1000_TORL);
119 high_val = E1000_READ_REG(hw, E1000_TORH);
120 igb->stat_tor += (uint64_t)high_val << 32 | (uint64_t)low_val;
121 *val = igb->stat_tor;
122 break;
123
124 case MAC_STAT_IPACKETS:
125 igb->stat_tpr += E1000_READ_REG(hw, E1000_TPR);
126 *val = igb->stat_tpr;
127 break;
128
129 case MAC_STAT_OBYTES:
130 /*
131 * The 64-bit register will reset whenever the upper
132 * 32 bits are read. So we need to read the lower
133 * 32 bits first, then read the upper 32 bits.
134 */
135 low_val = E1000_READ_REG(hw, E1000_TOTL);
136 high_val = E1000_READ_REG(hw, E1000_TOTH);
137 igb->stat_tot += (uint64_t)high_val << 32 | (uint64_t)low_val;
138 *val = igb->stat_tot;
139 break;
140
141 case MAC_STAT_OPACKETS:
142 igb->stat_tpt += E1000_READ_REG(hw, E1000_TPT);
143 *val = igb->stat_tpt;
144 break;
145
146 /* RFC 1643 stats */
147 case ETHER_STAT_ALIGN_ERRORS:
148 igb->stat_algnerrc += E1000_READ_REG(hw, E1000_ALGNERRC);
149 *val = igb->stat_algnerrc;
150 break;
151
152 case ETHER_STAT_FCS_ERRORS:
153 igb->stat_crcerrs += E1000_READ_REG(hw, E1000_CRCERRS);
154 *val = igb->stat_crcerrs;
155 break;
156
157 case ETHER_STAT_FIRST_COLLISIONS:
158 igb->stat_scc += E1000_READ_REG(hw, E1000_SCC);
159 *val = igb->stat_scc;
160 break;
161
162 case ETHER_STAT_MULTI_COLLISIONS:
163 igb->stat_mcc += E1000_READ_REG(hw, E1000_MCC);
164 *val = igb->stat_mcc;
165 break;
166
167 case ETHER_STAT_SQE_ERRORS:
168 igb->stat_sec += E1000_READ_REG(hw, E1000_SEC);
169 *val = igb->stat_sec;
170 break;
171
172 case ETHER_STAT_DEFER_XMTS:
173 igb->stat_dc += E1000_READ_REG(hw, E1000_DC);
174 *val = igb->stat_dc;
175 break;
176
177 case ETHER_STAT_TX_LATE_COLLISIONS:
178 igb->stat_latecol += E1000_READ_REG(hw, E1000_LATECOL);
179 *val = igb->stat_latecol;
180 break;
181
182 case ETHER_STAT_EX_COLLISIONS:
183 igb->stat_ecol += E1000_READ_REG(hw, E1000_ECOL);
184 *val = igb->stat_ecol;
185 break;
186
187 case ETHER_STAT_MACXMT_ERRORS:
188 igb->stat_ecol += E1000_READ_REG(hw, E1000_ECOL);
189 *val = igb->stat_ecol;
190 break;
191
192 case ETHER_STAT_CARRIER_ERRORS:
193 igb->stat_cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
194 *val = igb->stat_cexterr;
195 break;
196
197 case ETHER_STAT_TOOLONG_ERRORS:
198 igb->stat_roc += E1000_READ_REG(hw, E1000_ROC);
199 *val = igb->stat_roc;
200 break;
201
202 case ETHER_STAT_MACRCV_ERRORS:
203 igb->stat_rxerrc += E1000_READ_REG(hw, E1000_RXERRC);
204 *val = igb->stat_rxerrc;
205 break;
206
207 /* MII/GMII stats */
208 case ETHER_STAT_XCVR_ADDR:
209 *val = hw->phy.addr;
210 break;
211
212 case ETHER_STAT_XCVR_ID:
213 *val = hw->phy.id | hw->phy.revision;
214 break;
215
216 case ETHER_STAT_XCVR_INUSE:
217 *val = (uint64_t)e1000_link_to_media(hw, igb->link_speed);
218 break;
219
220 case ETHER_STAT_CAP_1000FDX:
221 *val = igb->param_1000fdx_cap;
222 break;
223
224 case ETHER_STAT_CAP_1000HDX:
225 *val = igb->param_1000hdx_cap;
226 break;
227
228 case ETHER_STAT_CAP_100FDX:
229 *val = igb->param_100fdx_cap;
230 break;
231
232 case ETHER_STAT_CAP_100HDX:
233 *val = igb->param_100hdx_cap;
234 break;
235
236 case ETHER_STAT_CAP_10FDX:
237 *val = igb->param_10fdx_cap;
238 break;
239
240 case ETHER_STAT_CAP_10HDX:
241 *val = igb->param_10hdx_cap;
242 break;
243
244 case ETHER_STAT_CAP_ASMPAUSE:
245 *val = igb->param_asym_pause_cap;
246 break;
247
248 case ETHER_STAT_CAP_PAUSE:
249 *val = igb->param_pause_cap;
250 break;
251
252 case ETHER_STAT_CAP_AUTONEG:
253 *val = igb->param_autoneg_cap;
254 break;
255
256 case ETHER_STAT_ADV_CAP_1000FDX:
257 *val = igb->param_adv_1000fdx_cap;
258 break;
259
260 case ETHER_STAT_ADV_CAP_1000HDX:
261 *val = igb->param_adv_1000hdx_cap;
262 break;
263
264 case ETHER_STAT_ADV_CAP_100FDX:
265 *val = igb->param_adv_100fdx_cap;
266 break;
267
268 case ETHER_STAT_ADV_CAP_100HDX:
269 *val = igb->param_adv_100hdx_cap;
270 break;
271
272 case ETHER_STAT_ADV_CAP_10FDX:
273 *val = igb->param_adv_10fdx_cap;
274 break;
275
276 case ETHER_STAT_ADV_CAP_10HDX:
277 *val = igb->param_adv_10hdx_cap;
278 break;
279
280 case ETHER_STAT_ADV_CAP_ASMPAUSE:
281 *val = igb->param_adv_asym_pause_cap;
282 break;
283
284 case ETHER_STAT_ADV_CAP_PAUSE:
285 *val = igb->param_adv_pause_cap;
286 break;
287
288 case ETHER_STAT_ADV_CAP_AUTONEG:
289 *val = hw->mac.autoneg;
290 break;
291
292 case ETHER_STAT_LP_CAP_1000FDX:
293 *val = igb->param_lp_1000fdx_cap;
294 break;
295
296 case ETHER_STAT_LP_CAP_1000HDX:
297 *val = igb->param_lp_1000hdx_cap;
298 break;
299
300 case ETHER_STAT_LP_CAP_100FDX:
301 *val = igb->param_lp_100fdx_cap;
302 break;
303
304 case ETHER_STAT_LP_CAP_100HDX:
305 *val = igb->param_lp_100hdx_cap;
306 break;
307
308 case ETHER_STAT_LP_CAP_10FDX:
309 *val = igb->param_lp_10fdx_cap;
310 break;
311
312 case ETHER_STAT_LP_CAP_10HDX:
313 *val = igb->param_lp_10hdx_cap;
314 break;
315
316 case ETHER_STAT_LP_CAP_ASMPAUSE:
317 *val = igb->param_lp_asym_pause_cap;
318 break;
319
320 case ETHER_STAT_LP_CAP_PAUSE:
321 *val = igb->param_lp_pause_cap;
322 break;
323
324 case ETHER_STAT_LP_CAP_AUTONEG:
325 *val = igb->param_lp_autoneg_cap;
326 break;
327
328 case ETHER_STAT_LINK_ASMPAUSE:
329 *val = igb->param_asym_pause_cap;
330 break;
331
332 case ETHER_STAT_LINK_PAUSE:
333 *val = igb->param_pause_cap;
334 break;
335
336 case ETHER_STAT_LINK_AUTONEG:
337 *val = hw->mac.autoneg;
338 break;
339
340 case ETHER_STAT_LINK_DUPLEX:
341 *val = (igb->link_duplex == FULL_DUPLEX) ?
342 LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
343 break;
344
345 case ETHER_STAT_TOOSHORT_ERRORS:
346 igb->stat_ruc += E1000_READ_REG(hw, E1000_RUC);
347 *val = igb->stat_ruc;
348 break;
349
350 case ETHER_STAT_CAP_REMFAULT:
351 *val = igb->param_rem_fault;
352 break;
353
354 case ETHER_STAT_ADV_REMFAULT:
355 *val = igb->param_adv_rem_fault;
356 break;
357
358 case ETHER_STAT_LP_REMFAULT:
359 *val = igb->param_lp_rem_fault;
360 break;
361
362 case ETHER_STAT_JABBER_ERRORS:
363 igb->stat_rjc += E1000_READ_REG(hw, E1000_RJC);
364 *val = igb->stat_rjc;
365 break;
366
367 case ETHER_STAT_CAP_100T4:
368 *val = igb->param_100t4_cap;
369 break;
370
371 case ETHER_STAT_ADV_CAP_100T4:
372 *val = igb->param_adv_100t4_cap;
373 break;
374
375 case ETHER_STAT_LP_CAP_100T4:
376 *val = igb->param_lp_100t4_cap;
377 break;
378
379 default:
380 mutex_exit(&igb->gen_lock);
381 return (ENOTSUP);
382 }
383
384 mutex_exit(&igb->gen_lock);
385
386 if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) {
387 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED);
388 return (EIO);
389 }
390
391 return (0);
392 }
393
394 /*
395 * Bring the device out of the reset/quiesced state that it
396 * was in when the interface was registered.
397 */
398 int
igb_m_start(void * arg)399 igb_m_start(void *arg)
400 {
401 igb_t *igb = (igb_t *)arg;
402
403 mutex_enter(&igb->gen_lock);
404
405 if (igb->igb_state & IGB_SUSPENDED) {
406 mutex_exit(&igb->gen_lock);
407 return (ECANCELED);
408 }
409
410 if (igb_start(igb, B_TRUE) != IGB_SUCCESS) {
411 mutex_exit(&igb->gen_lock);
412 return (EIO);
413 }
414
415 atomic_or_32(&igb->igb_state, IGB_STARTED);
416
417 mutex_exit(&igb->gen_lock);
418
419 /*
420 * Enable and start the watchdog timer
421 */
422 igb_enable_watchdog_timer(igb);
423
424 return (0);
425 }
426
427 /*
428 * Stop the device and put it in a reset/quiesced state such
429 * that the interface can be unregistered.
430 */
431 void
igb_m_stop(void * arg)432 igb_m_stop(void *arg)
433 {
434 igb_t *igb = (igb_t *)arg;
435
436 mutex_enter(&igb->gen_lock);
437
438 if (igb->igb_state & IGB_SUSPENDED) {
439 mutex_exit(&igb->gen_lock);
440 return;
441 }
442
443 atomic_and_32(&igb->igb_state, ~IGB_STARTED);
444
445 igb_stop(igb, B_TRUE);
446
447 mutex_exit(&igb->gen_lock);
448
449 /*
450 * Disable and stop the watchdog timer
451 */
452 igb_disable_watchdog_timer(igb);
453 }
454
455 /*
456 * Set the promiscuity of the device.
457 */
458 int
igb_m_promisc(void * arg,boolean_t on)459 igb_m_promisc(void *arg, boolean_t on)
460 {
461 igb_t *igb = (igb_t *)arg;
462 uint32_t reg_val;
463
464 mutex_enter(&igb->gen_lock);
465
466 if (igb->igb_state & IGB_SUSPENDED) {
467 mutex_exit(&igb->gen_lock);
468 return (ECANCELED);
469 }
470
471 reg_val = E1000_READ_REG(&igb->hw, E1000_RCTL);
472
473 if (on)
474 reg_val |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
475 else
476 reg_val &= (~(E1000_RCTL_UPE | E1000_RCTL_MPE));
477
478 E1000_WRITE_REG(&igb->hw, E1000_RCTL, reg_val);
479
480 mutex_exit(&igb->gen_lock);
481
482 if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) {
483 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED);
484 return (EIO);
485 }
486
487 return (0);
488 }
489
490 /*
491 * Add/remove the addresses to/from the set of multicast
492 * addresses for which the device will receive packets.
493 */
494 int
igb_m_multicst(void * arg,boolean_t add,const uint8_t * mcst_addr)495 igb_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr)
496 {
497 igb_t *igb = (igb_t *)arg;
498 int result;
499
500 mutex_enter(&igb->gen_lock);
501
502 if (igb->igb_state & IGB_SUSPENDED) {
503 mutex_exit(&igb->gen_lock);
504 return (ECANCELED);
505 }
506
507 result = (add) ? igb_multicst_add(igb, mcst_addr)
508 : igb_multicst_remove(igb, mcst_addr);
509
510 mutex_exit(&igb->gen_lock);
511
512 return (result);
513 }
514
515 /*
516 * Pass on M_IOCTL messages passed to the DLD, and support
517 * private IOCTLs for debugging and ndd.
518 */
519 void
igb_m_ioctl(void * arg,queue_t * q,mblk_t * mp)520 igb_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
521 {
522 igb_t *igb = (igb_t *)arg;
523 struct iocblk *iocp;
524 enum ioc_reply status;
525
526 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
527 iocp->ioc_error = 0;
528
529 mutex_enter(&igb->gen_lock);
530 if (igb->igb_state & IGB_SUSPENDED) {
531 mutex_exit(&igb->gen_lock);
532 miocnak(q, mp, 0, EINVAL);
533 return;
534 }
535 mutex_exit(&igb->gen_lock);
536
537 switch (iocp->ioc_cmd) {
538 case LB_GET_INFO_SIZE:
539 case LB_GET_INFO:
540 case LB_GET_MODE:
541 case LB_SET_MODE:
542 status = igb_loopback_ioctl(igb, iocp, mp);
543 break;
544
545 default:
546 status = IOC_INVAL;
547 break;
548 }
549
550 /*
551 * Decide how to reply
552 */
553 switch (status) {
554 default:
555 case IOC_INVAL:
556 /*
557 * Error, reply with a NAK and EINVAL or the specified error
558 */
559 miocnak(q, mp, 0, iocp->ioc_error == 0 ?
560 EINVAL : iocp->ioc_error);
561 break;
562
563 case IOC_DONE:
564 /*
565 * OK, reply already sent
566 */
567 break;
568
569 case IOC_ACK:
570 /*
571 * OK, reply with an ACK
572 */
573 miocack(q, mp, 0, 0);
574 break;
575
576 case IOC_REPLY:
577 /*
578 * OK, send prepared reply as ACK or NAK
579 */
580 mp->b_datap->db_type = iocp->ioc_error == 0 ?
581 M_IOCACK : M_IOCNAK;
582 qreply(q, mp);
583 break;
584 }
585 }
586
587 /*
588 * Add a MAC address to the target RX group.
589 */
590 static int
igb_addmac(void * arg,const uint8_t * mac_addr)591 igb_addmac(void *arg, const uint8_t *mac_addr)
592 {
593 igb_rx_group_t *rx_group = (igb_rx_group_t *)arg;
594 igb_t *igb = rx_group->igb;
595 struct e1000_hw *hw = &igb->hw;
596 int i, slot;
597
598 mutex_enter(&igb->gen_lock);
599
600 if (igb->igb_state & IGB_SUSPENDED) {
601 mutex_exit(&igb->gen_lock);
602 return (ECANCELED);
603 }
604
605 if (igb->unicst_avail == 0) {
606 /* no slots available */
607 mutex_exit(&igb->gen_lock);
608 return (ENOSPC);
609 }
610
611 /*
612 * The slots from 0 to igb->num_rx_groups are reserved slots which
613 * are 1 to 1 mapped with group index directly. The other slots are
614 * shared between the all of groups. While adding a MAC address,
615 * it will try to set the reserved slots first, then the shared slots.
616 */
617 slot = -1;
618 if (igb->unicst_addr[rx_group->index].mac.set == 1) {
619 /*
620 * The reserved slot for current group is used, find the free
621 * slots in the shared slots.
622 */
623 for (i = igb->num_rx_groups; i < igb->unicst_total; i++) {
624 if (igb->unicst_addr[i].mac.set == 0) {
625 slot = i;
626 break;
627 }
628 }
629 } else
630 slot = rx_group->index;
631
632 if (slot == -1) {
633 /* no slots available in the shared slots */
634 mutex_exit(&igb->gen_lock);
635 return (ENOSPC);
636 }
637
638 /* Set VMDq according to the mode supported by hardware. */
639 e1000_rar_set_vmdq(hw, mac_addr, slot, igb->vmdq_mode, rx_group->index);
640
641 bcopy(mac_addr, igb->unicst_addr[slot].mac.addr, ETHERADDRL);
642 igb->unicst_addr[slot].mac.group_index = rx_group->index;
643 igb->unicst_addr[slot].mac.set = 1;
644 igb->unicst_avail--;
645
646 mutex_exit(&igb->gen_lock);
647
648 return (0);
649 }
650
651 /*
652 * Remove a MAC address from the specified RX group.
653 */
654 static int
igb_remmac(void * arg,const uint8_t * mac_addr)655 igb_remmac(void *arg, const uint8_t *mac_addr)
656 {
657 igb_rx_group_t *rx_group = (igb_rx_group_t *)arg;
658 igb_t *igb = rx_group->igb;
659 struct e1000_hw *hw = &igb->hw;
660 int slot;
661
662 mutex_enter(&igb->gen_lock);
663
664 if (igb->igb_state & IGB_SUSPENDED) {
665 mutex_exit(&igb->gen_lock);
666 return (ECANCELED);
667 }
668
669 slot = igb_unicst_find(igb, mac_addr);
670 if (slot == -1) {
671 mutex_exit(&igb->gen_lock);
672 return (EINVAL);
673 }
674
675 if (igb->unicst_addr[slot].mac.set == 0) {
676 mutex_exit(&igb->gen_lock);
677 return (EINVAL);
678 }
679
680 /* Clear the MAC ddress in the slot */
681 e1000_rar_clear(hw, slot);
682 igb->unicst_addr[slot].mac.set = 0;
683 igb->unicst_avail++;
684
685 mutex_exit(&igb->gen_lock);
686
687 return (0);
688 }
689
690 /*
691 * Enable interrupt on the specificed rx ring.
692 */
693 int
igb_rx_ring_intr_enable(mac_intr_handle_t intrh)694 igb_rx_ring_intr_enable(mac_intr_handle_t intrh)
695 {
696 igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh;
697 igb_t *igb = rx_ring->igb;
698 struct e1000_hw *hw = &igb->hw;
699 uint32_t index = rx_ring->index;
700
701 if (igb->intr_type == DDI_INTR_TYPE_MSIX) {
702 /* Interrupt enabling for MSI-X */
703 igb->eims_mask |= (E1000_EICR_RX_QUEUE0 << index);
704 E1000_WRITE_REG(hw, E1000_EIMS, igb->eims_mask);
705 E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask);
706 } else {
707 ASSERT(index == 0);
708 /* Interrupt enabling for MSI and legacy */
709 igb->ims_mask |= E1000_IMS_RXT0;
710 E1000_WRITE_REG(hw, E1000_IMS, igb->ims_mask);
711 }
712
713 E1000_WRITE_FLUSH(hw);
714
715 return (0);
716 }
717
718 /*
719 * Disable interrupt on the specificed rx ring.
720 */
721 int
igb_rx_ring_intr_disable(mac_intr_handle_t intrh)722 igb_rx_ring_intr_disable(mac_intr_handle_t intrh)
723 {
724 igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)intrh;
725 igb_t *igb = rx_ring->igb;
726 struct e1000_hw *hw = &igb->hw;
727 uint32_t index = rx_ring->index;
728
729 if (igb->intr_type == DDI_INTR_TYPE_MSIX) {
730 /* Interrupt disabling for MSI-X */
731 igb->eims_mask &= ~(E1000_EICR_RX_QUEUE0 << index);
732 E1000_WRITE_REG(hw, E1000_EIMC,
733 (E1000_EICR_RX_QUEUE0 << index));
734 E1000_WRITE_REG(hw, E1000_EIAC, igb->eims_mask);
735 } else {
736 ASSERT(index == 0);
737 /* Interrupt disabling for MSI and legacy */
738 igb->ims_mask &= ~E1000_IMS_RXT0;
739 E1000_WRITE_REG(hw, E1000_IMC, E1000_IMS_RXT0);
740 }
741
742 E1000_WRITE_FLUSH(hw);
743
744 return (0);
745 }
746
747 /*
748 * Get the global ring index by a ring index within a group.
749 */
750 int
igb_get_rx_ring_index(igb_t * igb,int gindex,int rindex)751 igb_get_rx_ring_index(igb_t *igb, int gindex, int rindex)
752 {
753 igb_rx_ring_t *rx_ring;
754 int i;
755
756 for (i = 0; i < igb->num_rx_rings; i++) {
757 rx_ring = &igb->rx_rings[i];
758 if (rx_ring->group_index == gindex)
759 rindex--;
760 if (rindex < 0)
761 return (i);
762 }
763
764 return (-1);
765 }
766
767 static int
igb_ring_start(mac_ring_driver_t rh,uint64_t mr_gen_num)768 igb_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
769 {
770 igb_rx_ring_t *rx_ring = (igb_rx_ring_t *)rh;
771
772 mutex_enter(&rx_ring->rx_lock);
773 rx_ring->ring_gen_num = mr_gen_num;
774 mutex_exit(&rx_ring->rx_lock);
775 return (0);
776 }
777
778 /*
779 * Callback funtion for MAC layer to register all rings.
780 */
781 /* ARGSUSED */
782 void
igb_fill_ring(void * arg,mac_ring_type_t rtype,const int rg_index,const int index,mac_ring_info_t * infop,mac_ring_handle_t rh)783 igb_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
784 const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
785 {
786 igb_t *igb = (igb_t *)arg;
787 mac_intr_t *mintr = &infop->mri_intr;
788
789 switch (rtype) {
790 case MAC_RING_TYPE_RX: {
791 igb_rx_ring_t *rx_ring;
792 int global_index;
793
794 /*
795 * 'index' is the ring index within the group.
796 * We need the global ring index by searching in group.
797 */
798 global_index = igb_get_rx_ring_index(igb, rg_index, index);
799
800 ASSERT(global_index >= 0);
801
802 rx_ring = &igb->rx_rings[global_index];
803 rx_ring->ring_handle = rh;
804
805 infop->mri_driver = (mac_ring_driver_t)rx_ring;
806 infop->mri_start = igb_ring_start;
807 infop->mri_stop = NULL;
808 infop->mri_poll = (mac_ring_poll_t)igb_rx_ring_poll;
809 infop->mri_stat = igb_rx_ring_stat;
810
811 mintr->mi_handle = (mac_intr_handle_t)rx_ring;
812 mintr->mi_enable = igb_rx_ring_intr_enable;
813 mintr->mi_disable = igb_rx_ring_intr_disable;
814 if (igb->intr_type & (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
815 mintr->mi_ddi_handle =
816 igb->htable[rx_ring->intr_vector];
817 }
818 break;
819 }
820 case MAC_RING_TYPE_TX: {
821 ASSERT(index < igb->num_tx_rings);
822
823 igb_tx_ring_t *tx_ring = &igb->tx_rings[index];
824 tx_ring->ring_handle = rh;
825
826 infop->mri_driver = (mac_ring_driver_t)tx_ring;
827 infop->mri_start = NULL;
828 infop->mri_stop = NULL;
829 infop->mri_tx = igb_tx_ring_send;
830 infop->mri_stat = igb_tx_ring_stat;
831 if (igb->intr_type & (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
832 mintr->mi_ddi_handle =
833 igb->htable[tx_ring->intr_vector];
834 }
835 break;
836 }
837 default:
838 break;
839 }
840 }
841
842 void
igb_fill_group(void * arg,mac_ring_type_t rtype,const int index,mac_group_info_t * infop,mac_group_handle_t gh)843 igb_fill_group(void *arg, mac_ring_type_t rtype, const int index,
844 mac_group_info_t *infop, mac_group_handle_t gh)
845 {
846 igb_t *igb = (igb_t *)arg;
847
848 switch (rtype) {
849 case MAC_RING_TYPE_RX: {
850 igb_rx_group_t *rx_group;
851
852 ASSERT((index >= 0) && (index < igb->num_rx_groups));
853
854 rx_group = &igb->rx_groups[index];
855 rx_group->group_handle = gh;
856
857 infop->mgi_driver = (mac_group_driver_t)rx_group;
858 infop->mgi_start = NULL;
859 infop->mgi_stop = NULL;
860 infop->mgi_addmac = igb_addmac;
861 infop->mgi_remmac = igb_remmac;
862 infop->mgi_count = (igb->num_rx_rings / igb->num_rx_groups);
863
864 break;
865 }
866 case MAC_RING_TYPE_TX:
867 break;
868 default:
869 break;
870 }
871 }
872
873 static int
igb_led_set(void * arg,mac_led_mode_t mode,uint_t flags)874 igb_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
875 {
876 igb_t *igb = arg;
877
878 if (flags != 0)
879 return (EINVAL);
880
881 if (mode != MAC_LED_DEFAULT &&
882 mode != MAC_LED_IDENT &&
883 mode != MAC_LED_OFF &&
884 mode != MAC_LED_ON)
885 return (ENOTSUP);
886
887 if (mode != MAC_LED_DEFAULT && !igb->igb_led_setup) {
888 if (e1000_setup_led(&igb->hw) != E1000_SUCCESS)
889 return (EIO);
890
891 igb->igb_led_setup = B_TRUE;
892 }
893
894 switch (mode) {
895 case MAC_LED_DEFAULT:
896 if (igb->igb_led_setup) {
897 if (e1000_cleanup_led(&igb->hw) != E1000_SUCCESS)
898 return (EIO);
899 igb->igb_led_setup = B_FALSE;
900 }
901 break;
902 case MAC_LED_IDENT:
903 if (e1000_blink_led(&igb->hw) != E1000_SUCCESS)
904 return (EIO);
905 break;
906 case MAC_LED_OFF:
907 if (e1000_led_off(&igb->hw) != E1000_SUCCESS)
908 return (EIO);
909 break;
910 case MAC_LED_ON:
911 if (e1000_led_on(&igb->hw) != E1000_SUCCESS)
912 return (EIO);
913 break;
914 default:
915 return (ENOTSUP);
916 }
917
918 return (0);
919 }
920
921 /*
922 * Obtain the MAC's capabilities and associated data from
923 * the driver.
924 */
925 boolean_t
igb_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)926 igb_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
927 {
928 igb_t *igb = (igb_t *)arg;
929
930 switch (cap) {
931 case MAC_CAPAB_HCKSUM: {
932 uint32_t *tx_hcksum_flags = cap_data;
933
934 /*
935 * We advertise our capabilities only if tx hcksum offload is
936 * enabled. On receive, the stack will accept checksummed
937 * packets anyway, even if we haven't said we can deliver
938 * them.
939 */
940 if (!igb->tx_hcksum_enable)
941 return (B_FALSE);
942
943 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
944 break;
945 }
946 case MAC_CAPAB_LSO: {
947 mac_capab_lso_t *cap_lso = cap_data;
948
949 if (igb->lso_enable) {
950 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
951 LSO_TX_BASIC_TCP_IPV6;
952 cap_lso->lso_basic_tcp_ipv4.lso_max = IGB_LSO_MAXLEN;
953 cap_lso->lso_basic_tcp_ipv6.lso_max = IGB_LSO_MAXLEN;
954 break;
955 } else {
956 return (B_FALSE);
957 }
958 }
959 case MAC_CAPAB_RINGS: {
960 mac_capab_rings_t *cap_rings = cap_data;
961
962 switch (cap_rings->mr_type) {
963 case MAC_RING_TYPE_RX:
964 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
965 cap_rings->mr_rnum = igb->num_rx_rings;
966 cap_rings->mr_gnum = igb->num_rx_groups;
967 cap_rings->mr_rget = igb_fill_ring;
968 cap_rings->mr_gget = igb_fill_group;
969 cap_rings->mr_gaddring = NULL;
970 cap_rings->mr_gremring = NULL;
971
972 break;
973 case MAC_RING_TYPE_TX:
974 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
975 cap_rings->mr_rnum = igb->num_tx_rings;
976 cap_rings->mr_gnum = 0;
977 cap_rings->mr_rget = igb_fill_ring;
978 cap_rings->mr_gget = NULL;
979
980 break;
981 default:
982 break;
983 }
984 break;
985 }
986
987 case MAC_CAPAB_LED: {
988 mac_capab_led_t *cap_led = cap_data;
989
990 cap_led->mcl_flags = 0;
991 cap_led->mcl_modes = MAC_LED_DEFAULT;
992 if (igb->hw.mac.ops.blink_led != NULL &&
993 igb->hw.mac.ops.blink_led != e1000_null_ops_generic) {
994 cap_led->mcl_modes |= MAC_LED_IDENT;
995 }
996 if (igb->hw.mac.ops.led_off != NULL &&
997 igb->hw.mac.ops.led_off != e1000_null_ops_generic) {
998 cap_led->mcl_modes |= MAC_LED_OFF;
999 }
1000 if (igb->hw.mac.ops.led_on != NULL &&
1001 igb->hw.mac.ops.led_on != e1000_null_ops_generic) {
1002 cap_led->mcl_modes |= MAC_LED_ON;
1003 }
1004 cap_led->mcl_set = igb_led_set;
1005 break;
1006 }
1007
1008 default:
1009 return (B_FALSE);
1010 }
1011 return (B_TRUE);
1012 }
1013
1014 int
igb_m_setprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)1015 igb_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1016 uint_t pr_valsize, const void *pr_val)
1017 {
1018 igb_t *igb = (igb_t *)arg;
1019 struct e1000_hw *hw = &igb->hw;
1020 int err = 0;
1021 uint32_t flow_control;
1022 uint32_t cur_mtu, new_mtu;
1023 uint32_t rx_size;
1024 uint32_t tx_size;
1025
1026 mutex_enter(&igb->gen_lock);
1027 if (igb->igb_state & IGB_SUSPENDED) {
1028 mutex_exit(&igb->gen_lock);
1029 return (ECANCELED);
1030 }
1031
1032 if (igb->loopback_mode != IGB_LB_NONE && igb_param_locked(pr_num)) {
1033 /*
1034 * All en_* parameters are locked (read-only)
1035 * while the device is in any sort of loopback mode.
1036 */
1037 mutex_exit(&igb->gen_lock);
1038 return (EBUSY);
1039 }
1040
1041 switch (pr_num) {
1042 case MAC_PROP_EN_1000FDX_CAP:
1043 /* read/write on copper, read-only on serdes */
1044 if (hw->phy.media_type != e1000_media_type_copper) {
1045 err = ENOTSUP;
1046 break;
1047 }
1048 igb->param_en_1000fdx_cap = *(uint8_t *)pr_val;
1049 igb->param_adv_1000fdx_cap = *(uint8_t *)pr_val;
1050 goto setup_link;
1051 case MAC_PROP_EN_100FDX_CAP:
1052 if (hw->phy.media_type != e1000_media_type_copper) {
1053 err = ENOTSUP;
1054 break;
1055 }
1056 igb->param_en_100fdx_cap = *(uint8_t *)pr_val;
1057 igb->param_adv_100fdx_cap = *(uint8_t *)pr_val;
1058 goto setup_link;
1059 case MAC_PROP_EN_100HDX_CAP:
1060 if (hw->phy.media_type != e1000_media_type_copper) {
1061 err = ENOTSUP;
1062 break;
1063 }
1064 igb->param_en_100hdx_cap = *(uint8_t *)pr_val;
1065 igb->param_adv_100hdx_cap = *(uint8_t *)pr_val;
1066 goto setup_link;
1067 case MAC_PROP_EN_10FDX_CAP:
1068 if (hw->phy.media_type != e1000_media_type_copper) {
1069 err = ENOTSUP;
1070 break;
1071 }
1072 igb->param_en_10fdx_cap = *(uint8_t *)pr_val;
1073 igb->param_adv_10fdx_cap = *(uint8_t *)pr_val;
1074 goto setup_link;
1075 case MAC_PROP_EN_10HDX_CAP:
1076 if (hw->phy.media_type != e1000_media_type_copper) {
1077 err = ENOTSUP;
1078 break;
1079 }
1080 igb->param_en_10hdx_cap = *(uint8_t *)pr_val;
1081 igb->param_adv_10hdx_cap = *(uint8_t *)pr_val;
1082 goto setup_link;
1083 case MAC_PROP_AUTONEG:
1084 if (hw->phy.media_type != e1000_media_type_copper) {
1085 err = ENOTSUP;
1086 break;
1087 }
1088 igb->param_adv_autoneg_cap = *(uint8_t *)pr_val;
1089 goto setup_link;
1090 case MAC_PROP_FLOWCTRL:
1091 bcopy(pr_val, &flow_control, sizeof (flow_control));
1092
1093 switch (flow_control) {
1094 default:
1095 err = EINVAL;
1096 break;
1097 case LINK_FLOWCTRL_NONE:
1098 hw->fc.requested_mode = e1000_fc_none;
1099 break;
1100 case LINK_FLOWCTRL_RX:
1101 hw->fc.requested_mode = e1000_fc_rx_pause;
1102 break;
1103 case LINK_FLOWCTRL_TX:
1104 hw->fc.requested_mode = e1000_fc_tx_pause;
1105 break;
1106 case LINK_FLOWCTRL_BI:
1107 hw->fc.requested_mode = e1000_fc_full;
1108 break;
1109 }
1110 setup_link:
1111 if (err == 0) {
1112 if (igb_setup_link(igb, B_TRUE) != IGB_SUCCESS)
1113 err = EINVAL;
1114 }
1115 break;
1116 case MAC_PROP_ADV_1000FDX_CAP:
1117 case MAC_PROP_ADV_1000HDX_CAP:
1118 case MAC_PROP_ADV_100T4_CAP:
1119 case MAC_PROP_ADV_100FDX_CAP:
1120 case MAC_PROP_ADV_100HDX_CAP:
1121 case MAC_PROP_ADV_10FDX_CAP:
1122 case MAC_PROP_ADV_10HDX_CAP:
1123 case MAC_PROP_EN_1000HDX_CAP:
1124 case MAC_PROP_EN_100T4_CAP:
1125 case MAC_PROP_STATUS:
1126 case MAC_PROP_SPEED:
1127 case MAC_PROP_DUPLEX:
1128 case MAC_PROP_MEDIA:
1129 err = ENOTSUP; /* read-only prop. Can't set this. */
1130 break;
1131 case MAC_PROP_MTU:
1132 /* adapter must be stopped for an MTU change */
1133 if (igb->igb_state & IGB_STARTED) {
1134 err = EBUSY;
1135 break;
1136 }
1137
1138 cur_mtu = igb->default_mtu;
1139 bcopy(pr_val, &new_mtu, sizeof (new_mtu));
1140 if (new_mtu == cur_mtu) {
1141 err = 0;
1142 break;
1143 }
1144
1145 if (new_mtu < MIN_MTU || new_mtu > MAX_MTU) {
1146 err = EINVAL;
1147 break;
1148 }
1149
1150 err = mac_maxsdu_update(igb->mac_hdl, new_mtu);
1151 if (err == 0) {
1152 igb->default_mtu = new_mtu;
1153 igb->max_frame_size = igb->default_mtu +
1154 sizeof (struct ether_vlan_header) + ETHERFCSL;
1155
1156 /*
1157 * Set rx buffer size
1158 */
1159 rx_size = igb->max_frame_size + IPHDR_ALIGN_ROOM;
1160 igb->rx_buf_size = ((rx_size >> 10) + ((rx_size &
1161 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
1162
1163 /*
1164 * Set tx buffer size
1165 */
1166 tx_size = igb->max_frame_size;
1167 igb->tx_buf_size = ((tx_size >> 10) + ((tx_size &
1168 (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
1169 }
1170 break;
1171 case MAC_PROP_PRIVATE:
1172 err = igb_set_priv_prop(igb, pr_name, pr_valsize, pr_val);
1173 break;
1174 default:
1175 err = ENOTSUP;
1176 break;
1177 }
1178
1179 mutex_exit(&igb->gen_lock);
1180
1181 if (igb_check_acc_handle(igb->osdep.reg_handle) != DDI_FM_OK) {
1182 ddi_fm_service_impact(igb->dip, DDI_SERVICE_DEGRADED);
1183 return (EIO);
1184 }
1185
1186 return (err);
1187 }
1188
1189 int
igb_m_getprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)1190 igb_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1191 uint_t pr_valsize, void *pr_val)
1192 {
1193 igb_t *igb = (igb_t *)arg;
1194 struct e1000_hw *hw = &igb->hw;
1195 int err = 0;
1196 uint32_t flow_control;
1197 uint64_t tmp = 0;
1198
1199 switch (pr_num) {
1200 case MAC_PROP_DUPLEX:
1201 ASSERT(pr_valsize >= sizeof (link_duplex_t));
1202 bcopy(&igb->link_duplex, pr_val, sizeof (link_duplex_t));
1203 break;
1204 case MAC_PROP_SPEED:
1205 ASSERT(pr_valsize >= sizeof (uint64_t));
1206 tmp = igb->link_speed * 1000000ull;
1207 bcopy(&tmp, pr_val, sizeof (tmp));
1208 break;
1209 case MAC_PROP_AUTONEG:
1210 ASSERT(pr_valsize >= sizeof (uint8_t));
1211 *(uint8_t *)pr_val = igb->param_adv_autoneg_cap;
1212 break;
1213 case MAC_PROP_FLOWCTRL:
1214 ASSERT(pr_valsize >= sizeof (uint32_t));
1215 switch (hw->fc.requested_mode) {
1216 case e1000_fc_none:
1217 flow_control = LINK_FLOWCTRL_NONE;
1218 break;
1219 case e1000_fc_rx_pause:
1220 flow_control = LINK_FLOWCTRL_RX;
1221 break;
1222 case e1000_fc_tx_pause:
1223 flow_control = LINK_FLOWCTRL_TX;
1224 break;
1225 case e1000_fc_full:
1226 flow_control = LINK_FLOWCTRL_BI;
1227 break;
1228 }
1229 bcopy(&flow_control, pr_val, sizeof (flow_control));
1230 break;
1231 case MAC_PROP_ADV_1000FDX_CAP:
1232 *(uint8_t *)pr_val = igb->param_adv_1000fdx_cap;
1233 break;
1234 case MAC_PROP_EN_1000FDX_CAP:
1235 *(uint8_t *)pr_val = igb->param_en_1000fdx_cap;
1236 break;
1237 case MAC_PROP_ADV_1000HDX_CAP:
1238 *(uint8_t *)pr_val = igb->param_adv_1000hdx_cap;
1239 break;
1240 case MAC_PROP_EN_1000HDX_CAP:
1241 *(uint8_t *)pr_val = igb->param_en_1000hdx_cap;
1242 break;
1243 case MAC_PROP_ADV_100T4_CAP:
1244 *(uint8_t *)pr_val = igb->param_adv_100t4_cap;
1245 break;
1246 case MAC_PROP_EN_100T4_CAP:
1247 *(uint8_t *)pr_val = igb->param_en_100t4_cap;
1248 break;
1249 case MAC_PROP_ADV_100FDX_CAP:
1250 *(uint8_t *)pr_val = igb->param_adv_100fdx_cap;
1251 break;
1252 case MAC_PROP_EN_100FDX_CAP:
1253 *(uint8_t *)pr_val = igb->param_en_100fdx_cap;
1254 break;
1255 case MAC_PROP_ADV_100HDX_CAP:
1256 *(uint8_t *)pr_val = igb->param_adv_100hdx_cap;
1257 break;
1258 case MAC_PROP_EN_100HDX_CAP:
1259 *(uint8_t *)pr_val = igb->param_en_100hdx_cap;
1260 break;
1261 case MAC_PROP_ADV_10FDX_CAP:
1262 *(uint8_t *)pr_val = igb->param_adv_10fdx_cap;
1263 break;
1264 case MAC_PROP_EN_10FDX_CAP:
1265 *(uint8_t *)pr_val = igb->param_en_10fdx_cap;
1266 break;
1267 case MAC_PROP_ADV_10HDX_CAP:
1268 *(uint8_t *)pr_val = igb->param_adv_10hdx_cap;
1269 break;
1270 case MAC_PROP_EN_10HDX_CAP:
1271 *(uint8_t *)pr_val = igb->param_en_10hdx_cap;
1272 break;
1273 case MAC_PROP_MEDIA:
1274 *(mac_ether_media_t *)pr_val = e1000_link_to_media(hw,
1275 igb->link_speed);
1276 break;
1277 case MAC_PROP_PRIVATE:
1278 err = igb_get_priv_prop(igb, pr_name, pr_valsize, pr_val);
1279 break;
1280 default:
1281 err = ENOTSUP;
1282 break;
1283 }
1284 return (err);
1285 }
1286
1287 void
igb_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)1288 igb_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1289 mac_prop_info_handle_t prh)
1290 {
1291 igb_t *igb = (igb_t *)arg;
1292 struct e1000_hw *hw = &igb->hw;
1293 uint16_t phy_status, phy_ext_status;
1294
1295 switch (pr_num) {
1296 case MAC_PROP_DUPLEX:
1297 case MAC_PROP_SPEED:
1298 case MAC_PROP_ADV_1000FDX_CAP:
1299 case MAC_PROP_ADV_1000HDX_CAP:
1300 case MAC_PROP_EN_1000HDX_CAP:
1301 case MAC_PROP_ADV_100T4_CAP:
1302 case MAC_PROP_EN_100T4_CAP:
1303 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1304 break;
1305
1306 case MAC_PROP_EN_1000FDX_CAP:
1307 if (hw->phy.media_type != e1000_media_type_copper) {
1308 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1309 } else {
1310 (void) e1000_read_phy_reg(hw, PHY_EXT_STATUS,
1311 &phy_ext_status);
1312 mac_prop_info_set_default_uint8(prh,
1313 ((phy_ext_status & IEEE_ESR_1000T_FD_CAPS) ||
1314 (phy_ext_status & IEEE_ESR_1000X_FD_CAPS)) ? 1 : 0);
1315 }
1316 break;
1317
1318 case MAC_PROP_ADV_100FDX_CAP:
1319 case MAC_PROP_EN_100FDX_CAP:
1320 if (hw->phy.media_type != e1000_media_type_copper) {
1321 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1322 } else {
1323 (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1324 mac_prop_info_set_default_uint8(prh,
1325 ((phy_status & MII_SR_100X_FD_CAPS) ||
1326 (phy_status & MII_SR_100T2_FD_CAPS)) ? 1 : 0);
1327 }
1328 break;
1329
1330 case MAC_PROP_ADV_100HDX_CAP:
1331 case MAC_PROP_EN_100HDX_CAP:
1332 if (hw->phy.media_type != e1000_media_type_copper) {
1333 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1334 } else {
1335 (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1336 mac_prop_info_set_default_uint8(prh,
1337 ((phy_status & MII_SR_100X_HD_CAPS) ||
1338 (phy_status & MII_SR_100T2_HD_CAPS)) ? 1 : 0);
1339 }
1340 break;
1341
1342 case MAC_PROP_ADV_10FDX_CAP:
1343 case MAC_PROP_EN_10FDX_CAP:
1344 if (hw->phy.media_type != e1000_media_type_copper) {
1345 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1346 } else {
1347 (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1348 mac_prop_info_set_default_uint8(prh,
1349 (phy_status & MII_SR_10T_FD_CAPS) ? 1 : 0);
1350 }
1351 break;
1352
1353 case MAC_PROP_ADV_10HDX_CAP:
1354 case MAC_PROP_EN_10HDX_CAP:
1355 if (hw->phy.media_type != e1000_media_type_copper) {
1356 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1357 } else {
1358 (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1359 mac_prop_info_set_default_uint8(prh,
1360 (phy_status & MII_SR_10T_HD_CAPS) ? 1 : 0);
1361 }
1362 break;
1363
1364 case MAC_PROP_AUTONEG:
1365 if (hw->phy.media_type != e1000_media_type_copper) {
1366 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1367 } else {
1368 (void) e1000_read_phy_reg(hw, PHY_STATUS, &phy_status);
1369 mac_prop_info_set_default_uint8(prh,
1370 (phy_status & MII_SR_AUTONEG_CAPS) ? 1 : 0);
1371 }
1372 break;
1373
1374 case MAC_PROP_FLOWCTRL:
1375 mac_prop_info_set_default_link_flowctrl(prh, LINK_FLOWCTRL_BI);
1376 break;
1377
1378 case MAC_PROP_MTU:
1379 mac_prop_info_set_range_uint32(prh, MIN_MTU, MAX_MTU);
1380 break;
1381
1382 case MAC_PROP_PRIVATE:
1383 igb_priv_prop_info(igb, pr_name, prh);
1384 break;
1385 }
1386
1387 }
1388
1389 boolean_t
igb_param_locked(mac_prop_id_t pr_num)1390 igb_param_locked(mac_prop_id_t pr_num)
1391 {
1392 /*
1393 * All en_* parameters are locked (read-only) while
1394 * the device is in any sort of loopback mode ...
1395 */
1396 switch (pr_num) {
1397 case MAC_PROP_EN_1000FDX_CAP:
1398 case MAC_PROP_EN_1000HDX_CAP:
1399 case MAC_PROP_EN_100T4_CAP:
1400 case MAC_PROP_EN_100FDX_CAP:
1401 case MAC_PROP_EN_100HDX_CAP:
1402 case MAC_PROP_EN_10FDX_CAP:
1403 case MAC_PROP_EN_10HDX_CAP:
1404 case MAC_PROP_AUTONEG:
1405 case MAC_PROP_FLOWCTRL:
1406 return (B_TRUE);
1407 }
1408 return (B_FALSE);
1409 }
1410
1411 /* ARGSUSED */
1412 int
igb_set_priv_prop(igb_t * igb,const char * pr_name,uint_t pr_valsize,const void * pr_val)1413 igb_set_priv_prop(igb_t *igb, const char *pr_name,
1414 uint_t pr_valsize, const void *pr_val)
1415 {
1416 int err = 0;
1417 long result;
1418 struct e1000_hw *hw = &igb->hw;
1419 int i;
1420
1421 if (strcmp(pr_name, "_eee_support") == 0) {
1422 if (pr_val == NULL)
1423 return (EINVAL);
1424 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1425 switch (result) {
1426 case 0:
1427 case 1:
1428 /*
1429 * For now, only supported on I350/I354.
1430 * Add new mac.type values (or use < instead)
1431 * as new cards offer up EEE.
1432 */
1433 switch (hw->mac.type) {
1434 case e1000_i350:
1435 /* Must set this prior to the set call. */
1436 hw->dev_spec._82575.eee_disable = !result;
1437 if (e1000_set_eee_i350(hw, result,
1438 result) != E1000_SUCCESS)
1439 err = EIO;
1440 break;
1441 case e1000_i354:
1442 /* Must set this prior to the set call. */
1443 hw->dev_spec._82575.eee_disable = !result;
1444 if (e1000_set_eee_i354(hw, result,
1445 result) != E1000_SUCCESS)
1446 err = EIO;
1447 break;
1448 default:
1449 return (ENXIO);
1450 }
1451 break;
1452 default:
1453 err = EINVAL;
1454 /* FALLTHRU */
1455 }
1456 return (err);
1457 }
1458 if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1459 if (pr_val == NULL) {
1460 err = EINVAL;
1461 return (err);
1462 }
1463 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1464 if (result < MIN_TX_COPY_THRESHOLD ||
1465 result > MAX_TX_COPY_THRESHOLD)
1466 err = EINVAL;
1467 else {
1468 igb->tx_copy_thresh = (uint32_t)result;
1469 }
1470 return (err);
1471 }
1472 if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1473 if (pr_val == NULL) {
1474 err = EINVAL;
1475 return (err);
1476 }
1477 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1478 if (result < MIN_TX_RECYCLE_THRESHOLD ||
1479 result > MAX_TX_RECYCLE_THRESHOLD)
1480 err = EINVAL;
1481 else {
1482 igb->tx_recycle_thresh = (uint32_t)result;
1483 }
1484 return (err);
1485 }
1486 if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1487 if (pr_val == NULL) {
1488 err = EINVAL;
1489 return (err);
1490 }
1491 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1492 if (result < MIN_TX_OVERLOAD_THRESHOLD ||
1493 result > MAX_TX_OVERLOAD_THRESHOLD)
1494 err = EINVAL;
1495 else {
1496 igb->tx_overload_thresh = (uint32_t)result;
1497 }
1498 return (err);
1499 }
1500 if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1501 if (pr_val == NULL) {
1502 err = EINVAL;
1503 return (err);
1504 }
1505 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1506 if (result < MIN_TX_RESCHED_THRESHOLD ||
1507 result > MAX_TX_RESCHED_THRESHOLD ||
1508 result > igb->tx_ring_size)
1509 err = EINVAL;
1510 else {
1511 igb->tx_resched_thresh = (uint32_t)result;
1512 }
1513 return (err);
1514 }
1515 if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1516 if (pr_val == NULL) {
1517 err = EINVAL;
1518 return (err);
1519 }
1520 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1521 if (result < MIN_RX_COPY_THRESHOLD ||
1522 result > MAX_RX_COPY_THRESHOLD)
1523 err = EINVAL;
1524 else {
1525 igb->rx_copy_thresh = (uint32_t)result;
1526 }
1527 return (err);
1528 }
1529 if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1530 if (pr_val == NULL) {
1531 err = EINVAL;
1532 return (err);
1533 }
1534 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1535 if (result < MIN_RX_LIMIT_PER_INTR ||
1536 result > MAX_RX_LIMIT_PER_INTR)
1537 err = EINVAL;
1538 else {
1539 igb->rx_limit_per_intr = (uint32_t)result;
1540 }
1541 return (err);
1542 }
1543 if (strcmp(pr_name, "_intr_throttling") == 0) {
1544 if (pr_val == NULL) {
1545 err = EINVAL;
1546 return (err);
1547 }
1548 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
1549
1550 if (result < igb->capab->min_intr_throttle ||
1551 result > igb->capab->max_intr_throttle)
1552 err = EINVAL;
1553 else {
1554 igb->intr_throttling[0] = (uint32_t)result;
1555
1556 for (i = 0; i < MAX_NUM_EITR; i++)
1557 igb->intr_throttling[i] =
1558 igb->intr_throttling[0];
1559
1560 /* Set interrupt throttling rate */
1561 for (i = 0; i < igb->intr_cnt; i++)
1562 E1000_WRITE_REG(hw, E1000_EITR(i),
1563 igb->intr_throttling[i]);
1564 }
1565 return (err);
1566 }
1567 return (ENOTSUP);
1568 }
1569
1570 int
igb_get_priv_prop(igb_t * igb,const char * pr_name,uint_t pr_valsize,void * pr_val)1571 igb_get_priv_prop(igb_t *igb, const char *pr_name, uint_t pr_valsize,
1572 void *pr_val)
1573 {
1574 int value;
1575
1576 if (strcmp(pr_name, "_adv_pause_cap") == 0) {
1577 value = igb->param_adv_pause_cap;
1578 } else if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1579 value = igb->param_adv_asym_pause_cap;
1580 } else if (strcmp(pr_name, "_eee_support") == 0) {
1581 /*
1582 * For now, only supported on I350. Add new mac.type values
1583 * (or use < instead) as new cards offer up EEE.
1584 */
1585 switch (igb->hw.mac.type) {
1586 case e1000_i350:
1587 case e1000_i354:
1588 value = !(igb->hw.dev_spec._82575.eee_disable);
1589 break;
1590 default:
1591 value = 0;
1592 }
1593 } else if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1594 value = igb->tx_copy_thresh;
1595 } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1596 value = igb->tx_recycle_thresh;
1597 } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1598 value = igb->tx_overload_thresh;
1599 } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1600 value = igb->tx_resched_thresh;
1601 } else if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1602 value = igb->rx_copy_thresh;
1603 } else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1604 value = igb->rx_limit_per_intr;
1605 } else if (strcmp(pr_name, "_intr_throttling") == 0) {
1606 value = igb->intr_throttling[0];
1607 } else {
1608 return (ENOTSUP);
1609 }
1610
1611 (void) snprintf(pr_val, pr_valsize, "%d", value);
1612 return (0);
1613 }
1614
1615 void
igb_priv_prop_info(igb_t * igb,const char * pr_name,mac_prop_info_handle_t prh)1616 igb_priv_prop_info(igb_t *igb, const char *pr_name, mac_prop_info_handle_t prh)
1617 {
1618 char valstr[64];
1619 int value;
1620
1621 if (strcmp(pr_name, "_adv_pause_cap") == 0 ||
1622 strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1623 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1624 return;
1625 } else if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1626 value = DEFAULT_TX_COPY_THRESHOLD;
1627 } else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1628 value = DEFAULT_TX_RECYCLE_THRESHOLD;
1629 } else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1630 value = DEFAULT_TX_OVERLOAD_THRESHOLD;
1631 } else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1632 value = DEFAULT_TX_RESCHED_THRESHOLD;
1633 } else if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1634 value = DEFAULT_RX_COPY_THRESHOLD;
1635 } else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1636 value = DEFAULT_RX_LIMIT_PER_INTR;
1637 } else if (strcmp(pr_name, "_intr_throttling") == 0) {
1638 value = igb->capab->def_intr_throttle;
1639 } else {
1640 return;
1641 }
1642
1643 (void) snprintf(valstr, sizeof (valstr), "%d", value);
1644 mac_prop_info_set_default_str(prh, valstr);
1645 }
1646