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