xref: /illumos-gate/usr/src/uts/common/io/ixgbe/ixgbe_gld.c (revision 142d813a06c6f9a6142e2c276b62129a17a31a65)
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 			cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN;
309 			break;
310 		} else {
311 			return (B_FALSE);
312 		}
313 	}
314 	case MAC_CAPAB_RINGS: {
315 		mac_capab_rings_t *cap_rings = cap_data;
316 
317 		switch (cap_rings->mr_type) {
318 		case MAC_RING_TYPE_RX:
319 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
320 			cap_rings->mr_rnum = ixgbe->num_rx_rings;
321 			cap_rings->mr_gnum = ixgbe->num_rx_groups;
322 			cap_rings->mr_rget = ixgbe_fill_ring;
323 			cap_rings->mr_gget = ixgbe_fill_group;
324 			cap_rings->mr_gaddring = NULL;
325 			cap_rings->mr_gremring = NULL;
326 			break;
327 		case MAC_RING_TYPE_TX:
328 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
329 			cap_rings->mr_rnum = ixgbe->num_tx_rings;
330 			cap_rings->mr_gnum = 0;
331 			cap_rings->mr_rget = ixgbe_fill_ring;
332 			cap_rings->mr_gget = NULL;
333 			break;
334 		default:
335 			break;
336 		}
337 		break;
338 	}
339 	case MAC_CAPAB_TRANSCEIVER: {
340 		mac_capab_transceiver_t *mct = cap_data;
341 
342 		/*
343 		 * Rather than try and guess based on the media type whether or
344 		 * not we have a transceiver we can read, we instead will let
345 		 * the actual function calls figure that out for us.
346 		 */
347 		mct->mct_flags = 0;
348 		mct->mct_ntransceivers = 1;
349 		mct->mct_info = ixgbe_transceiver_info;
350 		mct->mct_read = ixgbe_transceiver_read;
351 		return (B_TRUE);
352 	}
353 	case MAC_CAPAB_LED: {
354 		mac_capab_led_t *mcl = cap_data;
355 
356 		mcl->mcl_flags = 0;
357 		mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_ON | MAC_LED_OFF |
358 		    MAC_LED_IDENT;
359 		mcl->mcl_set = ixgbe_led_set;
360 		break;
361 
362 	}
363 	default:
364 		return (B_FALSE);
365 	}
366 	return (B_TRUE);
367 }
368 
369 int
370 ixgbe_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
371     uint_t pr_valsize, const void *pr_val)
372 {
373 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
374 	struct ixgbe_hw *hw = &ixgbe->hw;
375 	int err = 0;
376 	uint32_t flow_control;
377 	uint32_t cur_mtu, new_mtu;
378 	uint32_t rx_size;
379 	uint32_t tx_size;
380 	ixgbe_link_speed speeds = 0;
381 
382 	mutex_enter(&ixgbe->gen_lock);
383 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
384 		mutex_exit(&ixgbe->gen_lock);
385 		return (ECANCELED);
386 	}
387 
388 	/*
389 	 * We cannot always rely on the common code maintaining
390 	 * hw->phy.speeds_supported, therefore we fall back to use the recorded
391 	 * supported speeds which were obtained during instance init in
392 	 * ixgbe_init_params().
393 	 */
394 	speeds = hw->phy.speeds_supported;
395 	if (speeds == 0)
396 		speeds = ixgbe->speeds_supported;
397 
398 	if (ixgbe->loopback_mode != IXGBE_LB_NONE &&
399 	    ixgbe_param_locked(pr_num)) {
400 		/*
401 		 * All en_* parameters are locked (read-only)
402 		 * while the device is in any sort of loopback mode.
403 		 */
404 		mutex_exit(&ixgbe->gen_lock);
405 		return (EBUSY);
406 	}
407 
408 	/*
409 	 * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
410 	 * read-only on non-baseT PHYs.
411 	 */
412 	switch (pr_num) {
413 	case MAC_PROP_EN_10GFDX_CAP:
414 		if (hw->phy.media_type == ixgbe_media_type_copper &&
415 		    speeds & IXGBE_LINK_SPEED_10GB_FULL) {
416 			ixgbe->param_en_10000fdx_cap = *(uint8_t *)pr_val;
417 			goto setup_link;
418 		} else {
419 			err = ENOTSUP;
420 			break;
421 		}
422 	case MAC_PROP_EN_5000FDX_CAP:
423 		if (hw->phy.media_type == ixgbe_media_type_copper &&
424 		    speeds & IXGBE_LINK_SPEED_5GB_FULL) {
425 			ixgbe->param_en_5000fdx_cap = *(uint8_t *)pr_val;
426 			goto setup_link;
427 		} else {
428 			err = ENOTSUP;
429 			break;
430 		}
431 	case MAC_PROP_EN_2500FDX_CAP:
432 		if (hw->phy.media_type == ixgbe_media_type_copper &&
433 		    speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
434 			ixgbe->param_en_2500fdx_cap = *(uint8_t *)pr_val;
435 			goto setup_link;
436 		} else {
437 			err = ENOTSUP;
438 			break;
439 		}
440 	case MAC_PROP_EN_1000FDX_CAP:
441 		if (hw->phy.media_type == ixgbe_media_type_copper &&
442 		    speeds & IXGBE_LINK_SPEED_1GB_FULL) {
443 			ixgbe->param_en_1000fdx_cap = *(uint8_t *)pr_val;
444 			goto setup_link;
445 		} else {
446 			err = ENOTSUP;
447 			break;
448 		}
449 	case MAC_PROP_EN_100FDX_CAP:
450 		if (hw->phy.media_type == ixgbe_media_type_copper &&
451 		    speeds & IXGBE_LINK_SPEED_100_FULL) {
452 			ixgbe->param_en_100fdx_cap = *(uint8_t *)pr_val;
453 			goto setup_link;
454 		} else {
455 			err = ENOTSUP;
456 			break;
457 		}
458 	case MAC_PROP_AUTONEG:
459 		if (ixgbe->hw.phy.media_type != ixgbe_media_type_copper) {
460 			err = ENOTSUP;
461 			break;
462 		} else {
463 			ixgbe->param_adv_autoneg_cap = *(uint8_t *)pr_val;
464 			goto setup_link;
465 		}
466 	case MAC_PROP_FLOWCTRL:
467 		bcopy(pr_val, &flow_control, sizeof (flow_control));
468 
469 		switch (flow_control) {
470 		default:
471 			err = EINVAL;
472 			break;
473 		case LINK_FLOWCTRL_NONE:
474 			hw->fc.requested_mode = ixgbe_fc_none;
475 			break;
476 		case LINK_FLOWCTRL_RX:
477 			hw->fc.requested_mode = ixgbe_fc_rx_pause;
478 			break;
479 		case LINK_FLOWCTRL_TX:
480 			hw->fc.requested_mode = ixgbe_fc_tx_pause;
481 			break;
482 		case LINK_FLOWCTRL_BI:
483 			hw->fc.requested_mode = ixgbe_fc_full;
484 			break;
485 		}
486 setup_link:
487 		if (err == 0) {
488 			if (ixgbe_driver_setup_link(ixgbe, B_TRUE) !=
489 			    IXGBE_SUCCESS)
490 				err = EINVAL;
491 		}
492 		break;
493 	case MAC_PROP_ADV_10GFDX_CAP:
494 	case MAC_PROP_ADV_5000FDX_CAP:
495 	case MAC_PROP_ADV_2500FDX_CAP:
496 	case MAC_PROP_ADV_1000FDX_CAP:
497 	case MAC_PROP_ADV_100FDX_CAP:
498 	case MAC_PROP_STATUS:
499 	case MAC_PROP_SPEED:
500 	case MAC_PROP_DUPLEX:
501 		err = ENOTSUP; /* read-only prop. Can't set this. */
502 		break;
503 	case MAC_PROP_MTU:
504 		cur_mtu = ixgbe->default_mtu;
505 		bcopy(pr_val, &new_mtu, sizeof (new_mtu));
506 		if (new_mtu == cur_mtu) {
507 			err = 0;
508 			break;
509 		}
510 
511 		if (new_mtu < DEFAULT_MTU || new_mtu > ixgbe->capab->max_mtu) {
512 			err = EINVAL;
513 			break;
514 		}
515 
516 		if (ixgbe->ixgbe_state & IXGBE_STARTED) {
517 			err = EBUSY;
518 			break;
519 		}
520 
521 		err = mac_maxsdu_update(ixgbe->mac_hdl, new_mtu);
522 		if (err == 0) {
523 			ixgbe->default_mtu = new_mtu;
524 			ixgbe->max_frame_size = ixgbe->default_mtu +
525 			    sizeof (struct ether_vlan_header) + ETHERFCSL;
526 
527 			/*
528 			 * Set rx buffer size
529 			 */
530 			rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM;
531 			ixgbe->rx_buf_size = ((rx_size >> 10) + ((rx_size &
532 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
533 
534 			/*
535 			 * Set tx buffer size
536 			 */
537 			tx_size = ixgbe->max_frame_size;
538 			ixgbe->tx_buf_size = ((tx_size >> 10) + ((tx_size &
539 			    (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
540 		}
541 		break;
542 	case MAC_PROP_PRIVATE:
543 		err = ixgbe_set_priv_prop(ixgbe, pr_name, pr_valsize, pr_val);
544 		break;
545 	default:
546 		err = ENOTSUP;
547 		break;
548 	}
549 	mutex_exit(&ixgbe->gen_lock);
550 	return (err);
551 }
552 
553 int
554 ixgbe_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
555     uint_t pr_valsize, void *pr_val)
556 {
557 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
558 	struct ixgbe_hw *hw = &ixgbe->hw;
559 	int err = 0;
560 	uint32_t flow_control;
561 	uint64_t tmp = 0;
562 	ixgbe_link_speed speeds = 0;
563 
564 	/*
565 	 * We cannot always rely on the common code maintaining
566 	 * hw->phy.speeds_supported, therefore we fall back to use the recorded
567 	 * supported speeds which were obtained during instance init in
568 	 * ixgbe_init_params().
569 	 */
570 	speeds = hw->phy.speeds_supported;
571 	if (speeds == 0)
572 		speeds = ixgbe->speeds_supported;
573 
574 	switch (pr_num) {
575 	case MAC_PROP_DUPLEX:
576 		ASSERT(pr_valsize >= sizeof (link_duplex_t));
577 		bcopy(&ixgbe->link_duplex, pr_val,
578 		    sizeof (link_duplex_t));
579 		break;
580 	case MAC_PROP_SPEED:
581 		ASSERT(pr_valsize >= sizeof (uint64_t));
582 		tmp = ixgbe->link_speed * 1000000ull;
583 		bcopy(&tmp, pr_val, sizeof (tmp));
584 		break;
585 	case MAC_PROP_AUTONEG:
586 		*(uint8_t *)pr_val = ixgbe->param_adv_autoneg_cap;
587 		break;
588 	case MAC_PROP_FLOWCTRL:
589 		ASSERT(pr_valsize >= sizeof (uint32_t));
590 
591 		switch (hw->fc.requested_mode) {
592 			case ixgbe_fc_none:
593 				flow_control = LINK_FLOWCTRL_NONE;
594 				break;
595 			case ixgbe_fc_rx_pause:
596 				flow_control = LINK_FLOWCTRL_RX;
597 				break;
598 			case ixgbe_fc_tx_pause:
599 				flow_control = LINK_FLOWCTRL_TX;
600 				break;
601 			case ixgbe_fc_full:
602 				flow_control = LINK_FLOWCTRL_BI;
603 				break;
604 		}
605 		bcopy(&flow_control, pr_val, sizeof (flow_control));
606 		break;
607 	case MAC_PROP_ADV_10GFDX_CAP:
608 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
609 			*(uint8_t *)pr_val = ixgbe->param_adv_10000fdx_cap;
610 		else
611 			err = ENOTSUP;
612 		break;
613 	case MAC_PROP_EN_10GFDX_CAP:
614 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL)
615 			*(uint8_t *)pr_val = ixgbe->param_en_10000fdx_cap;
616 		else
617 			err = ENOTSUP;
618 		break;
619 	case MAC_PROP_ADV_5000FDX_CAP:
620 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
621 			*(uint8_t *)pr_val = ixgbe->param_adv_5000fdx_cap;
622 		else
623 			err = ENOTSUP;
624 		break;
625 	case MAC_PROP_EN_5000FDX_CAP:
626 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL)
627 			*(uint8_t *)pr_val = ixgbe->param_en_5000fdx_cap;
628 		else
629 			err = ENOTSUP;
630 		break;
631 	case MAC_PROP_ADV_2500FDX_CAP:
632 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
633 			*(uint8_t *)pr_val = ixgbe->param_adv_2500fdx_cap;
634 		else
635 			err = ENOTSUP;
636 		break;
637 	case MAC_PROP_EN_2500FDX_CAP:
638 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL)
639 			*(uint8_t *)pr_val = ixgbe->param_en_2500fdx_cap;
640 		else
641 			err = ENOTSUP;
642 		break;
643 	case MAC_PROP_ADV_1000FDX_CAP:
644 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
645 			*(uint8_t *)pr_val = ixgbe->param_adv_1000fdx_cap;
646 		else
647 			err = ENOTSUP;
648 		break;
649 	case MAC_PROP_EN_1000FDX_CAP:
650 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL)
651 			*(uint8_t *)pr_val = ixgbe->param_en_1000fdx_cap;
652 		else
653 			err = ENOTSUP;
654 		break;
655 	case MAC_PROP_ADV_100FDX_CAP:
656 		if (speeds & IXGBE_LINK_SPEED_100_FULL)
657 			*(uint8_t *)pr_val = ixgbe->param_adv_100fdx_cap;
658 		else
659 			err = ENOTSUP;
660 		break;
661 	case MAC_PROP_EN_100FDX_CAP:
662 		if (speeds & IXGBE_LINK_SPEED_100_FULL)
663 			*(uint8_t *)pr_val = ixgbe->param_en_100fdx_cap;
664 		else
665 			err = ENOTSUP;
666 		break;
667 	case MAC_PROP_PRIVATE:
668 		err = ixgbe_get_priv_prop(ixgbe, pr_name,
669 		    pr_valsize, pr_val);
670 		break;
671 	default:
672 		err = ENOTSUP;
673 		break;
674 	}
675 	return (err);
676 }
677 
678 void
679 ixgbe_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
680     mac_prop_info_handle_t prh)
681 {
682 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
683 	struct ixgbe_hw *hw = &ixgbe->hw;
684 	uint_t perm;
685 	uint8_t value;
686 	ixgbe_link_speed speeds = 0;
687 
688 	/*
689 	 * We cannot always rely on the common code maintaining
690 	 * hw->phy.speeds_supported, therefore we fall back to use the
691 	 * recorded supported speeds which were obtained during instance init in
692 	 * ixgbe_init_params().
693 	 */
694 	speeds = hw->phy.speeds_supported;
695 	if (speeds == 0)
696 		speeds = ixgbe->speeds_supported;
697 
698 	switch (pr_num) {
699 	case MAC_PROP_DUPLEX:
700 	case MAC_PROP_SPEED:
701 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
702 		break;
703 
704 	case MAC_PROP_ADV_100FDX_CAP:
705 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
706 		value = (speeds & IXGBE_LINK_SPEED_100_FULL) ? 1 : 0;
707 		mac_prop_info_set_default_uint8(prh, value);
708 		break;
709 
710 	case MAC_PROP_ADV_1000FDX_CAP:
711 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
712 		value = (speeds & IXGBE_LINK_SPEED_1GB_FULL) ? 1 : 0;
713 		mac_prop_info_set_default_uint8(prh, value);
714 		break;
715 
716 	case MAC_PROP_ADV_2500FDX_CAP:
717 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
718 		value = (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) ? 1 : 0;
719 		mac_prop_info_set_default_uint8(prh, value);
720 		break;
721 
722 	case MAC_PROP_ADV_5000FDX_CAP:
723 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
724 		value = (speeds & IXGBE_LINK_SPEED_5GB_FULL) ? 1 : 0;
725 		mac_prop_info_set_default_uint8(prh, value);
726 		break;
727 
728 	case MAC_PROP_ADV_10GFDX_CAP:
729 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
730 		value = (speeds & IXGBE_LINK_SPEED_10GB_FULL) ? 1 : 0;
731 		mac_prop_info_set_default_uint8(prh, value);
732 		break;
733 
734 	/*
735 	 * We allow speed changes only on baseT PHYs. MAC_PROP_EN_* are marked
736 	 * read-only on non-baseT (SFP) PHYs.
737 	 */
738 	case MAC_PROP_AUTONEG:
739 		perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
740 		    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
741 		mac_prop_info_set_perm(prh, perm);
742 		mac_prop_info_set_default_uint8(prh, 1);
743 		break;
744 
745 	case MAC_PROP_EN_10GFDX_CAP:
746 		if (speeds & IXGBE_LINK_SPEED_10GB_FULL) {
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 		}
752 		break;
753 
754 	case MAC_PROP_EN_5000FDX_CAP:
755 		if (speeds & IXGBE_LINK_SPEED_5GB_FULL) {
756 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
757 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
758 			mac_prop_info_set_perm(prh, perm);
759 			mac_prop_info_set_default_uint8(prh, 1);
760 		}
761 		break;
762 
763 	case MAC_PROP_EN_2500FDX_CAP:
764 		if (speeds & IXGBE_LINK_SPEED_2_5GB_FULL) {
765 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
766 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
767 			mac_prop_info_set_perm(prh, perm);
768 			mac_prop_info_set_default_uint8(prh, 1);
769 		}
770 		break;
771 
772 	case MAC_PROP_EN_1000FDX_CAP:
773 		if (speeds & IXGBE_LINK_SPEED_1GB_FULL) {
774 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
775 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
776 			mac_prop_info_set_perm(prh, perm);
777 			mac_prop_info_set_default_uint8(prh, 1);
778 		}
779 		break;
780 
781 	case MAC_PROP_EN_100FDX_CAP:
782 		if (speeds & IXGBE_LINK_SPEED_100_FULL) {
783 			perm = (hw->phy.media_type == ixgbe_media_type_copper) ?
784 			    MAC_PROP_PERM_RW : MAC_PROP_PERM_READ;
785 			mac_prop_info_set_perm(prh, perm);
786 			mac_prop_info_set_default_uint8(prh, 1);
787 		}
788 		break;
789 
790 	case MAC_PROP_FLOWCTRL:
791 		mac_prop_info_set_default_link_flowctrl(prh,
792 		    LINK_FLOWCTRL_NONE);
793 		break;
794 
795 	case MAC_PROP_MTU:
796 		mac_prop_info_set_range_uint32(prh,
797 		    DEFAULT_MTU, ixgbe->capab->max_mtu);
798 		break;
799 
800 	case MAC_PROP_PRIVATE: {
801 		char valstr[64];
802 		int value;
803 
804 		bzero(valstr, sizeof (valstr));
805 
806 		if (strcmp(pr_name, "_adv_pause_cap") == 0 ||
807 		    strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
808 			mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
809 			return;
810 		}
811 
812 		if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
813 			value = DEFAULT_TX_COPY_THRESHOLD;
814 		} else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
815 			value = DEFAULT_TX_RECYCLE_THRESHOLD;
816 		} else if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
817 			value = DEFAULT_TX_OVERLOAD_THRESHOLD;
818 		} else if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
819 			value = DEFAULT_TX_RESCHED_THRESHOLD;
820 		} else if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
821 			value = DEFAULT_RX_COPY_THRESHOLD;
822 		} else if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
823 			value = DEFAULT_RX_LIMIT_PER_INTR;
824 		} else if (strcmp(pr_name, "_intr_throttling") == 0) {
825 			value = ixgbe->capab->def_intr_throttle;
826 		} else {
827 			return;
828 		}
829 
830 		(void) snprintf(valstr, sizeof (valstr), "%x", value);
831 	}
832 	}
833 }
834 
835 boolean_t
836 ixgbe_param_locked(mac_prop_id_t pr_num)
837 {
838 	/*
839 	 * All en_* parameters are locked (read-only) while
840 	 * the device is in any sort of loopback mode ...
841 	 */
842 	switch (pr_num) {
843 		case MAC_PROP_EN_10GFDX_CAP:
844 		case MAC_PROP_EN_5000FDX_CAP:
845 		case MAC_PROP_EN_2500FDX_CAP:
846 		case MAC_PROP_EN_1000FDX_CAP:
847 		case MAC_PROP_EN_100FDX_CAP:
848 		case MAC_PROP_AUTONEG:
849 		case MAC_PROP_FLOWCTRL:
850 			return (B_TRUE);
851 	}
852 	return (B_FALSE);
853 }
854 
855 /* ARGSUSED */
856 int
857 ixgbe_set_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
858     uint_t pr_valsize, const void *pr_val)
859 {
860 	int err = 0;
861 	long result;
862 	struct ixgbe_hw *hw = &ixgbe->hw;
863 	int i;
864 
865 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
866 		if (pr_val == NULL) {
867 			err = EINVAL;
868 			return (err);
869 		}
870 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
871 		if (result < MIN_TX_COPY_THRESHOLD ||
872 		    result > MAX_TX_COPY_THRESHOLD)
873 			err = EINVAL;
874 		else {
875 			ixgbe->tx_copy_thresh = (uint32_t)result;
876 		}
877 		return (err);
878 	}
879 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
880 		if (pr_val == NULL) {
881 			err = EINVAL;
882 			return (err);
883 		}
884 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
885 		if (result < MIN_TX_RECYCLE_THRESHOLD ||
886 		    result > MAX_TX_RECYCLE_THRESHOLD)
887 			err = EINVAL;
888 		else {
889 			ixgbe->tx_recycle_thresh = (uint32_t)result;
890 		}
891 		return (err);
892 	}
893 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
894 		if (pr_val == NULL) {
895 			err = EINVAL;
896 			return (err);
897 		}
898 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
899 		if (result < MIN_TX_OVERLOAD_THRESHOLD ||
900 		    result > MAX_TX_OVERLOAD_THRESHOLD)
901 			err = EINVAL;
902 		else {
903 			ixgbe->tx_overload_thresh = (uint32_t)result;
904 		}
905 		return (err);
906 	}
907 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
908 		if (pr_val == NULL) {
909 			err = EINVAL;
910 			return (err);
911 		}
912 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
913 		if (result < MIN_TX_RESCHED_THRESHOLD ||
914 		    result > MAX_TX_RESCHED_THRESHOLD)
915 			err = EINVAL;
916 		else {
917 			ixgbe->tx_resched_thresh = (uint32_t)result;
918 		}
919 		return (err);
920 	}
921 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
922 		if (pr_val == NULL) {
923 			err = EINVAL;
924 			return (err);
925 		}
926 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
927 		if (result < MIN_RX_COPY_THRESHOLD ||
928 		    result > MAX_RX_COPY_THRESHOLD)
929 			err = EINVAL;
930 		else {
931 			ixgbe->rx_copy_thresh = (uint32_t)result;
932 		}
933 		return (err);
934 	}
935 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
936 		if (pr_val == NULL) {
937 			err = EINVAL;
938 			return (err);
939 		}
940 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
941 		if (result < MIN_RX_LIMIT_PER_INTR ||
942 		    result > MAX_RX_LIMIT_PER_INTR)
943 			err = EINVAL;
944 		else {
945 			ixgbe->rx_limit_per_intr = (uint32_t)result;
946 		}
947 		return (err);
948 	}
949 	if (strcmp(pr_name, "_intr_throttling") == 0) {
950 		if (pr_val == NULL) {
951 			err = EINVAL;
952 			return (err);
953 		}
954 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
955 
956 		if (result < ixgbe->capab->min_intr_throttle ||
957 		    result > ixgbe->capab->max_intr_throttle)
958 			err = EINVAL;
959 		else {
960 			ixgbe->intr_throttling[0] = (uint32_t)result;
961 
962 			/*
963 			 * 82599, X540 and X550 require the interrupt throttling
964 			 * rate is a multiple of 8. This is enforced by the
965 			 * register definiton.
966 			 */
967 			if (hw->mac.type == ixgbe_mac_82599EB ||
968 			    hw->mac.type == ixgbe_mac_X540 ||
969 			    hw->mac.type == ixgbe_mac_X550 ||
970 			    hw->mac.type == ixgbe_mac_X550EM_x) {
971 				ixgbe->intr_throttling[0] =
972 				    ixgbe->intr_throttling[0] & 0xFF8;
973 			}
974 
975 			for (i = 0; i < MAX_INTR_VECTOR; i++)
976 				ixgbe->intr_throttling[i] =
977 				    ixgbe->intr_throttling[0];
978 
979 			/* Set interrupt throttling rate */
980 			for (i = 0; i < ixgbe->intr_cnt; i++)
981 				IXGBE_WRITE_REG(hw, IXGBE_EITR(i),
982 				    ixgbe->intr_throttling[i]);
983 		}
984 		return (err);
985 	}
986 	return (ENOTSUP);
987 }
988 
989 int
990 ixgbe_get_priv_prop(ixgbe_t *ixgbe, const char *pr_name,
991     uint_t pr_valsize, void *pr_val)
992 {
993 	int err = ENOTSUP;
994 	int value;
995 
996 	if (strcmp(pr_name, "_adv_pause_cap") == 0) {
997 		value = ixgbe->param_adv_pause_cap;
998 		err = 0;
999 		goto done;
1000 	}
1001 	if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
1002 		value = ixgbe->param_adv_asym_pause_cap;
1003 		err = 0;
1004 		goto done;
1005 	}
1006 	if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
1007 		value = ixgbe->tx_copy_thresh;
1008 		err = 0;
1009 		goto done;
1010 	}
1011 	if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
1012 		value = ixgbe->tx_recycle_thresh;
1013 		err = 0;
1014 		goto done;
1015 	}
1016 	if (strcmp(pr_name, "_tx_overload_thresh") == 0) {
1017 		value = ixgbe->tx_overload_thresh;
1018 		err = 0;
1019 		goto done;
1020 	}
1021 	if (strcmp(pr_name, "_tx_resched_thresh") == 0) {
1022 		value = ixgbe->tx_resched_thresh;
1023 		err = 0;
1024 		goto done;
1025 	}
1026 	if (strcmp(pr_name, "_rx_copy_thresh") == 0) {
1027 		value = ixgbe->rx_copy_thresh;
1028 		err = 0;
1029 		goto done;
1030 	}
1031 	if (strcmp(pr_name, "_rx_limit_per_intr") == 0) {
1032 		value = ixgbe->rx_limit_per_intr;
1033 		err = 0;
1034 		goto done;
1035 	}
1036 	if (strcmp(pr_name, "_intr_throttling") == 0) {
1037 		value = ixgbe->intr_throttling[0];
1038 		err = 0;
1039 		goto done;
1040 	}
1041 done:
1042 	if (err == 0) {
1043 		(void) snprintf(pr_val, pr_valsize, "%d", value);
1044 	}
1045 	return (err);
1046 }
1047