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