2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
14 * Copyright 2016 Joyent, Inc.
15 * Copyright 2017 Tegile Systems, Inc. All rights reserved.
19 * For more information, please see the big theory statement in i40e_main.c.
24 #define I40E_PROP_RX_DMA_THRESH "_rx_dma_threshold"
25 #define I40E_PROP_TX_DMA_THRESH "_tx_dma_threshold"
26 #define I40E_PROP_RX_ITR "_rx_intr_throttle"
27 #define I40E_PROP_TX_ITR "_tx_intr_throttle"
28 #define I40E_PROP_OTHER_ITR "_other_intr_throttle"
30 char *i40e_priv_props
[] = {
31 I40E_PROP_RX_DMA_THRESH
,
32 I40E_PROP_TX_DMA_THRESH
,
40 i40e_group_remove_mac(void *arg
, const uint8_t *mac_addr
)
43 struct i40e_aqc_remove_macvlan_element_data filt
;
44 struct i40e_hw
*hw
= &i40e
->i40e_hw_space
;
48 if (I40E_IS_MULTICAST(mac_addr
))
51 mutex_enter(&i40e
->i40e_general_lock
);
53 if (i40e
->i40e_state
& I40E_SUSPENDED
) {
58 for (i
= 0; i
< i40e
->i40e_resources
.ifr_nmacfilt_used
; i
++) {
59 if (bcmp(mac_addr
, i40e
->i40e_uaddrs
[i
].iua_mac
,
64 if (i
== i40e
->i40e_resources
.ifr_nmacfilt_used
) {
69 iua
= &i40e
->i40e_uaddrs
[i
];
70 ASSERT(i40e
->i40e_resources
.ifr_nmacfilt_used
> 0);
72 bzero(&filt
, sizeof (filt
));
73 bcopy(mac_addr
, filt
.mac_addr
, ETHERADDRL
);
74 filt
.flags
= I40E_AQC_MACVLAN_DEL_PERFECT_MATCH
|
75 I40E_AQC_MACVLAN_DEL_IGNORE_VLAN
;
77 if (i40e_aq_remove_macvlan(hw
, iua
->iua_vsi
, &filt
, 1, NULL
) !=
79 i40e_error(i40e
, "failed to remove mac address "
80 "%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d",
81 mac_addr
[0], mac_addr
[1], mac_addr
[2], mac_addr
[3],
82 mac_addr
[4], mac_addr
[5], filt
.error_code
);
87 last
= i40e
->i40e_resources
.ifr_nmacfilt_used
- 1;
89 i40e_uaddr_t
*src
= &i40e
->i40e_uaddrs
[last
];
90 bcopy(src
, iua
, sizeof (i40e_uaddr_t
));
94 * Set the multicast bit in the last one to indicate to ourselves that
97 bzero(&i40e
->i40e_uaddrs
[last
], sizeof (i40e_uaddr_t
));
98 i40e
->i40e_uaddrs
[last
].iua_mac
[0] = 0x01;
99 i40e
->i40e_resources
.ifr_nmacfilt_used
--;
102 mutex_exit(&i40e
->i40e_general_lock
);
108 i40e_group_add_mac(void *arg
, const uint8_t *mac_addr
)
111 struct i40e_hw
*hw
= &i40e
->i40e_hw_space
;
114 struct i40e_aqc_add_macvlan_element_data filt
;
116 if (I40E_IS_MULTICAST(mac_addr
))
119 mutex_enter(&i40e
->i40e_general_lock
);
120 if (i40e
->i40e_state
& I40E_SUSPENDED
) {
125 if (i40e
->i40e_resources
.ifr_nmacfilt
==
126 i40e
->i40e_resources
.ifr_nmacfilt_used
) {
131 for (i
= 0; i
< i40e
->i40e_resources
.ifr_nmacfilt_used
; i
++) {
132 if (bcmp(mac_addr
, i40e
->i40e_uaddrs
[i
].iua_mac
,
140 * Note, the general use of the i40e_vsi_id will have to be refactored
141 * when we have proper group support.
143 bzero(&filt
, sizeof (filt
));
144 bcopy(mac_addr
, filt
.mac_addr
, ETHERADDRL
);
145 filt
.flags
= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH
|
146 I40E_AQC_MACVLAN_ADD_IGNORE_VLAN
;
148 if ((ret
= i40e_aq_add_macvlan(hw
, i40e
->i40e_vsi_id
, &filt
, 1,
149 NULL
)) != I40E_SUCCESS
) {
150 i40e_error(i40e
, "failed to add mac address "
151 "%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d",
152 mac_addr
[0], mac_addr
[1], mac_addr
[2], mac_addr
[3],
153 mac_addr
[4], mac_addr
[5], ret
);
158 iua
= &i40e
->i40e_uaddrs
[i40e
->i40e_resources
.ifr_nmacfilt_used
];
159 bcopy(mac_addr
, iua
->iua_mac
, ETHERADDRL
);
160 iua
->iua_vsi
= i40e
->i40e_vsi_id
;
161 i40e
->i40e_resources
.ifr_nmacfilt_used
++;
162 ASSERT(i40e
->i40e_resources
.ifr_nmacfilt_used
<=
163 i40e
->i40e_resources
.ifr_nmacfilt
);
166 mutex_exit(&i40e
->i40e_general_lock
);
171 i40e_m_start(void *arg
)
176 mutex_enter(&i40e
->i40e_general_lock
);
177 if (i40e
->i40e_state
& I40E_SUSPENDED
) {
182 if (!i40e_start(i40e
, B_TRUE
)) {
187 atomic_or_32(&i40e
->i40e_state
, I40E_STARTED
);
189 mutex_exit(&i40e
->i40e_general_lock
);
195 i40e_m_stop(void *arg
)
199 mutex_enter(&i40e
->i40e_general_lock
);
201 if (i40e
->i40e_state
& I40E_SUSPENDED
)
204 atomic_and_32(&i40e
->i40e_state
, ~I40E_STARTED
);
205 i40e_stop(i40e
, B_TRUE
);
207 mutex_exit(&i40e
->i40e_general_lock
);
211 * Enable and disable promiscuous mode as requested. We have to toggle both
212 * unicast and multicast. Note that multicast may already be enabled due to the
213 * i40e_m_multicast may toggle it itself. See i40e_main.c for more information
217 i40e_m_promisc(void *arg
, boolean_t on
)
220 struct i40e_hw
*hw
= &i40e
->i40e_hw_space
;
221 int ret
= 0, err
= 0;
223 mutex_enter(&i40e
->i40e_general_lock
);
224 if (i40e
->i40e_state
& I40E_SUSPENDED
) {
230 ret
= i40e_aq_set_vsi_unicast_promiscuous(hw
, i40e
->i40e_vsi_id
,
232 if (ret
!= I40E_SUCCESS
) {
233 i40e_error(i40e
, "failed to %s unicast promiscuity on "
234 "the default VSI: %d", on
== B_TRUE
? "enable" : "disable",
241 * If we have a non-zero mcast_promisc_count, then it has already been
242 * enabled or we need to leave it that way and not touch it.
244 if (i40e
->i40e_mcast_promisc_count
> 0) {
245 i40e
->i40e_promisc_on
= on
;
249 ret
= i40e_aq_set_vsi_multicast_promiscuous(hw
, i40e
->i40e_vsi_id
,
251 if (ret
!= I40E_SUCCESS
) {
252 i40e_error(i40e
, "failed to %s multicast promiscuity on "
253 "the default VSI: %d", on
== B_TRUE
? "enable" : "disable",
257 * Try our best to put us back into a state that MAC expects us
260 ret
= i40e_aq_set_vsi_unicast_promiscuous(hw
, i40e
->i40e_vsi_id
,
262 if (ret
!= I40E_SUCCESS
) {
263 i40e_error(i40e
, "failed to %s unicast promiscuity on "
264 "the default VSI after toggling multicast failed: "
265 "%d", on
== B_TRUE
? "disable" : "enable", ret
);
271 i40e
->i40e_promisc_on
= on
;
275 mutex_exit(&i40e
->i40e_general_lock
);
280 * See the big theory statement in i40e_main.c for multicast address management.
283 i40e_multicast_add(i40e_t
*i40e
, const uint8_t *multicast_address
)
285 struct i40e_hw
*hw
= &i40e
->i40e_hw_space
;
286 struct i40e_aqc_add_macvlan_element_data filt
;
290 ASSERT(MUTEX_HELD(&i40e
->i40e_general_lock
));
292 if (i40e
->i40e_resources
.ifr_nmcastfilt_used
==
293 i40e
->i40e_resources
.ifr_nmcastfilt
) {
294 if (i40e
->i40e_mcast_promisc_count
== 0 &&
295 i40e
->i40e_promisc_on
== B_FALSE
) {
296 ret
= i40e_aq_set_vsi_multicast_promiscuous(hw
,
297 i40e
->i40e_vsi_id
, B_TRUE
, NULL
);
298 if (ret
!= I40E_SUCCESS
) {
299 i40e_error(i40e
, "failed to enable multicast "
300 "promiscuous mode on VSI %d: %d",
301 i40e
->i40e_vsi_id
, ret
);
305 i40e
->i40e_mcast_promisc_count
++;
309 mc
= &i40e
->i40e_maddrs
[i40e
->i40e_resources
.ifr_nmcastfilt_used
];
310 bzero(&filt
, sizeof (filt
));
311 bcopy(multicast_address
, filt
.mac_addr
, ETHERADDRL
);
312 filt
.flags
= I40E_AQC_MACVLAN_ADD_HASH_MATCH
|
313 I40E_AQC_MACVLAN_ADD_IGNORE_VLAN
;
315 if ((ret
= i40e_aq_add_macvlan(hw
, i40e
->i40e_vsi_id
, &filt
, 1,
316 NULL
)) != I40E_SUCCESS
) {
317 i40e_error(i40e
, "failed to add mac address "
318 "%2x:%2x:%2x:%2x:%2x:%2x to multicast filter: %d",
319 multicast_address
[0], multicast_address
[1],
320 multicast_address
[2], multicast_address
[3],
321 multicast_address
[4], multicast_address
[5],
326 bcopy(multicast_address
, mc
->ima_mac
, ETHERADDRL
);
327 i40e
->i40e_resources
.ifr_nmcastfilt_used
++;
332 * See the big theory statement in i40e_main.c for multicast address management.
335 i40e_multicast_remove(i40e_t
*i40e
, const uint8_t *multicast_address
)
338 struct i40e_hw
*hw
= &i40e
->i40e_hw_space
;
340 ASSERT(MUTEX_HELD(&i40e
->i40e_general_lock
));
342 for (i
= 0; i
< i40e
->i40e_resources
.ifr_nmcastfilt_used
; i
++) {
343 struct i40e_aqc_remove_macvlan_element_data filt
;
346 if (bcmp(multicast_address
, i40e
->i40e_maddrs
[i
].ima_mac
,
351 bzero(&filt
, sizeof (filt
));
352 bcopy(multicast_address
, filt
.mac_addr
, ETHERADDRL
);
353 filt
.flags
= I40E_AQC_MACVLAN_DEL_HASH_MATCH
|
354 I40E_AQC_MACVLAN_DEL_IGNORE_VLAN
;
356 if (i40e_aq_remove_macvlan(hw
, i40e
->i40e_vsi_id
,
357 &filt
, 1, NULL
) != I40E_SUCCESS
) {
358 i40e_error(i40e
, "failed to remove mac address "
359 "%2x:%2x:%2x:%2x:%2x:%2x from multicast "
361 multicast_address
[0], multicast_address
[1],
362 multicast_address
[2], multicast_address
[3],
363 multicast_address
[4], multicast_address
[5],
368 last
= i40e
->i40e_resources
.ifr_nmcastfilt_used
- 1;
370 bcopy(&i40e
->i40e_maddrs
[last
], &i40e
->i40e_maddrs
[i
],
371 sizeof (i40e_maddr_t
));
372 bzero(&i40e
->i40e_maddrs
[last
], sizeof (i40e_maddr_t
));
375 ASSERT(i40e
->i40e_resources
.ifr_nmcastfilt_used
> 0);
376 i40e
->i40e_resources
.ifr_nmcastfilt_used
--;
380 if (i40e
->i40e_mcast_promisc_count
> 0) {
381 if (i40e
->i40e_mcast_promisc_count
== 1 &&
382 i40e
->i40e_promisc_on
== B_FALSE
) {
383 ret
= i40e_aq_set_vsi_multicast_promiscuous(hw
,
384 i40e
->i40e_vsi_id
, B_FALSE
, NULL
);
385 if (ret
!= I40E_SUCCESS
) {
386 i40e_error(i40e
, "failed to disable "
387 "multicast promiscuous mode on VSI %d: %d",
388 i40e
->i40e_vsi_id
, ret
);
392 i40e
->i40e_mcast_promisc_count
--;
401 i40e_m_multicast(void *arg
, boolean_t add
, const uint8_t *multicast_address
)
406 mutex_enter(&i40e
->i40e_general_lock
);
408 if (i40e
->i40e_state
& I40E_SUSPENDED
) {
409 mutex_exit(&i40e
->i40e_general_lock
);
414 rc
= i40e_multicast_add(i40e
, multicast_address
);
416 rc
= i40e_multicast_remove(i40e
, multicast_address
);
419 mutex_exit(&i40e
->i40e_general_lock
);
425 i40e_m_ioctl(void *arg
, queue_t
*q
, mblk_t
*mp
)
428 * At this time, we don't support toggling i40e into loopback mode. It's
429 * questionable how much value this has when there's no clear way to
430 * toggle this behavior from a supported way in userland.
432 miocnak(q
, mp
, 0, EINVAL
);
436 i40e_ring_start(mac_ring_driver_t rh
, uint64_t gen_num
)
438 i40e_trqpair_t
*itrq
= (i40e_trqpair_t
*)rh
;
441 * GLDv3 requires we keep track of a generation number, as it uses
442 * that number to keep track of whether or not a ring is active.
444 mutex_enter(&itrq
->itrq_rx_lock
);
445 itrq
->itrq_rxgen
= gen_num
;
446 mutex_exit(&itrq
->itrq_rx_lock
);
452 i40e_rx_ring_intr_enable(mac_intr_handle_t intrh
)
454 i40e_trqpair_t
*itrq
= (i40e_trqpair_t
*)intrh
;
455 i40e_t
*i40e
= itrq
->itrq_i40e
;
457 mutex_enter(&itrq
->itrq_rx_lock
);
458 ASSERT(itrq
->itrq_intr_poll
== B_TRUE
);
459 i40e_intr_rx_queue_enable(i40e
, itrq
->itrq_index
);
460 itrq
->itrq_intr_poll
= B_FALSE
;
461 mutex_exit(&itrq
->itrq_rx_lock
);
468 i40e_rx_ring_intr_disable(mac_intr_handle_t intrh
)
470 i40e_trqpair_t
*itrq
= (i40e_trqpair_t
*)intrh
;
471 i40e_t
*i40e
= itrq
->itrq_i40e
;
473 mutex_enter(&itrq
->itrq_rx_lock
);
474 i40e_intr_rx_queue_disable(i40e
, itrq
->itrq_index
);
475 itrq
->itrq_intr_poll
= B_TRUE
;
476 mutex_exit(&itrq
->itrq_rx_lock
);
483 i40e_fill_tx_ring(void *arg
, mac_ring_type_t rtype
, const int group_index
,
484 const int ring_index
, mac_ring_info_t
*infop
, mac_ring_handle_t rh
)
487 mac_intr_t
*mintr
= &infop
->mri_intr
;
488 i40e_trqpair_t
*itrq
= &(i40e
->i40e_trqpairs
[ring_index
]);
491 * Note the group index here is expected to be -1 due to the fact that
492 * we're not actually grouping things tx-wise at this time.
494 ASSERT(group_index
== -1);
495 ASSERT(ring_index
< i40e
->i40e_num_trqpairs
);
497 itrq
->itrq_mactxring
= rh
;
498 infop
->mri_driver
= (mac_ring_driver_t
)itrq
;
499 infop
->mri_start
= NULL
;
500 infop
->mri_stop
= NULL
;
501 infop
->mri_tx
= i40e_ring_tx
;
502 infop
->mri_stat
= i40e_tx_ring_stat
;
505 * We only provide the handle in cases where we have MSI-X interrupts,
506 * to indicate that we'd actually support retargetting.
508 if (i40e
->i40e_intr_type
& DDI_INTR_TYPE_MSIX
) {
509 mintr
->mi_ddi_handle
=
510 i40e
->i40e_intr_handles
[itrq
->itrq_tx_intrvec
];
516 i40e_fill_rx_ring(void *arg
, mac_ring_type_t rtype
, const int group_index
,
517 const int ring_index
, mac_ring_info_t
*infop
, mac_ring_handle_t rh
)
520 mac_intr_t
*mintr
= &infop
->mri_intr
;
521 i40e_trqpair_t
*itrq
= &i40e
->i40e_trqpairs
[ring_index
];
524 * We assert the group number and ring index to help sanity check
525 * ourselves and mark that we'll need to rework this when we have
528 ASSERT3S(group_index
, ==, 0);
529 ASSERT3S(ring_index
, <, i40e
->i40e_num_trqpairs
);
531 itrq
->itrq_macrxring
= rh
;
532 infop
->mri_driver
= (mac_ring_driver_t
)itrq
;
533 infop
->mri_start
= i40e_ring_start
;
534 infop
->mri_stop
= NULL
;
535 infop
->mri_poll
= i40e_ring_rx_poll
;
536 infop
->mri_stat
= i40e_rx_ring_stat
;
537 mintr
->mi_handle
= (mac_intr_handle_t
)itrq
;
538 mintr
->mi_enable
= i40e_rx_ring_intr_enable
;
539 mintr
->mi_disable
= i40e_rx_ring_intr_disable
;
542 * We only provide the handle in cases where we have MSI-X interrupts,
543 * to indicate that we'd actually support retargetting.
545 if (i40e
->i40e_intr_type
& DDI_INTR_TYPE_MSIX
) {
546 mintr
->mi_ddi_handle
=
547 i40e
->i40e_intr_handles
[itrq
->itrq_rx_intrvec
];
553 i40e_fill_rx_group(void *arg
, mac_ring_type_t rtype
, const int index
,
554 mac_group_info_t
*infop
, mac_group_handle_t gh
)
558 if (rtype
!= MAC_RING_TYPE_RX
)
562 * Note, this is a simplified view of a group, given that we only have a
563 * single group and a single ring at the moment. We'll want to expand
564 * upon this as we leverage more hardware functionality.
566 i40e
->i40e_rx_group_handle
= gh
;
567 infop
->mgi_driver
= (mac_group_driver_t
)i40e
;
568 infop
->mgi_start
= NULL
;
569 infop
->mgi_stop
= NULL
;
570 infop
->mgi_addmac
= i40e_group_add_mac
;
571 infop
->mgi_remmac
= i40e_group_remove_mac
;
573 ASSERT(i40e
->i40e_num_rx_groups
== I40E_GROUP_MAX
);
574 infop
->mgi_count
= i40e
->i40e_num_trqpairs
;
578 i40e_m_getcapab(void *arg
, mac_capab_t cap
, void *cap_data
)
581 mac_capab_rings_t
*cap_rings
;
584 case MAC_CAPAB_HCKSUM
: {
585 uint32_t *txflags
= cap_data
;
588 if (i40e
->i40e_tx_hcksum_enable
== B_TRUE
)
589 *txflags
= HCKSUM_INET_PARTIAL
| HCKSUM_IPHDRCKSUM
;
593 case MAC_CAPAB_RINGS
:
594 cap_rings
= cap_data
;
595 cap_rings
->mr_group_type
= MAC_GROUP_TYPE_STATIC
;
596 switch (cap_rings
->mr_type
) {
597 case MAC_RING_TYPE_TX
:
599 * Note, saying we have no rings, but some number of
600 * groups indicates to MAC that it should create
601 * psuedo-groups with one for each TX ring. This may not
602 * be the long term behavior we want, but it'll work for
605 cap_rings
->mr_gnum
= 0;
606 cap_rings
->mr_rnum
= i40e
->i40e_num_trqpairs
;
607 cap_rings
->mr_rget
= i40e_fill_tx_ring
;
608 cap_rings
->mr_gget
= NULL
;
609 cap_rings
->mr_gaddring
= NULL
;
610 cap_rings
->mr_gremring
= NULL
;
612 case MAC_RING_TYPE_RX
:
613 cap_rings
->mr_rnum
= i40e
->i40e_num_trqpairs
;
614 cap_rings
->mr_rget
= i40e_fill_rx_ring
;
615 cap_rings
->mr_gnum
= I40E_GROUP_MAX
;
616 cap_rings
->mr_gget
= i40e_fill_rx_group
;
617 cap_rings
->mr_gaddring
= NULL
;
618 cap_rings
->mr_gremring
= NULL
;
633 i40e_m_setprop_private(i40e_t
*i40e
, const char *pr_name
, uint_t pr_valsize
,
640 ASSERT(MUTEX_HELD(&i40e
->i40e_general_lock
));
642 if ((ret
= ddi_strtol(pr_val
, &eptr
, 10, &val
)) != 0 ||
647 if (strcmp(pr_name
, I40E_PROP_RX_DMA_THRESH
) == 0) {
648 if (val
< I40E_MIN_RX_DMA_THRESH
||
649 val
> I40E_MAX_RX_DMA_THRESH
) {
652 i40e
->i40e_rx_dma_min
= (uint32_t)val
;
656 if (strcmp(pr_name
, I40E_PROP_TX_DMA_THRESH
) == 0) {
657 if (val
< I40E_MIN_TX_DMA_THRESH
||
658 val
> I40E_MAX_TX_DMA_THRESH
) {
661 i40e
->i40e_tx_dma_min
= (uint32_t)val
;
665 if (strcmp(pr_name
, I40E_PROP_RX_ITR
) == 0) {
666 if (val
< I40E_MIN_ITR
||
667 val
> I40E_MAX_ITR
) {
670 i40e
->i40e_rx_itr
= (uint32_t)val
;
671 i40e_intr_set_itr(i40e
, I40E_ITR_INDEX_RX
, i40e
->i40e_rx_itr
);
675 if (strcmp(pr_name
, I40E_PROP_TX_ITR
) == 0) {
676 if (val
< I40E_MIN_ITR
||
677 val
> I40E_MAX_ITR
) {
680 i40e
->i40e_tx_itr
= (uint32_t)val
;
681 i40e_intr_set_itr(i40e
, I40E_ITR_INDEX_TX
, i40e
->i40e_tx_itr
);
685 if (strcmp(pr_name
, I40E_PROP_OTHER_ITR
) == 0) {
686 if (val
< I40E_MIN_ITR
||
687 val
> I40E_MAX_ITR
) {
690 i40e
->i40e_tx_itr
= (uint32_t)val
;
691 i40e_intr_set_itr(i40e
, I40E_ITR_INDEX_OTHER
,
692 i40e
->i40e_other_itr
);
700 i40e_m_getprop_private(i40e_t
*i40e
, const char *pr_name
, uint_t pr_valsize
,
705 ASSERT(MUTEX_HELD(&i40e
->i40e_general_lock
));
707 if (strcmp(pr_name
, I40E_PROP_RX_DMA_THRESH
) == 0) {
708 val
= i40e
->i40e_rx_dma_min
;
709 } else if (strcmp(pr_name
, I40E_PROP_TX_DMA_THRESH
) == 0) {
710 val
= i40e
->i40e_tx_dma_min
;
711 } else if (strcmp(pr_name
, I40E_PROP_RX_ITR
) == 0) {
712 val
= i40e
->i40e_rx_itr
;
713 } else if (strcmp(pr_name
, I40E_PROP_TX_ITR
) == 0) {
714 val
= i40e
->i40e_tx_itr
;
715 } else if (strcmp(pr_name
, I40E_PROP_OTHER_ITR
) == 0) {
716 val
= i40e
->i40e_other_itr
;
721 if (snprintf(pr_val
, pr_valsize
, "%d", val
) >= pr_valsize
)
727 * Annoyingly for private properties MAC seems to ignore default values that
728 * aren't strings. That means that we have to translate all of these into
729 * uint32_t's and instead we size the buffer to be large enough to hold a
734 i40e_m_propinfo_private(i40e_t
*i40e
, const char *pr_name
,
735 mac_prop_info_handle_t prh
)
740 if (strcmp(pr_name
, I40E_PROP_RX_DMA_THRESH
) == 0) {
741 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_RW
);
742 def
= I40E_DEF_RX_DMA_THRESH
;
743 mac_prop_info_set_range_uint32(prh
,
744 I40E_MIN_RX_DMA_THRESH
,
745 I40E_MAX_RX_DMA_THRESH
);
746 } else if (strcmp(pr_name
, I40E_PROP_TX_DMA_THRESH
) == 0) {
747 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_RW
);
748 def
= I40E_DEF_TX_DMA_THRESH
;
749 mac_prop_info_set_range_uint32(prh
,
750 I40E_MIN_TX_DMA_THRESH
,
751 I40E_MAX_TX_DMA_THRESH
);
752 } else if (strcmp(pr_name
, I40E_PROP_RX_ITR
) == 0) {
753 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_RW
);
754 def
= I40E_DEF_RX_ITR
;
755 mac_prop_info_set_range_uint32(prh
, I40E_MIN_ITR
, I40E_MAX_ITR
);
756 } else if (strcmp(pr_name
, I40E_PROP_TX_ITR
) == 0) {
757 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_RW
);
758 def
= I40E_DEF_TX_ITR
;
759 mac_prop_info_set_range_uint32(prh
, I40E_MIN_ITR
, I40E_MAX_ITR
);
760 } else if (strcmp(pr_name
, I40E_PROP_OTHER_ITR
) == 0) {
761 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_RW
);
762 def
= I40E_DEF_OTHER_ITR
;
763 mac_prop_info_set_range_uint32(prh
, I40E_MIN_ITR
, I40E_MAX_ITR
);
768 (void) snprintf(buf
, sizeof (buf
), "%d", def
);
769 mac_prop_info_set_default_str(prh
, buf
);
773 i40e_m_setprop(void *arg
, const char *pr_name
, mac_prop_id_t pr_num
,
774 uint_t pr_valsize
, const void *pr_val
)
780 mutex_enter(&i40e
->i40e_general_lock
);
781 if (i40e
->i40e_state
& I40E_SUSPENDED
) {
782 mutex_exit(&i40e
->i40e_general_lock
);
788 * These properties are always read-only across every device.
790 case MAC_PROP_DUPLEX
:
792 case MAC_PROP_STATUS
:
793 case MAC_PROP_ADV_100FDX_CAP
:
794 case MAC_PROP_ADV_1000FDX_CAP
:
795 case MAC_PROP_ADV_10GFDX_CAP
:
796 case MAC_PROP_ADV_25GFDX_CAP
:
797 case MAC_PROP_ADV_40GFDX_CAP
:
801 * These are read-only at this time as we don't support configuring
802 * auto-negotiation. See the theory statement in i40e_main.c.
804 case MAC_PROP_EN_100FDX_CAP
:
805 case MAC_PROP_EN_1000FDX_CAP
:
806 case MAC_PROP_EN_10GFDX_CAP
:
807 case MAC_PROP_EN_25GFDX_CAP
:
808 case MAC_PROP_EN_40GFDX_CAP
:
809 case MAC_PROP_AUTONEG
:
810 case MAC_PROP_FLOWCTRL
:
815 bcopy(pr_val
, &new_mtu
, sizeof (new_mtu
));
816 if (new_mtu
== i40e
->i40e_sdu
)
819 if (new_mtu
< I40E_MIN_MTU
||
820 new_mtu
> I40E_MAX_MTU
) {
825 if (i40e
->i40e_state
& I40E_STARTED
) {
830 ret
= mac_maxsdu_update(i40e
->i40e_mac_hdl
, new_mtu
);
832 i40e
->i40e_sdu
= new_mtu
;
833 i40e_update_mtu(i40e
);
837 case MAC_PROP_PRIVATE
:
838 ret
= i40e_m_setprop_private(i40e
, pr_name
, pr_valsize
, pr_val
);
845 mutex_exit(&i40e
->i40e_general_lock
);
850 i40e_m_getprop(void *arg
, const char *pr_name
, mac_prop_id_t pr_num
,
851 uint_t pr_valsize
, void *pr_val
)
857 link_flowctrl_t fctl
;
859 mutex_enter(&i40e
->i40e_general_lock
);
862 case MAC_PROP_DUPLEX
:
863 if (pr_valsize
< sizeof (link_duplex_t
)) {
867 bcopy(&i40e
->i40e_link_duplex
, pr_val
, sizeof (link_duplex_t
));
870 if (pr_valsize
< sizeof (uint64_t)) {
874 speed
= i40e
->i40e_link_speed
* 1000000ULL;
875 bcopy(&speed
, pr_val
, sizeof (speed
));
877 case MAC_PROP_STATUS
:
878 if (pr_valsize
< sizeof (link_state_t
)) {
882 bcopy(&i40e
->i40e_link_state
, pr_val
, sizeof (link_state_t
));
884 case MAC_PROP_AUTONEG
:
885 if (pr_valsize
< sizeof (uint8_t)) {
892 case MAC_PROP_FLOWCTRL
:
894 * Because we don't currently support hardware flow control, we
895 * just hardcode this to be none.
897 if (pr_valsize
< sizeof (link_flowctrl_t
)) {
901 fctl
= LINK_FLOWCTRL_NONE
;
902 bcopy(&fctl
, pr_val
, sizeof (link_flowctrl_t
));
905 if (pr_valsize
< sizeof (uint32_t)) {
909 bcopy(&i40e
->i40e_sdu
, pr_val
, sizeof (uint32_t));
913 * Because we don't let users control the speeds we may auto-negotiate
914 * to, the values of the ADV_ and EN_ will always be the same.
916 case MAC_PROP_ADV_100FDX_CAP
:
917 case MAC_PROP_EN_100FDX_CAP
:
918 if (pr_valsize
< sizeof (uint8_t)) {
923 *u8
= (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_100MB
) != 0;
925 case MAC_PROP_ADV_1000FDX_CAP
:
926 case MAC_PROP_EN_1000FDX_CAP
:
927 if (pr_valsize
< sizeof (uint8_t)) {
932 *u8
= (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_1GB
) != 0;
934 case MAC_PROP_ADV_10GFDX_CAP
:
935 case MAC_PROP_EN_10GFDX_CAP
:
936 if (pr_valsize
< sizeof (uint8_t)) {
941 *u8
= (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_10GB
) != 0;
943 case MAC_PROP_ADV_25GFDX_CAP
:
944 case MAC_PROP_EN_25GFDX_CAP
:
945 if (pr_valsize
< sizeof (uint8_t)) {
950 *u8
= (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_25GB
) != 0;
952 case MAC_PROP_ADV_40GFDX_CAP
:
953 case MAC_PROP_EN_40GFDX_CAP
:
954 if (pr_valsize
< sizeof (uint8_t)) {
959 *u8
= (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_40GB
) != 0;
961 case MAC_PROP_PRIVATE
:
962 ret
= i40e_m_getprop_private(i40e
, pr_name
, pr_valsize
, pr_val
);
969 mutex_exit(&i40e
->i40e_general_lock
);
975 i40e_m_propinfo(void *arg
, const char *pr_name
, mac_prop_id_t pr_num
,
976 mac_prop_info_handle_t prh
)
980 mutex_enter(&i40e
->i40e_general_lock
);
983 case MAC_PROP_DUPLEX
:
985 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
987 case MAC_PROP_FLOWCTRL
:
989 * At the moment, the driver doesn't support flow control, hence
990 * why this is set to read-only and none.
992 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
993 mac_prop_info_set_default_link_flowctrl(prh
,
997 mac_prop_info_set_range_uint32(prh
, I40E_MIN_MTU
, I40E_MAX_MTU
);
1001 * We set the defaults for these based upon the phy's ability to
1002 * support the speeds. Note, auto-negotiation is required for fiber,
1003 * hence it is read-only and always enabled. When we have access to
1004 * copper phys we can revisit this.
1006 case MAC_PROP_AUTONEG
:
1007 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1008 mac_prop_info_set_default_uint8(prh
, 1);
1010 case MAC_PROP_ADV_100FDX_CAP
:
1011 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1012 mac_prop_info_set_default_uint8(prh
,
1013 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_100MB
) != 0);
1015 case MAC_PROP_EN_100FDX_CAP
:
1016 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1017 mac_prop_info_set_default_uint8(prh
,
1018 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_100MB
) != 0);
1020 case MAC_PROP_ADV_1000FDX_CAP
:
1021 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1022 mac_prop_info_set_default_uint8(prh
,
1023 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_1GB
) != 0);
1025 case MAC_PROP_EN_1000FDX_CAP
:
1026 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1027 mac_prop_info_set_default_uint8(prh
,
1028 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_1GB
) != 0);
1030 case MAC_PROP_ADV_10GFDX_CAP
:
1031 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1032 mac_prop_info_set_default_uint8(prh
,
1033 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_10GB
) != 0);
1035 case MAC_PROP_EN_10GFDX_CAP
:
1036 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1037 mac_prop_info_set_default_uint8(prh
,
1038 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_10GB
) != 0);
1040 case MAC_PROP_ADV_25GFDX_CAP
:
1041 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1042 mac_prop_info_set_default_uint8(prh
,
1043 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_25GB
) != 0);
1045 case MAC_PROP_EN_25GFDX_CAP
:
1046 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1047 mac_prop_info_set_default_uint8(prh
,
1048 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_25GB
) != 0);
1050 case MAC_PROP_ADV_40GFDX_CAP
:
1051 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1052 mac_prop_info_set_default_uint8(prh
,
1053 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_40GB
) != 0);
1055 case MAC_PROP_EN_40GFDX_CAP
:
1056 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
1057 mac_prop_info_set_default_uint8(prh
,
1058 (i40e
->i40e_phy
.link_speed
& I40E_LINK_SPEED_40GB
) != 0);
1060 case MAC_PROP_PRIVATE
:
1061 i40e_m_propinfo_private(i40e
, pr_name
, prh
);
1067 mutex_exit(&i40e
->i40e_general_lock
);
1070 #define I40E_M_CALLBACK_FLAGS \
1071 (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
1073 static mac_callbacks_t i40e_m_callbacks
= {
1074 I40E_M_CALLBACK_FLAGS
,
1093 i40e_register_mac(i40e_t
*i40e
)
1095 struct i40e_hw
*hw
= &i40e
->i40e_hw_space
;
1097 mac_register_t
*mac
= mac_alloc(MAC_VERSION
);
1102 mac
->m_type_ident
= MAC_PLUGIN_IDENT_ETHER
;
1103 mac
->m_driver
= i40e
;
1104 mac
->m_dip
= i40e
->i40e_dip
;
1105 mac
->m_src_addr
= hw
->mac
.addr
;
1106 mac
->m_callbacks
= &i40e_m_callbacks
;
1108 mac
->m_max_sdu
= i40e
->i40e_sdu
;
1109 mac
->m_margin
= VLAN_TAGSZ
;
1110 mac
->m_priv_props
= i40e_priv_props
;
1111 mac
->m_v12n
= MAC_VIRT_LEVEL1
;
1113 status
= mac_register(mac
, &i40e
->i40e_mac_hdl
);
1115 i40e_error(i40e
, "mac_register() returned %d", status
);
1118 return (status
== 0);