xref: /illumos-gate/usr/src/uts/common/io/ixgbe/ixgbe_gld.c (revision a92282e44f968185a6bba094d1e5fece2da819cf)
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 		err = ENOTSUP; /* read-only prop. Can't set this. */
504 		break;
505 	case MAC_PROP_MTU:
506 		cur_mtu = ixgbe->default_mtu;
507 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
508 		if (new_mtu == cur_mtu) {
509 			err = 0;
510 			break;
511 		}
512 
513 		if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) {
514 			err = EINVAL;
515 			break;
516 		}
517 
518 		if (ixgbe->ixgbe_state & IXGBE_STARTED) {
519 			err = EBUSY;
520 			break;
521 		}
522 
523 		err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu);
524 		if (err == 0) {
525 			ixgbe->default_mtu = new_mtu;
526 			ixgbe->max_frame_size = ixgbe->default_mtu +
527 			    sizeof (struct ether_vlan_header) + ETHERFCSL;
528 
529 			/*
530 			 * Set rx buffer size
531 			 */
532 			rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM;
533 			ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size &
534 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
535 
536 			/*
537 			 * Set tx buffer size
538 			 */
539 			tx_size = ixgbe->max_frame_size;
540 			ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size &
541 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
542 		}
543 		break;
544 	case MAC_PROP_PRIVATE:
545 		err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val);
546 		break;
547 	default:
548 		err = ENOTSUP;
549 		break;
550 	}
551 	mutex_exit(&ixgbe->gen_lock);
552 	return (err);
553 }
554 
555 int
556 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
557     uint_t pr_valsize, void *pr_val)
558 {
559 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
560 	struct ixgbe_hw *hw = &ixgbe->hw;
561 	int err = 0;
562 	uint32_t flow_control;
563 	uint64_t tmp = 0;
564 	ixgbe_link_speed speeds = 0;
565 
566 	/*
567 	 * We cannot always rely on the common code maintaining
568 	 * hw->phy.speeds_supported, therefore we fall back to use the recorded
569 	 * supported speeds which were obtained during instance init in
570 	 * ixgbe_init_params().
571 	 */
572 	speeds = hw->phy.speeds_supported;
573 	if (speeds == 0)
574 		speeds = ixgbe->speeds_supported;
575 
576 	switch (pr_num) {
577 	case MAC_PROP_DUPLEX:
578 		ASSERT(pr_valsize >= sizeof (link_duplex_t));
579 		bcopy(&ixgbe->link_duplex, pr_val,
580 		    sizeof (link_duplex_t));
581 		break;
582 	case MAC_PROP_SPEED:
583 		ASSERT(pr_valsize >= sizeof (uint64_t));
584 		tmp = ixgbe->link_speed * 1000000ull;
585 		bcopy(&tmp, pr_val, sizeof (tmp));
586 		break;
587 	case MAC_PROP_AUTONEG:
588 		*(uint8_t *)pr_val = ixgbe->param_adv_autoneg_cap;
589 		break;
590 	case MAC_PROP_FLOWCTRL:
591 		ASSERT(pr_valsize >= sizeof (uint32_t));
592 
593 		switch (hw->fc.requested_mode) {
594 			case ixgbe_fc_none:
595 				flow_control = LINK_FLOWCTRL_NONE;
596 				break;
597 			case ixgbe_fc_rx_pause:
598 				flow_control = LINK_FLOWCTRL_RX;
599 				break;
600 			case ixgbe_fc_tx_pause:
601 				flow_control = LINK_FLOWCTRL_TX;
602 				break;
603 			case ixgbe_fc_full:
604 				flow_control = LINK_FLOWCTRL_BI;
605 				break;
606 		}
607 		bcopy(&flow_control, pr_val, sizeof (flow_control));
608 		break;
609 	case MAC_PROP_ADV_10GFDX_CAP:
610 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
611 			*(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap;
612 		else
613 			err = ENOTSUP;
614 		break;
615 	case MAC_PROP_EN_10GFDX_CAP:
616 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
617 			*(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap;
618 		else
619 			err = ENOTSUP;
620 		break;
621 	case MAC_PROP_ADV_5000FDX_CAP:
622 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
623 			*(uint8_t *)pr_val = ixgbe->param_adv_5000fdx_cap;
624 		else
625 			err = ENOTSUP;
626 		break;
627 	case MAC_PROP_EN_5000FDX_CAP:
628 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
629 			*(uint8_t *)pr_val = ixgbe->param_en_5000fdx_cap;
630 		else
631 			err = ENOTSUP;
632 		break;
633 	case MAC_PROP_ADV_2500FDX_CAP:
634 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
635 			*(uint8_t *)pr_val = ixgbe->param_adv_2500fdx_cap;
636 		else
637 			err = ENOTSUP;
638 		break;
639 	case MAC_PROP_EN_2500FDX_CAP:
640 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
641 			*(uint8_t *)pr_val = ixgbe->param_en_2500fdx_cap;
642 		else
643 			err = ENOTSUP;
644 		break;
645 	case MAC_PROP_ADV_1000FDX_CAP:
646 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
647 			*(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap;
648 		else
649 			err = ENOTSUP;
650 		break;
651 	case MAC_PROP_EN_1000FDX_CAP:
652 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
653 			*(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap;
654 		else
655 			err = ENOTSUP;
656 		break;
657 	case MAC_PROP_ADV_100FDX_CAP:
658 		if (speeds & IXGBE_LINK_SPEED_100_FULL)
659 			*(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap;
660 		else
661 			err = ENOTSUP;
662 		break;
663 	case MAC_PROP_EN_100FDX_CAP:
664 		if (speeds & IXGBE_LINK_SPEED_100_FULL)
665 			*(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap;
666 		else
667 			err = ENOTSUP;
668 		break;
669 	case MAC_PROP_PRIVATE:
670 		err = ixgbe_get_priv_prop(ixgbe, pr_name,
671 		    pr_valsize, pr_val);
672 		break;
673 	default:
674 		err = ENOTSUP;
675 		break;
676 	}
677 	return (err);
678 }
679 
680 void
681 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
682     mac_prop_info_handle_t prh)
683 {
684 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
685 	struct ixgbe_hw *hw = &ixgbe->hw;
686 	uint_t perm;
687 	uint8_t value;
688 	ixgbe_link_speed speeds = 0;
689 
690 	/*
691 	 * We cannot always rely on the common code maintaining
692 	 * hw->phy.speeds_supported, therefore we fall back to use the
693 	 * recorded supported speeds which were obtained during instance init in
694 	 * ixgbe_init_params().
695 	 */
696 	speeds = hw->phy.speeds_supported;
697 	if (speeds == 0)
698 		speeds = ixgbe->speeds_supported;
699 
700 	switch (pr_num) {
701 	case MAC_PROP_DUPLEX:
702 	case MAC_PROP_SPEED:
703 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
704 		break;
705 
706 	case MAC_PROP_ADV_100FDX_CAP:
707 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
708 		value = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0;
709 		mac_prop_info_set_default_uint8(prh, value);
710 		break;
711 
712 	case MAC_PROP_ADV_1000FDX_CAP:
713 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
714 		value = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0;
715 		mac_prop_info_set_default_uint8(prh, value);
716 		break;
717 
718 	case MAC_PROP_ADV_2500FDX_CAP:
719 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
720 		value = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0;
721 		mac_prop_info_set_default_uint8(prh, value);
722 		break;
723 
724 	case MAC_PROP_ADV_5000FDX_CAP:
725 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
726 		value = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0;
727 		mac_prop_info_set_default_uint8(prh, value);
728 		break;
729 
730 	case MAC_PROP_ADV_10GFDX_CAP:
731 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
732 		value = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0;
733 		mac_prop_info_set_default_uint8(prh, value);
734 		break;
735 
736 	/*
737 	 * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
738 	 * read-only on non-baseT (SFP) PHYs.
739 	 */
740 	case MAC_PROP_AUTONEG:
741 		perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
742 		    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
743 		mac_prop_info_set_perm(prh, perm);
744 		mac_prop_info_set_default_uint8(prh, 1);
745 		break;
746 
747 	case MAC_PROP_EN_10GFDX_CAP:
748 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL) {
749 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
750 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
751 			mac_prop_info_set_perm(prh, perm);
752 			mac_prop_info_set_default_uint8(prh, 1);
753 		}
754 		break;
755 
756 	case MAC_PROP_EN_5000FDX_CAP:
757 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL) {
758 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
759 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
760 			mac_prop_info_set_perm(prh, perm);
761 			mac_prop_info_set_default_uint8(prh, 1);
762 		}
763 		break;
764 
765 	case MAC_PROP_EN_2500FDX_CAP:
766 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
767 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
768 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
769 			mac_prop_info_set_perm(prh, perm);
770 			mac_prop_info_set_default_uint8(prh, 1);
771 		}
772 		break;
773 
774 	case MAC_PROP_EN_1000FDX_CAP:
775 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL) {
776 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
777 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
778 			mac_prop_info_set_perm(prh, perm);
779 			mac_prop_info_set_default_uint8(prh, 1);
780 		}
781 		break;
782 
783 	case MAC_PROP_EN_100FDX_CAP:
784 		if (speeds & IXGBE_LINK_SPEED_100_FULL) {
785 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
786 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
787 			mac_prop_info_set_perm(prh, perm);
788 			mac_prop_info_set_default_uint8(prh, 1);
789 		}
790 		break;
791 
792 	case MAC_PROP_FLOWCTRL:
793 		mac_prop_info_set_default_link_flowctrl(prh,
794 		    LINK_FLOWCTRL_NONE);
795 		break;
796 
797 	case MAC_PROP_MTU:
798 		mac_prop_info_set_range_uint32(prh,
799 		    DEFAULT_MTU, ixgbe->capab->max_mtu);
800 		break;
801 
802 	case MAC_PROP_PRIVATE: {
803 		char valstr[64];
804 		int value;
805 
806 		bzero(valstr, sizeof (valstr));
807 
808 		if (strcmp(pr_name, "_adv_pause_cap") == 0 ||
809 		    strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
810 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
811 			return;
812 		}
813 
814 		if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
815 			value = DEFAULT_TX_COPY_THRESHOLD;
816 		} else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
817 			value = DEFAULT_TX_RECYCLE_THRESHOLD;
818 		} else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
819 			value = DEFAULT_TX_OVERLOAD_THRESHOLD;
820 		} else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
821 			value = DEFAULT_TX_RESCHED_THRESHOLD;
822 		} else if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
823 			value = DEFAULT_RX_COPY_THRESHOLD;
824 		} else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
825 			value = DEFAULT_RX_LIMIT_PER_INTR;
826 		} else if (strcmp(pr_name, "_intr_throttling") == 0) {
827 			value = ixgbe->capab->def_intr_throttle;
828 		} else {
829 			return;
830 		}
831 
832 		(void) snprintf(valstr, sizeof (valstr), "%x", value);
833 	}
834 	}
835 }
836 
837 boolean_t
838 ixgbe_param_locked(mac_prop_id_t pr_num)
839 {
840 	/*
841 	 * All en_* parameters are locked (read-only) while
842 	 * the device is in any sort of loopback mode ...
843 	 */
844 	switch (pr_num) {
845 		case MAC_PROP_EN_10GFDX_CAP:
846 		case MAC_PROP_EN_5000FDX_CAP:
847 		case MAC_PROP_EN_2500FDX_CAP:
848 		case MAC_PROP_EN_1000FDX_CAP:
849 		case MAC_PROP_EN_100FDX_CAP:
850 		case MAC_PROP_AUTONEG:
851 		case MAC_PROP_FLOWCTRL:
852 			return (B_TRUE);
853 	}
854 	return (B_FALSE);
855 }
856 
857 /* ARGSUSED */
858 int
859 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
860     uint_t pr_valsize, const void *pr_val)
861 {
862 	int err = 0;
863 	long result;
864 	struct ixgbe_hw *hw = &ixgbe->hw;
865 	int i;
866 
867 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
868 		if (pr_val == NULL) {
869 			err = EINVAL;
870 			return (err);
871 		}
872 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
873 		if (result < MIN_TX_COPY_THRESHOLD ||
874 		    result > MAX_TX_COPY_THRESHOLD)
875 			err = EINVAL;
876 		else {
877 			ixgbe->tx_copy_thresh = (uint32_t)result;
878 		}
879 		return (err);
880 	}
881 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
882 		if (pr_val == NULL) {
883 			err = EINVAL;
884 			return (err);
885 		}
886 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
887 		if (result < MIN_TX_RECYCLE_THRESHOLD ||
888 		    result > MAX_TX_RECYCLE_THRESHOLD)
889 			err = EINVAL;
890 		else {
891 			ixgbe->tx_recycle_thresh = (uint32_t)result;
892 		}
893 		return (err);
894 	}
895 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
896 		if (pr_val == NULL) {
897 			err = EINVAL;
898 			return (err);
899 		}
900 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
901 		if (result < MIN_TX_OVERLOAD_THRESHOLD ||
902 		    result > MAX_TX_OVERLOAD_THRESHOLD)
903 			err = EINVAL;
904 		else {
905 			ixgbe->tx_overload_thresh = (uint32_t)result;
906 		}
907 		return (err);
908 	}
909 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
910 		if (pr_val == NULL) {
911 			err = EINVAL;
912 			return (err);
913 		}
914 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
915 		if (result < MIN_TX_RESCHED_THRESHOLD ||
916 		    result > MAX_TX_RESCHED_THRESHOLD)
917 			err = EINVAL;
918 		else {
919 			ixgbe->tx_resched_thresh = (uint32_t)result;
920 		}
921 		return (err);
922 	}
923 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
924 		if (pr_val == NULL) {
925 			err = EINVAL;
926 			return (err);
927 		}
928 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
929 		if (result < MIN_RX_COPY_THRESHOLD ||
930 		    result > MAX_RX_COPY_THRESHOLD)
931 			err = EINVAL;
932 		else {
933 			ixgbe->rx_copy_thresh = (uint32_t)result;
934 		}
935 		return (err);
936 	}
937 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
938 		if (pr_val == NULL) {
939 			err = EINVAL;
940 			return (err);
941 		}
942 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
943 		if (result < MIN_RX_LIMIT_PER_INTR ||
944 		    result > MAX_RX_LIMIT_PER_INTR)
945 			err = EINVAL;
946 		else {
947 			ixgbe->rx_limit_per_intr = (uint32_t)result;
948 		}
949 		return (err);
950 	}
951 	if (strcmp(pr_name, "_intr_throttling") == 0) {
952 		if (pr_val == NULL) {
953 			err = EINVAL;
954 			return (err);
955 		}
956 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
957 
958 		if (result < ixgbe->capab->min_intr_throttle ||
959 		    result > ixgbe->capab->max_intr_throttle)
960 			err = EINVAL;
961 		else {
962 			ixgbe->intr_throttling[0] = (uint32_t)result;
963 
964 			/*
965 			 * 82599, X540 and X550 require the interrupt throttling
966 			 * rate is a multiple of 8. This is enforced by the
967 			 * register definiton.
968 			 */
969 			if (hw->mac.type == ixgbe_mac_82599EB ||
970 			    hw->mac.type == ixgbe_mac_X540 ||
971 			    hw->mac.type == ixgbe_mac_X550 ||
972 			    hw->mac.type == ixgbe_mac_X550EM_x) {
973 				ixgbe->intr_throttling[0] =
974 				    ixgbe->intr_throttling[0] & 0xFF8;
975 			}
976 
977 			for (i = 0; i < MAX_INTR_VECTOR; i++)
978 				ixgbe->intr_throttling[i] =
979 				    ixgbe->intr_throttling[0];
980 
981 			/* Set interrupt throttling rate */
982 			for (i = 0; i < ixgbe->intr_cnt; i++)
983 				IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
984 				    ixgbe->intr_throttling[i]);
985 		}
986 		return (err);
987 	}
988 	return (ENOTSUP);
989 }
990 
991 int
992 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
993     uint_t pr_valsize, void *pr_val)
994 {
995 	int err = ENOTSUP;
996 	int value;
997 
998 	if (strcmp(pr_name, "_adv_pause_cap") == 0) {
999 		value = ixgbe->param_adv_pause_cap;
1000 		err = 0;
1001 		goto done;
1002 	}
1003 	if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1004 		value = ixgbe->param_adv_asym_pause_cap;
1005 		err = 0;
1006 		goto done;
1007 	}
1008 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1009 		value = ixgbe->tx_copy_thresh;
1010 		err = 0;
1011 		goto done;
1012 	}
1013 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1014 		value = ixgbe->tx_recycle_thresh;
1015 		err = 0;
1016 		goto done;
1017 	}
1018 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1019 		value = ixgbe->tx_overload_thresh;
1020 		err = 0;
1021 		goto done;
1022 	}
1023 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1024 		value = ixgbe->tx_resched_thresh;
1025 		err = 0;
1026 		goto done;
1027 	}
1028 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1029 		value = ixgbe->rx_copy_thresh;
1030 		err = 0;
1031 		goto done;
1032 	}
1033 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1034 		value = ixgbe->rx_limit_per_intr;
1035 		err = 0;
1036 		goto done;
1037 	}
1038 	if (strcmp(pr_name, "_intr_throttling") == 0) {
1039 		value = ixgbe->intr_throttling[0];
1040 		err = 0;
1041 		goto done;
1042 	}
1043 done:
1044 	if (err == 0) {
1045 		(void) snprintf(pr_val, pr_valsize, "%d", value);
1046 	}
1047 	return (err);
1048 }
1049