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 }