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