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