xref: /illumos-gate/usr/src/uts/common/io/ixgbe/ixgbe_gld.c (revision 9164a50bf932130cbb5097a16f6986873ce0e6e5)
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 2012 Nexenta Systems, Inc. All rights reserved.
29  * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved.
30  * Copyright (c) 2019, Joyent, Inc.
31  */
32 
33 #include "ixgbe_sw.h"
34 
35 /*
36  * Bring the device out of the reset/quiesced state that it
37  * was in when the interface was registered.
38  */
39 int
40 ixgbe_m_start(void *arg)
41 {
42 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
43 
44 	mutex_enter(&ixgbe->gen_lock);
45 
46 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
47 		mutex_exit(&ixgbe->gen_lock);
48 		return (ECANCELED);
49 	}
50 
51 	if (ixgbe_start(ixgbe, B_TRUE) != IXGBE_SUCCESS) {
52 		mutex_exit(&ixgbe->gen_lock);
53 		return (EIO);
54 	}
55 
56 	atomic_or_32(&ixgbe->ixgbe_state, IXGBE_STARTED);
57 
58 	mutex_exit(&ixgbe->gen_lock);
59 
60 	/*
61 	 * Enable and start the watchdog timer
62 	 */
63 	ixgbe_enable_watchdog_timer(ixgbe);
64 
65 	return (0);
66 }
67 
68 /*
69  * Stop the device and put it in a reset/quiesced state such
70  * that the interface can be unregistered.
71  */
72 void
73 ixgbe_m_stop(void *arg)
74 {
75 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
76 
77 	mutex_enter(&ixgbe->gen_lock);
78 
79 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
80 		mutex_exit(&ixgbe->gen_lock);
81 		return;
82 	}
83 
84 	atomic_and_32(&ixgbe->ixgbe_state, ~IXGBE_STARTED);
85 
86 	ixgbe_stop(ixgbe, B_TRUE);
87 
88 	mutex_exit(&ixgbe->gen_lock);
89 
90 	/*
91 	 * Disable and stop the watchdog timer
92 	 */
93 	ixgbe_disable_watchdog_timer(ixgbe);
94 }
95 
96 /*
97  * Set the promiscuity of the device.
98  */
99 int
100 ixgbe_m_promisc(void *arg, boolean_t on)
101 {
102 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
103 	uint32_t reg_val;
104 	struct ixgbe_hw *hw = &ixgbe->hw;
105 
106 	mutex_enter(&ixgbe->gen_lock);
107 
108 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
109 		mutex_exit(&ixgbe->gen_lock);
110 		return (ECANCELED);
111 	}
112 	reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL);
113 
114 	if (on)
115 		reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
116 	else
117 		reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE));
118 
119 	IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val);
120 
121 	mutex_exit(&ixgbe->gen_lock);
122 
123 	return (0);
124 }
125 
126 /*
127  * Add/remove the addresses to/from the set of multicast
128  * addresses for which the device will receive packets.
129  */
130 int
131 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr)
132 {
133 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
134 	int result;
135 
136 	mutex_enter(&ixgbe->gen_lock);
137 
138 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
139 		mutex_exit(&ixgbe->gen_lock);
140 		return (ECANCELED);
141 	}
142 
143 	result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr)
144 	    : ixgbe_multicst_remove(ixgbe, mcst_addr);
145 
146 	mutex_exit(&ixgbe->gen_lock);
147 
148 	return (result);
149 }
150 
151 /*
152  * Pass on M_IOCTL messages passed to the DLD, and support
153  * private IOCTLs for debugging and ndd.
154  */
155 void
156 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
157 {
158 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
159 	struct iocblk *iocp;
160 	enum ioc_reply status;
161 
162 	iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
163 	iocp->ioc_error = 0;
164 
165 	mutex_enter(&ixgbe->gen_lock);
166 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
167 		mutex_exit(&ixgbe->gen_lock);
168 		miocnak(q, mp, 0, EINVAL);
169 		return;
170 	}
171 	mutex_exit(&ixgbe->gen_lock);
172 
173 	switch (iocp->ioc_cmd) {
174 	case LB_GET_INFO_SIZE:
175 	case LB_GET_INFO:
176 	case LB_GET_MODE:
177 	case LB_SET_MODE:
178 		status = ixgbe_loopback_ioctl(ixgbe, iocp, mp);
179 		break;
180 
181 	default:
182 		status = IOC_INVAL;
183 		break;
184 	}
185 
186 	/*
187 	 * Decide how to reply
188 	 */
189 	switch (status) {
190 	default:
191 	case IOC_INVAL:
192 		/*
193 		 * Error, reply with a NAK and EINVAL or the specified error
194 		 */
195 		miocnak(q, mp, 0, iocp->ioc_error == 0 ?
196 		    EINVAL : iocp->ioc_error);
197 		break;
198 
199 	case IOC_DONE:
200 		/*
201 		 * OK, reply already sent
202 		 */
203 		break;
204 
205 	case IOC_ACK:
206 		/*
207 		 * OK, reply with an ACK
208 		 */
209 		miocack(q, mp, 0, 0);
210 		break;
211 
212 	case IOC_REPLY:
213 		/*
214 		 * OK, send prepared reply as ACK or NAK
215 		 */
216 		mp->b_datap->db_type = iocp->ioc_error == 0 ?
217 		    M_IOCACK : M_IOCNAK;
218 		qreply(q, mp);
219 		break;
220 	}
221 }
222 
223 static int
224 ixgbe_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
225 {
226 	ixgbe_t *ixgbe = arg;
227 	struct ixgbe_hw *hw = &ixgbe->hw;
228 	uint32_t lidx = ixgbe->ixgbe_led_index;
229 
230 	if (flags != 0)
231 		return (EINVAL);
232 
233 	if (mode != MAC_LED_DEFAULT &&
234 	    mode != MAC_LED_IDENT &&
235 	    mode != MAC_LED_OFF &&
236 	    mode != MAC_LED_ON)
237 		return (ENOTSUP);
238 
239 	if (ixgbe->ixgbe_led_blink && mode != MAC_LED_IDENT) {
240 		if (ixgbe_blink_led_stop(hw, lidx) != IXGBE_SUCCESS) {
241 			return (EIO);
242 		}
243 		ixgbe->ixgbe_led_blink = B_FALSE;
244 	}
245 
246 	if (mode != MAC_LED_DEFAULT && !ixgbe->ixgbe_led_active) {
247 		ixgbe->ixgbe_led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
248 		ixgbe->ixgbe_led_active = B_TRUE;
249 	}
250 
251 	switch (mode) {
252 	case MAC_LED_DEFAULT:
253 		if (ixgbe->ixgbe_led_active) {
254 			IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ixgbe->ixgbe_led_reg);
255 			ixgbe->ixgbe_led_active = B_FALSE;
256 		}
257 		break;
258 	case MAC_LED_IDENT:
259 		if (ixgbe_blink_led_start(hw, lidx) != IXGBE_SUCCESS)
260 			return (EIO);
261 		ixgbe->ixgbe_led_blink = B_TRUE;
262 		break;
263 	case MAC_LED_OFF:
264 		if (ixgbe_led_off(hw, lidx) != IXGBE_SUCCESS)
265 			return (EIO);
266 		break;
267 	case MAC_LED_ON:
268 		if (ixgbe_led_on(hw, lidx) != IXGBE_SUCCESS)
269 			return (EIO);
270 		break;
271 	default:
272 		return (ENOTSUP);
273 	}
274 
275 	return (0);
276 }
277 
278 /*
279  * Obtain the MAC's capabilities and associated data from
280  * the driver.
281  */
282 boolean_t
283 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
284 {
285 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
286 
287 	switch (cap) {
288 	case MAC_CAPAB_HCKSUM: {
289 		uint32_t *tx_hcksum_flags = cap_data;
290 
291 		/*
292 		 * We advertise our capabilities only if tx hcksum offload is
293 		 * enabled.  On receive, the stack will accept checksummed
294 		 * packets anyway, even if we haven't said we can deliver
295 		 * them.
296 		 */
297 		if (!ixgbe->tx_hcksum_enable)
298 			return (B_FALSE);
299 
300 		*tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
301 		break;
302 	}
303 	case MAC_CAPAB_LSO: {
304 		mac_capab_lso_t *cap_lso = cap_data;
305 
306 		if (ixgbe->lso_enable) {
307 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
308 			    LSO_TX_BASIC_TCP_IPV6;
309 			cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN;
310 			cap_lso->lso_basic_tcp_ipv6.lso_max = IXGBE_LSO_MAXLEN;
311 			break;
312 		} else {
313 			return (B_FALSE);
314 		}
315 	}
316 	case MAC_CAPAB_RINGS: {
317 		mac_capab_rings_t *cap_rings = cap_data;
318 
319 		switch (cap_rings->mr_type) {
320 		case MAC_RING_TYPE_RX:
321 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
322 			cap_rings->mr_rnum = ixgbe->num_rx_rings;
323 			cap_rings->mr_gnum = ixgbe->num_rx_groups;
324 			cap_rings->mr_rget = ixgbe_fill_ring;
325 			cap_rings->mr_gget = ixgbe_fill_group;
326 			cap_rings->mr_gaddring = NULL;
327 			cap_rings->mr_gremring = NULL;
328 			break;
329 		case MAC_RING_TYPE_TX:
330 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
331 			cap_rings->mr_rnum = ixgbe->num_tx_rings;
332 			cap_rings->mr_gnum = 0;
333 			cap_rings->mr_rget = ixgbe_fill_ring;
334 			cap_rings->mr_gget = NULL;
335 			break;
336 		default:
337 			break;
338 		}
339 		break;
340 	}
341 	case MAC_CAPAB_TRANSCEIVER: {
342 		mac_capab_transceiver_t *mct = cap_data;
343 
344 		/*
345 		 * Rather than try and guess based on the media type whether or
346 		 * not we have a transceiver we can read, we instead will let
347 		 * the actual function calls figure that out for us.
348 		 */
349 		mct->mct_flags = 0;
350 		mct->mct_ntransceivers = 1;
351 		mct->mct_info = ixgbe_transceiver_info;
352 		mct->mct_read = ixgbe_transceiver_read;
353 		return (B_TRUE);
354 	}
355 	case MAC_CAPAB_LED: {
356 		mac_capab_led_t *mcl = cap_data;
357 
358 		mcl->mcl_flags = 0;
359 		mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_ON | MAC_LED_OFF |
360 		    MAC_LED_IDENT;
361 		mcl->mcl_set = ixgbe_led_set;
362 		break;
363 
364 	}
365 	default:
366 		return (B_FALSE);
367 	}
368 	return (B_TRUE);
369 }
370 
371 int
372 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
373     uint_t pr_valsize, const void *pr_val)
374 {
375 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
376 	struct ixgbe_hw *hw = &ixgbe->hw;
377 	int err = 0;
378 	uint32_t flow_control;
379 	uint32_t cur_mtu, new_mtu;
380 	uint32_t rx_size;
381 	uint32_t tx_size;
382 	ixgbe_link_speed speeds = 0;
383 
384 	mutex_enter(&ixgbe->gen_lock);
385 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
386 		mutex_exit(&ixgbe->gen_lock);
387 		return (ECANCELED);
388 	}
389 
390 	/*
391 	 * We cannot always rely on the common code maintaining
392 	 * hw->phy.speeds_supported, therefore we fall back to use the recorded
393 	 * supported speeds which were obtained during instance init in
394 	 * ixgbe_init_params().
395 	 */
396 	speeds = hw->phy.speeds_supported;
397 	if (speeds == 0)
398 		speeds = ixgbe->speeds_supported;
399 
400 	if (ixgbe->loopback_mode != IXGBE_LB_NONE &&
401 	    ixgbe_param_locked(pr_num)) {
402 		/*
403 		 * All en_* parameters are locked (read-only)
404 		 * while the device is in any sort of loopback mode.
405 		 */
406 		mutex_exit(&ixgbe->gen_lock);
407 		return (EBUSY);
408 	}
409 
410 	/*
411 	 * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
412 	 * read-only on non-baseT PHYs.
413 	 */
414 	switch (pr_num) {
415 	case MAC_PROP_EN_10GFDX_CAP:
416 		if (hw->phy.media_type == ixgbe_media_type_copper &&
417 		    speeds & IXGBE_LINK_SPEED_10GB_FULL) {
418 			ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val;
419 			goto setup_link;
420 		} else {
421 			err = ENOTSUP;
422 			break;
423 		}
424 	case MAC_PROP_EN_5000FDX_CAP:
425 		if (hw->phy.media_type == ixgbe_media_type_copper &&
426 		    speeds & IXGBE_LINK_SPEED_5GB_FULL) {
427 			ixgbe->param_en_5000fdx_cap = *(uint8_t *)pr_val;
428 			goto setup_link;
429 		} else {
430 			err = ENOTSUP;
431 			break;
432 		}
433 	case MAC_PROP_EN_2500FDX_CAP:
434 		if (hw->phy.media_type == ixgbe_media_type_copper &&
435 		    speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
436 			ixgbe->param_en_2500fdx_cap = *(uint8_t *)pr_val;
437 			goto setup_link;
438 		} else {
439 			err = ENOTSUP;
440 			break;
441 		}
442 	case MAC_PROP_EN_1000FDX_CAP:
443 		if (hw->phy.media_type == ixgbe_media_type_copper &&
444 		    speeds & IXGBE_LINK_SPEED_1GB_FULL) {
445 			ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val;
446 			goto setup_link;
447 		} else {
448 			err = ENOTSUP;
449 			break;
450 		}
451 	case MAC_PROP_EN_100FDX_CAP:
452 		if (hw->phy.media_type == ixgbe_media_type_copper &&
453 		    speeds & IXGBE_LINK_SPEED_100_FULL) {
454 			ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val;
455 			goto setup_link;
456 		} else {
457 			err = ENOTSUP;
458 			break;
459 		}
460 	case MAC_PROP_AUTONEG:
461 		if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
462 			err = ENOTSUP;
463 			break;
464 		} else {
465 			ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val;
466 			goto setup_link;
467 		}
468 	case MAC_PROP_FLOWCTRL:
469 		bcopy(pr_val, &flow_control, sizeof (flow_control));
470 
471 		switch (flow_control) {
472 		default:
473 			err = EINVAL;
474 			break;
475 		case LINK_FLOWCTRL_NONE:
476 			hw->fc.requested_mode = ixgbe_fc_none;
477 			break;
478 		case LINK_FLOWCTRL_RX:
479 			hw->fc.requested_mode = ixgbe_fc_rx_pause;
480 			break;
481 		case LINK_FLOWCTRL_TX:
482 			hw->fc.requested_mode = ixgbe_fc_tx_pause;
483 			break;
484 		case LINK_FLOWCTRL_BI:
485 			hw->fc.requested_mode = ixgbe_fc_full;
486 			break;
487 		}
488 setup_link:
489 		if (err == 0) {
490 			if (ixgbe_driver_setup_link(ixgbe, B_TRUE) !=
491 			    IXGBE_SUCCESS)
492 				err = EINVAL;
493 		}
494 		break;
495 	case MAC_PROP_ADV_10GFDX_CAP:
496 	case MAC_PROP_ADV_5000FDX_CAP:
497 	case MAC_PROP_ADV_2500FDX_CAP:
498 	case MAC_PROP_ADV_1000FDX_CAP:
499 	case MAC_PROP_ADV_100FDX_CAP:
500 	case MAC_PROP_STATUS:
501 	case MAC_PROP_SPEED:
502 	case MAC_PROP_DUPLEX:
503 	case MAC_PROP_MEDIA:
504 		err = ENOTSUP; /* read-only prop. Can't set this. */
505 		break;
506 	case MAC_PROP_MTU:
507 		cur_mtu = ixgbe->default_mtu;
508 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
509 		if (new_mtu == cur_mtu) {
510 			err = 0;
511 			break;
512 		}
513 
514 		if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) {
515 			err = EINVAL;
516 			break;
517 		}
518 
519 		if (ixgbe->ixgbe_state & IXGBE_STARTED) {
520 			err = EBUSY;
521 			break;
522 		}
523 
524 		err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu);
525 		if (err == 0) {
526 			ixgbe->default_mtu = new_mtu;
527 			ixgbe->max_frame_size = ixgbe->default_mtu +
528 			    sizeof (struct ether_vlan_header) + ETHERFCSL;
529 
530 			/*
531 			 * Set rx buffer size
532 			 */
533 			rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM;
534 			ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size &
535 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
536 
537 			/*
538 			 * Set tx buffer size
539 			 */
540 			tx_size = ixgbe->max_frame_size;
541 			ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size &
542 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
543 		}
544 		break;
545 	case MAC_PROP_PRIVATE:
546 		err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val);
547 		break;
548 	default:
549 		err = ENOTSUP;
550 		break;
551 	}
552 	mutex_exit(&ixgbe->gen_lock);
553 	return (err);
554 }
555 
556 int
557 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
558     uint_t pr_valsize, void *pr_val)
559 {
560 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
561 	struct ixgbe_hw *hw = &ixgbe->hw;
562 	int err = 0;
563 	uint32_t flow_control;
564 	uint64_t tmp = 0;
565 	ixgbe_link_speed speeds = 0;
566 
567 	/*
568 	 * We cannot always rely on the common code maintaining
569 	 * hw->phy.speeds_supported, therefore we fall back to use the recorded
570 	 * supported speeds which were obtained during instance init in
571 	 * ixgbe_init_params().
572 	 */
573 	speeds = hw->phy.speeds_supported;
574 	if (speeds == 0)
575 		speeds = ixgbe->speeds_supported;
576 
577 	switch (pr_num) {
578 	case MAC_PROP_DUPLEX:
579 		ASSERT(pr_valsize >= sizeof (link_duplex_t));
580 		bcopy(&ixgbe->link_duplex, pr_val,
581 		    sizeof (link_duplex_t));
582 		break;
583 	case MAC_PROP_SPEED:
584 		ASSERT(pr_valsize >= sizeof (uint64_t));
585 		tmp = ixgbe->link_speed * 1000000ull;
586 		bcopy(&tmp, pr_val, sizeof (tmp));
587 		break;
588 	case MAC_PROP_MEDIA:
589 		mutex_enter(&ixgbe->gen_lock);
590 		*(mac_ether_media_t *)pr_val = ixgbe_phy_to_media(ixgbe);
591 		mutex_exit(&ixgbe->gen_lock);
592 		break;
593 	case MAC_PROP_AUTONEG:
594 		*(uint8_t *)pr_val = ixgbe->param_adv_autoneg_cap;
595 		break;
596 	case MAC_PROP_FLOWCTRL:
597 		ASSERT(pr_valsize >= sizeof (uint32_t));
598 
599 		switch (hw->fc.requested_mode) {
600 			case ixgbe_fc_none:
601 				flow_control = LINK_FLOWCTRL_NONE;
602 				break;
603 			case ixgbe_fc_rx_pause:
604 				flow_control = LINK_FLOWCTRL_RX;
605 				break;
606 			case ixgbe_fc_tx_pause:
607 				flow_control = LINK_FLOWCTRL_TX;
608 				break;
609 			case ixgbe_fc_full:
610 				flow_control = LINK_FLOWCTRL_BI;
611 				break;
612 		}
613 		bcopy(&flow_control, pr_val, sizeof (flow_control));
614 		break;
615 	case MAC_PROP_ADV_10GFDX_CAP:
616 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
617 			*(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap;
618 		else
619 			err = ENOTSUP;
620 		break;
621 	case MAC_PROP_EN_10GFDX_CAP:
622 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
623 			*(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap;
624 		else
625 			err = ENOTSUP;
626 		break;
627 	case MAC_PROP_ADV_5000FDX_CAP:
628 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
629 			*(uint8_t *)pr_val = ixgbe->param_adv_5000fdx_cap;
630 		else
631 			err = ENOTSUP;
632 		break;
633 	case MAC_PROP_EN_5000FDX_CAP:
634 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
635 			*(uint8_t *)pr_val = ixgbe->param_en_5000fdx_cap;
636 		else
637 			err = ENOTSUP;
638 		break;
639 	case MAC_PROP_ADV_2500FDX_CAP:
640 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
641 			*(uint8_t *)pr_val = ixgbe->param_adv_2500fdx_cap;
642 		else
643 			err = ENOTSUP;
644 		break;
645 	case MAC_PROP_EN_2500FDX_CAP:
646 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
647 			*(uint8_t *)pr_val = ixgbe->param_en_2500fdx_cap;
648 		else
649 			err = ENOTSUP;
650 		break;
651 	case MAC_PROP_ADV_1000FDX_CAP:
652 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
653 			*(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap;
654 		else
655 			err = ENOTSUP;
656 		break;
657 	case MAC_PROP_EN_1000FDX_CAP:
658 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
659 			*(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap;
660 		else
661 			err = ENOTSUP;
662 		break;
663 	case MAC_PROP_ADV_100FDX_CAP:
664 		if (speeds & IXGBE_LINK_SPEED_100_FULL)
665 			*(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap;
666 		else
667 			err = ENOTSUP;
668 		break;
669 	case MAC_PROP_EN_100FDX_CAP:
670 		if (speeds & IXGBE_LINK_SPEED_100_FULL)
671 			*(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap;
672 		else
673 			err = ENOTSUP;
674 		break;
675 	case MAC_PROP_PRIVATE:
676 		err = ixgbe_get_priv_prop(ixgbe, pr_name,
677 		    pr_valsize, pr_val);
678 		break;
679 	default:
680 		err = ENOTSUP;
681 		break;
682 	}
683 	return (err);
684 }
685 
686 void
687 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
688     mac_prop_info_handle_t prh)
689 {
690 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
691 	struct ixgbe_hw *hw = &ixgbe->hw;
692 	uint_t perm;
693 	uint8_t value;
694 	ixgbe_link_speed speeds = 0;
695 
696 	/*
697 	 * We cannot always rely on the common code maintaining
698 	 * hw->phy.speeds_supported, therefore we fall back to use the
699 	 * recorded supported speeds which were obtained during instance init in
700 	 * ixgbe_init_params().
701 	 */
702 	speeds = hw->phy.speeds_supported;
703 	if (speeds == 0)
704 		speeds = ixgbe->speeds_supported;
705 
706 	switch (pr_num) {
707 	case MAC_PROP_DUPLEX:
708 	case MAC_PROP_SPEED:
709 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
710 		break;
711 
712 	case MAC_PROP_ADV_100FDX_CAP:
713 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
714 		value = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0;
715 		mac_prop_info_set_default_uint8(prh, value);
716 		break;
717 
718 	case MAC_PROP_ADV_1000FDX_CAP:
719 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
720 		value = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0;
721 		mac_prop_info_set_default_uint8(prh, value);
722 		break;
723 
724 	case MAC_PROP_ADV_2500FDX_CAP:
725 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
726 		value = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0;
727 		mac_prop_info_set_default_uint8(prh, value);
728 		break;
729 
730 	case MAC_PROP_ADV_5000FDX_CAP:
731 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
732 		value = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0;
733 		mac_prop_info_set_default_uint8(prh, value);
734 		break;
735 
736 	case MAC_PROP_ADV_10GFDX_CAP:
737 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
738 		value = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0;
739 		mac_prop_info_set_default_uint8(prh, value);
740 		break;
741 
742 	/*
743 	 * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
744 	 * read-only on non-baseT (SFP) PHYs.
745 	 */
746 	case MAC_PROP_AUTONEG:
747 		perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
748 		    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
749 		mac_prop_info_set_perm(prh, perm);
750 		mac_prop_info_set_default_uint8(prh, 1);
751 		break;
752 
753 	case MAC_PROP_EN_10GFDX_CAP:
754 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL) {
755 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
756 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
757 			mac_prop_info_set_perm(prh, perm);
758 			mac_prop_info_set_default_uint8(prh, 1);
759 		}
760 		break;
761 
762 	case MAC_PROP_EN_5000FDX_CAP:
763 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL) {
764 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
765 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
766 			mac_prop_info_set_perm(prh, perm);
767 			mac_prop_info_set_default_uint8(prh, 1);
768 		}
769 		break;
770 
771 	case MAC_PROP_EN_2500FDX_CAP:
772 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
773 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
774 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
775 			mac_prop_info_set_perm(prh, perm);
776 			mac_prop_info_set_default_uint8(prh, 1);
777 		}
778 		break;
779 
780 	case MAC_PROP_EN_1000FDX_CAP:
781 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL) {
782 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
783 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
784 			mac_prop_info_set_perm(prh, perm);
785 			mac_prop_info_set_default_uint8(prh, 1);
786 		}
787 		break;
788 
789 	case MAC_PROP_EN_100FDX_CAP:
790 		if (speeds & IXGBE_LINK_SPEED_100_FULL) {
791 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
792 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
793 			mac_prop_info_set_perm(prh, perm);
794 			mac_prop_info_set_default_uint8(prh, 1);
795 		}
796 		break;
797 
798 	case MAC_PROP_FLOWCTRL:
799 		mac_prop_info_set_default_link_flowctrl(prh,
800 		    LINK_FLOWCTRL_NONE);
801 		break;
802 
803 	case MAC_PROP_MTU:
804 		mac_prop_info_set_range_uint32(prh,
805 		    DEFAULT_MTU, ixgbe->capab->max_mtu);
806 		break;
807 
808 	case MAC_PROP_PRIVATE: {
809 		char valstr[64];
810 		int value;
811 
812 		bzero(valstr, sizeof (valstr));
813 
814 		if (strcmp(pr_name, "_adv_pause_cap") == 0 ||
815 		    strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
816 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
817 			return;
818 		}
819 
820 		if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
821 			value = DEFAULT_TX_COPY_THRESHOLD;
822 		} else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
823 			value = DEFAULT_TX_RECYCLE_THRESHOLD;
824 		} else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
825 			value = DEFAULT_TX_OVERLOAD_THRESHOLD;
826 		} else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
827 			value = DEFAULT_TX_RESCHED_THRESHOLD;
828 		} else if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
829 			value = DEFAULT_RX_COPY_THRESHOLD;
830 		} else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
831 			value = DEFAULT_RX_LIMIT_PER_INTR;
832 		} else if (strcmp(pr_name, "_intr_throttling") == 0) {
833 			value = ixgbe->capab->def_intr_throttle;
834 		} else {
835 			return;
836 		}
837 
838 		(void) snprintf(valstr, sizeof (valstr), "%x", value);
839 	}
840 	}
841 }
842 
843 boolean_t
844 ixgbe_param_locked(mac_prop_id_t pr_num)
845 {
846 	/*
847 	 * All en_* parameters are locked (read-only) while
848 	 * the device is in any sort of loopback mode ...
849 	 */
850 	switch (pr_num) {
851 		case MAC_PROP_EN_10GFDX_CAP:
852 		case MAC_PROP_EN_5000FDX_CAP:
853 		case MAC_PROP_EN_2500FDX_CAP:
854 		case MAC_PROP_EN_1000FDX_CAP:
855 		case MAC_PROP_EN_100FDX_CAP:
856 		case MAC_PROP_AUTONEG:
857 		case MAC_PROP_FLOWCTRL:
858 			return (B_TRUE);
859 	}
860 	return (B_FALSE);
861 }
862 
863 /* ARGSUSED */
864 int
865 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
866     uint_t pr_valsize, const void *pr_val)
867 {
868 	int err = 0;
869 	long result;
870 	struct ixgbe_hw *hw = &ixgbe->hw;
871 	int i;
872 
873 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
874 		if (pr_val == NULL) {
875 			err = EINVAL;
876 			return (err);
877 		}
878 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
879 		if (result < MIN_TX_COPY_THRESHOLD ||
880 		    result > MAX_TX_COPY_THRESHOLD)
881 			err = EINVAL;
882 		else {
883 			ixgbe->tx_copy_thresh = (uint32_t)result;
884 		}
885 		return (err);
886 	}
887 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
888 		if (pr_val == NULL) {
889 			err = EINVAL;
890 			return (err);
891 		}
892 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
893 		if (result < MIN_TX_RECYCLE_THRESHOLD ||
894 		    result > MAX_TX_RECYCLE_THRESHOLD)
895 			err = EINVAL;
896 		else {
897 			ixgbe->tx_recycle_thresh = (uint32_t)result;
898 		}
899 		return (err);
900 	}
901 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
902 		if (pr_val == NULL) {
903 			err = EINVAL;
904 			return (err);
905 		}
906 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
907 		if (result < MIN_TX_OVERLOAD_THRESHOLD ||
908 		    result > MAX_TX_OVERLOAD_THRESHOLD)
909 			err = EINVAL;
910 		else {
911 			ixgbe->tx_overload_thresh = (uint32_t)result;
912 		}
913 		return (err);
914 	}
915 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
916 		if (pr_val == NULL) {
917 			err = EINVAL;
918 			return (err);
919 		}
920 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
921 		if (result < MIN_TX_RESCHED_THRESHOLD ||
922 		    result > MAX_TX_RESCHED_THRESHOLD)
923 			err = EINVAL;
924 		else {
925 			ixgbe->tx_resched_thresh = (uint32_t)result;
926 		}
927 		return (err);
928 	}
929 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
930 		if (pr_val == NULL) {
931 			err = EINVAL;
932 			return (err);
933 		}
934 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
935 		if (result < MIN_RX_COPY_THRESHOLD ||
936 		    result > MAX_RX_COPY_THRESHOLD)
937 			err = EINVAL;
938 		else {
939 			ixgbe->rx_copy_thresh = (uint32_t)result;
940 		}
941 		return (err);
942 	}
943 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
944 		if (pr_val == NULL) {
945 			err = EINVAL;
946 			return (err);
947 		}
948 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
949 		if (result < MIN_RX_LIMIT_PER_INTR ||
950 		    result > MAX_RX_LIMIT_PER_INTR)
951 			err = EINVAL;
952 		else {
953 			ixgbe->rx_limit_per_intr = (uint32_t)result;
954 		}
955 		return (err);
956 	}
957 	if (strcmp(pr_name, "_intr_throttling") == 0) {
958 		if (pr_val == NULL) {
959 			err = EINVAL;
960 			return (err);
961 		}
962 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
963 
964 		if (result < ixgbe->capab->min_intr_throttle ||
965 		    result > ixgbe->capab->max_intr_throttle)
966 			err = EINVAL;
967 		else {
968 			ixgbe->intr_throttling[0] = (uint32_t)result;
969 
970 			/*
971 			 * 82599, X540 and X550 require the interrupt throttling
972 			 * rate is a multiple of 8. This is enforced by the
973 			 * register definiton.
974 			 */
975 			if (hw->mac.type == ixgbe_mac_82599EB ||
976 			    hw->mac.type == ixgbe_mac_X540 ||
977 			    hw->mac.type == ixgbe_mac_X550 ||
978 			    hw->mac.type == ixgbe_mac_X550EM_x) {
979 				ixgbe->intr_throttling[0] =
980 				    ixgbe->intr_throttling[0] & 0xFF8;
981 			}
982 
983 			for (i = 0; i < MAX_INTR_VECTOR; i++)
984 				ixgbe->intr_throttling[i] =
985 				    ixgbe->intr_throttling[0];
986 
987 			/* Set interrupt throttling rate */
988 			for (i = 0; i < ixgbe->intr_cnt; i++)
989 				IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
990 				    ixgbe->intr_throttling[i]);
991 		}
992 		return (err);
993 	}
994 	return (ENOTSUP);
995 }
996 
997 int
998 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
999     uint_t pr_valsize, void *pr_val)
1000 {
1001 	int err = ENOTSUP;
1002 	int value;
1003 
1004 	if (strcmp(pr_name, "_adv_pause_cap") == 0) {
1005 		value = ixgbe->param_adv_pause_cap;
1006 		err = 0;
1007 		goto done;
1008 	}
1009 	if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1010 		value = ixgbe->param_adv_asym_pause_cap;
1011 		err = 0;
1012 		goto done;
1013 	}
1014 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1015 		value = ixgbe->tx_copy_thresh;
1016 		err = 0;
1017 		goto done;
1018 	}
1019 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1020 		value = ixgbe->tx_recycle_thresh;
1021 		err = 0;
1022 		goto done;
1023 	}
1024 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1025 		value = ixgbe->tx_overload_thresh;
1026 		err = 0;
1027 		goto done;
1028 	}
1029 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1030 		value = ixgbe->tx_resched_thresh;
1031 		err = 0;
1032 		goto done;
1033 	}
1034 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1035 		value = ixgbe->rx_copy_thresh;
1036 		err = 0;
1037 		goto done;
1038 	}
1039 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1040 		value = ixgbe->rx_limit_per_intr;
1041 		err = 0;
1042 		goto done;
1043 	}
1044 	if (strcmp(pr_name, "_intr_throttling") == 0) {
1045 		value = ixgbe->intr_throttling[0];
1046 		err = 0;
1047 		goto done;
1048 	}
1049 done:
1050 	if (err == 0) {
1051 		(void) snprintf(pr_val, pr_valsize, "%d", value);
1052 	}
1053 	return (err);
1054 }
1055