19d26e4fcSRobert Mustacchi /*
29d26e4fcSRobert Mustacchi * This file and its contents are supplied under the terms of the
39d26e4fcSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
49d26e4fcSRobert Mustacchi * You may only use this file in accordance with the terms of version
59d26e4fcSRobert Mustacchi * 1.0 of the CDDL.
69d26e4fcSRobert Mustacchi *
79d26e4fcSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
89d26e4fcSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
99d26e4fcSRobert Mustacchi * http://www.illumos.org/license/CDDL.
109d26e4fcSRobert Mustacchi */
119d26e4fcSRobert Mustacchi
129d26e4fcSRobert Mustacchi /*
139d26e4fcSRobert Mustacchi * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
146158afa4SDan McDonald * Copyright 2022 Joyent, Inc.
15396505afSPaul Winder * Copyright 2017 Tegile Systems, Inc. All rights reserved.
1688628b1bSRyan Zezeski * Copyright 2020 Ryan Zezeski
17aa2a44afSPaul Winder * Copyright 2020 RackTop Systems, Inc.
18*63783c5cSRobert Mustacchi * Copyright 2023 Oxide Computer Company
199d26e4fcSRobert Mustacchi */
209d26e4fcSRobert Mustacchi
219d26e4fcSRobert Mustacchi /*
229d26e4fcSRobert Mustacchi * For more information, please see the big theory statement in i40e_main.c.
239d26e4fcSRobert Mustacchi */
249d26e4fcSRobert Mustacchi
259d26e4fcSRobert Mustacchi #include "i40e_sw.h"
269d26e4fcSRobert Mustacchi
279d26e4fcSRobert Mustacchi #define I40E_PROP_RX_DMA_THRESH "_rx_dma_threshold"
289d26e4fcSRobert Mustacchi #define I40E_PROP_TX_DMA_THRESH "_tx_dma_threshold"
299d26e4fcSRobert Mustacchi #define I40E_PROP_RX_ITR "_rx_intr_throttle"
309d26e4fcSRobert Mustacchi #define I40E_PROP_TX_ITR "_tx_intr_throttle"
319d26e4fcSRobert Mustacchi #define I40E_PROP_OTHER_ITR "_other_intr_throttle"
329d26e4fcSRobert Mustacchi
339d26e4fcSRobert Mustacchi char *i40e_priv_props[] = {
349d26e4fcSRobert Mustacchi I40E_PROP_RX_DMA_THRESH,
359d26e4fcSRobert Mustacchi I40E_PROP_TX_DMA_THRESH,
369d26e4fcSRobert Mustacchi I40E_PROP_RX_ITR,
379d26e4fcSRobert Mustacchi I40E_PROP_TX_ITR,
389d26e4fcSRobert Mustacchi I40E_PROP_OTHER_ITR,
399d26e4fcSRobert Mustacchi NULL
409d26e4fcSRobert Mustacchi };
419d26e4fcSRobert Mustacchi
429d26e4fcSRobert Mustacchi static int
i40e_group_remove_mac(void * arg,const uint8_t * mac_addr)439d26e4fcSRobert Mustacchi i40e_group_remove_mac(void *arg, const uint8_t *mac_addr)
449d26e4fcSRobert Mustacchi {
4509aee612SRyan Zezeski i40e_rx_group_t *rxg = arg;
4609aee612SRyan Zezeski i40e_t *i40e = rxg->irg_i40e;
479d26e4fcSRobert Mustacchi struct i40e_aqc_remove_macvlan_element_data filt;
489d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space;
499d26e4fcSRobert Mustacchi int ret, i, last;
509d26e4fcSRobert Mustacchi i40e_uaddr_t *iua;
519d26e4fcSRobert Mustacchi
529d26e4fcSRobert Mustacchi if (I40E_IS_MULTICAST(mac_addr))
539d26e4fcSRobert Mustacchi return (EINVAL);
549d26e4fcSRobert Mustacchi
559d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
569d26e4fcSRobert Mustacchi
579d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) {
589d26e4fcSRobert Mustacchi ret = ECANCELED;
599d26e4fcSRobert Mustacchi goto done;
609d26e4fcSRobert Mustacchi }
619d26e4fcSRobert Mustacchi
629d26e4fcSRobert Mustacchi for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
639d26e4fcSRobert Mustacchi if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
649d26e4fcSRobert Mustacchi ETHERADDRL) == 0)
659d26e4fcSRobert Mustacchi break;
669d26e4fcSRobert Mustacchi }
679d26e4fcSRobert Mustacchi
689d26e4fcSRobert Mustacchi if (i == i40e->i40e_resources.ifr_nmacfilt_used) {
699d26e4fcSRobert Mustacchi ret = ENOENT;
709d26e4fcSRobert Mustacchi goto done;
719d26e4fcSRobert Mustacchi }
729d26e4fcSRobert Mustacchi
739d26e4fcSRobert Mustacchi iua = &i40e->i40e_uaddrs[i];
749d26e4fcSRobert Mustacchi ASSERT(i40e->i40e_resources.ifr_nmacfilt_used > 0);
759d26e4fcSRobert Mustacchi
769d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt));
779d26e4fcSRobert Mustacchi bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
789d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
799d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
809d26e4fcSRobert Mustacchi
819d26e4fcSRobert Mustacchi if (i40e_aq_remove_macvlan(hw, iua->iua_vsi, &filt, 1, NULL) !=
829d26e4fcSRobert Mustacchi I40E_SUCCESS) {
839d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to remove mac address "
846158afa4SDan McDonald "%02x:%02x:%02x:%02x:%02x:%02x from unicast filter: %d",
859d26e4fcSRobert Mustacchi mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
869d26e4fcSRobert Mustacchi mac_addr[4], mac_addr[5], filt.error_code);
879d26e4fcSRobert Mustacchi ret = EIO;
889d26e4fcSRobert Mustacchi goto done;
899d26e4fcSRobert Mustacchi }
909d26e4fcSRobert Mustacchi
919d26e4fcSRobert Mustacchi last = i40e->i40e_resources.ifr_nmacfilt_used - 1;
929d26e4fcSRobert Mustacchi if (i != last) {
939d26e4fcSRobert Mustacchi i40e_uaddr_t *src = &i40e->i40e_uaddrs[last];
949d26e4fcSRobert Mustacchi bcopy(src, iua, sizeof (i40e_uaddr_t));
959d26e4fcSRobert Mustacchi }
969d26e4fcSRobert Mustacchi
979d26e4fcSRobert Mustacchi /*
989d26e4fcSRobert Mustacchi * Set the multicast bit in the last one to indicate to ourselves that
999d26e4fcSRobert Mustacchi * it's invalid.
1009d26e4fcSRobert Mustacchi */
1019d26e4fcSRobert Mustacchi bzero(&i40e->i40e_uaddrs[last], sizeof (i40e_uaddr_t));
1029d26e4fcSRobert Mustacchi i40e->i40e_uaddrs[last].iua_mac[0] = 0x01;
1039d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt_used--;
1049d26e4fcSRobert Mustacchi ret = 0;
1059d26e4fcSRobert Mustacchi done:
1069d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
1079d26e4fcSRobert Mustacchi
1089d26e4fcSRobert Mustacchi return (ret);
1099d26e4fcSRobert Mustacchi }
1109d26e4fcSRobert Mustacchi
1119d26e4fcSRobert Mustacchi static int
i40e_group_add_mac(void * arg,const uint8_t * mac_addr)1129d26e4fcSRobert Mustacchi i40e_group_add_mac(void *arg, const uint8_t *mac_addr)
1139d26e4fcSRobert Mustacchi {
11409aee612SRyan Zezeski i40e_rx_group_t *rxg = arg;
11509aee612SRyan Zezeski i40e_t *i40e = rxg->irg_i40e;
11609aee612SRyan Zezeski struct i40e_hw *hw = &i40e->i40e_hw_space;
11709aee612SRyan Zezeski int i, ret;
11809aee612SRyan Zezeski i40e_uaddr_t *iua;
1199d26e4fcSRobert Mustacchi struct i40e_aqc_add_macvlan_element_data filt;
1209d26e4fcSRobert Mustacchi
1219d26e4fcSRobert Mustacchi if (I40E_IS_MULTICAST(mac_addr))
1229d26e4fcSRobert Mustacchi return (EINVAL);
1239d26e4fcSRobert Mustacchi
1249d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
1259d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) {
1269d26e4fcSRobert Mustacchi ret = ECANCELED;
1279d26e4fcSRobert Mustacchi goto done;
1289d26e4fcSRobert Mustacchi }
1299d26e4fcSRobert Mustacchi
1309d26e4fcSRobert Mustacchi if (i40e->i40e_resources.ifr_nmacfilt ==
1319d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt_used) {
1329d26e4fcSRobert Mustacchi ret = ENOSPC;
1339d26e4fcSRobert Mustacchi goto done;
1349d26e4fcSRobert Mustacchi }
1359d26e4fcSRobert Mustacchi
1369d26e4fcSRobert Mustacchi for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
1379d26e4fcSRobert Mustacchi if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
1389d26e4fcSRobert Mustacchi ETHERADDRL) == 0) {
1399d26e4fcSRobert Mustacchi ret = EEXIST;
1409d26e4fcSRobert Mustacchi goto done;
1419d26e4fcSRobert Mustacchi }
1429d26e4fcSRobert Mustacchi }
1439d26e4fcSRobert Mustacchi
1449d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt));
1459d26e4fcSRobert Mustacchi bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
1469d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH |
1479d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
1489d26e4fcSRobert Mustacchi
14909aee612SRyan Zezeski if ((ret = i40e_aq_add_macvlan(hw, rxg->irg_vsi_seid, &filt, 1,
1509d26e4fcSRobert Mustacchi NULL)) != I40E_SUCCESS) {
1519d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to add mac address "
1526158afa4SDan McDonald "%02x:%02x:%02x:%02x:%02x:%02x to unicast filter: %d",
1539d26e4fcSRobert Mustacchi mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
1549d26e4fcSRobert Mustacchi mac_addr[4], mac_addr[5], ret);
1559d26e4fcSRobert Mustacchi ret = EIO;
1569d26e4fcSRobert Mustacchi goto done;
1579d26e4fcSRobert Mustacchi }
1589d26e4fcSRobert Mustacchi
1599d26e4fcSRobert Mustacchi iua = &i40e->i40e_uaddrs[i40e->i40e_resources.ifr_nmacfilt_used];
1609d26e4fcSRobert Mustacchi bcopy(mac_addr, iua->iua_mac, ETHERADDRL);
16109aee612SRyan Zezeski iua->iua_vsi = rxg->irg_vsi_seid;
1629d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt_used++;
1639d26e4fcSRobert Mustacchi ASSERT(i40e->i40e_resources.ifr_nmacfilt_used <=
1649d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt);
1659d26e4fcSRobert Mustacchi ret = 0;
1669d26e4fcSRobert Mustacchi done:
1679d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
1689d26e4fcSRobert Mustacchi return (ret);
1699d26e4fcSRobert Mustacchi }
1709d26e4fcSRobert Mustacchi
1719d26e4fcSRobert Mustacchi static int
i40e_m_start(void * arg)1729d26e4fcSRobert Mustacchi i40e_m_start(void *arg)
1739d26e4fcSRobert Mustacchi {
1749d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
1759d26e4fcSRobert Mustacchi int rc = 0;
1769d26e4fcSRobert Mustacchi
1779d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
1789d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) {
1799d26e4fcSRobert Mustacchi rc = ECANCELED;
1809d26e4fcSRobert Mustacchi goto done;
1819d26e4fcSRobert Mustacchi }
1829d26e4fcSRobert Mustacchi
183aa2a44afSPaul Winder if (!i40e_start(i40e)) {
1849d26e4fcSRobert Mustacchi rc = EIO;
1859d26e4fcSRobert Mustacchi goto done;
1869d26e4fcSRobert Mustacchi }
1879d26e4fcSRobert Mustacchi
1889d26e4fcSRobert Mustacchi atomic_or_32(&i40e->i40e_state, I40E_STARTED);
1899d26e4fcSRobert Mustacchi done:
1909d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
1919d26e4fcSRobert Mustacchi
1929d26e4fcSRobert Mustacchi return (rc);
1939d26e4fcSRobert Mustacchi }
1949d26e4fcSRobert Mustacchi
1959d26e4fcSRobert Mustacchi static void
i40e_m_stop(void * arg)1969d26e4fcSRobert Mustacchi i40e_m_stop(void *arg)
1979d26e4fcSRobert Mustacchi {
1989d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
1999d26e4fcSRobert Mustacchi
2009d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
2019d26e4fcSRobert Mustacchi
2029d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED)
2039d26e4fcSRobert Mustacchi goto done;
2049d26e4fcSRobert Mustacchi
2059d26e4fcSRobert Mustacchi atomic_and_32(&i40e->i40e_state, ~I40E_STARTED);
206aa2a44afSPaul Winder i40e_stop(i40e);
2079d26e4fcSRobert Mustacchi done:
2089d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
2099d26e4fcSRobert Mustacchi }
2109d26e4fcSRobert Mustacchi
2119d26e4fcSRobert Mustacchi /*
2129d26e4fcSRobert Mustacchi * Enable and disable promiscuous mode as requested. We have to toggle both
2139d26e4fcSRobert Mustacchi * unicast and multicast. Note that multicast may already be enabled due to the
2149d26e4fcSRobert Mustacchi * i40e_m_multicast may toggle it itself. See i40e_main.c for more information
2159d26e4fcSRobert Mustacchi * on this.
2169d26e4fcSRobert Mustacchi */
2179d26e4fcSRobert Mustacchi static int
i40e_m_promisc(void * arg,boolean_t on)2189d26e4fcSRobert Mustacchi i40e_m_promisc(void *arg, boolean_t on)
2199d26e4fcSRobert Mustacchi {
2209d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
2219d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space;
2229d26e4fcSRobert Mustacchi int ret = 0, err = 0;
2239d26e4fcSRobert Mustacchi
2249d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
2259d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) {
2269d26e4fcSRobert Mustacchi ret = ECANCELED;
2279d26e4fcSRobert Mustacchi goto done;
2289d26e4fcSRobert Mustacchi }
2299d26e4fcSRobert Mustacchi
2309d26e4fcSRobert Mustacchi
23109aee612SRyan Zezeski ret = i40e_aq_set_vsi_unicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
2323d75a287SRobert Mustacchi on, NULL, B_FALSE);
2339d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) {
2349d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to %s unicast promiscuity on "
2359d26e4fcSRobert Mustacchi "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
2369d26e4fcSRobert Mustacchi ret);
2379d26e4fcSRobert Mustacchi err = EIO;
2389d26e4fcSRobert Mustacchi goto done;
2399d26e4fcSRobert Mustacchi }
2409d26e4fcSRobert Mustacchi
2419d26e4fcSRobert Mustacchi /*
2429d26e4fcSRobert Mustacchi * If we have a non-zero mcast_promisc_count, then it has already been
2439d26e4fcSRobert Mustacchi * enabled or we need to leave it that way and not touch it.
2449d26e4fcSRobert Mustacchi */
2459d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count > 0) {
2469d26e4fcSRobert Mustacchi i40e->i40e_promisc_on = on;
2479d26e4fcSRobert Mustacchi goto done;
2489d26e4fcSRobert Mustacchi }
2499d26e4fcSRobert Mustacchi
25009aee612SRyan Zezeski ret = i40e_aq_set_vsi_multicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
2519d26e4fcSRobert Mustacchi on, NULL);
2529d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) {
2539d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to %s multicast promiscuity on "
2549d26e4fcSRobert Mustacchi "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
2559d26e4fcSRobert Mustacchi ret);
2569d26e4fcSRobert Mustacchi
2579d26e4fcSRobert Mustacchi /*
2589d26e4fcSRobert Mustacchi * Try our best to put us back into a state that MAC expects us
2599d26e4fcSRobert Mustacchi * to be in.
2609d26e4fcSRobert Mustacchi */
26109aee612SRyan Zezeski ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
26209aee612SRyan Zezeski I40E_DEF_VSI_SEID(i40e), !on, NULL, B_FALSE);
2639d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) {
2649d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to %s unicast promiscuity on "
2659d26e4fcSRobert Mustacchi "the default VSI after toggling multicast failed: "
2669d26e4fcSRobert Mustacchi "%d", on == B_TRUE ? "disable" : "enable", ret);
2679d26e4fcSRobert Mustacchi }
2689d26e4fcSRobert Mustacchi
2699d26e4fcSRobert Mustacchi err = EIO;
2709d26e4fcSRobert Mustacchi goto done;
2719d26e4fcSRobert Mustacchi } else {
2729d26e4fcSRobert Mustacchi i40e->i40e_promisc_on = on;
2739d26e4fcSRobert Mustacchi }
2749d26e4fcSRobert Mustacchi
2759d26e4fcSRobert Mustacchi done:
2769d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
2779d26e4fcSRobert Mustacchi return (err);
2789d26e4fcSRobert Mustacchi }
2799d26e4fcSRobert Mustacchi
2809d26e4fcSRobert Mustacchi /*
2819d26e4fcSRobert Mustacchi * See the big theory statement in i40e_main.c for multicast address management.
2829d26e4fcSRobert Mustacchi */
2839d26e4fcSRobert Mustacchi static int
i40e_multicast_add(i40e_t * i40e,const uint8_t * multicast_address)2849d26e4fcSRobert Mustacchi i40e_multicast_add(i40e_t *i40e, const uint8_t *multicast_address)
2859d26e4fcSRobert Mustacchi {
2869d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space;
2879d26e4fcSRobert Mustacchi struct i40e_aqc_add_macvlan_element_data filt;
2889d26e4fcSRobert Mustacchi i40e_maddr_t *mc;
2899d26e4fcSRobert Mustacchi int ret;
2909d26e4fcSRobert Mustacchi
2919d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
2929d26e4fcSRobert Mustacchi
2939d26e4fcSRobert Mustacchi if (i40e->i40e_resources.ifr_nmcastfilt_used ==
2949d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmcastfilt) {
2959d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count == 0 &&
2969d26e4fcSRobert Mustacchi i40e->i40e_promisc_on == B_FALSE) {
2979d26e4fcSRobert Mustacchi ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
29809aee612SRyan Zezeski I40E_DEF_VSI_SEID(i40e), B_TRUE, NULL);
2999d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) {
3009d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to enable multicast "
3019d26e4fcSRobert Mustacchi "promiscuous mode on VSI %d: %d",
30209aee612SRyan Zezeski I40E_DEF_VSI_SEID(i40e), ret);
3039d26e4fcSRobert Mustacchi return (EIO);
3049d26e4fcSRobert Mustacchi }
3059d26e4fcSRobert Mustacchi }
3069d26e4fcSRobert Mustacchi i40e->i40e_mcast_promisc_count++;
3079d26e4fcSRobert Mustacchi return (0);
3089d26e4fcSRobert Mustacchi }
3099d26e4fcSRobert Mustacchi
3109d26e4fcSRobert Mustacchi mc = &i40e->i40e_maddrs[i40e->i40e_resources.ifr_nmcastfilt_used];
3119d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt));
3129d26e4fcSRobert Mustacchi bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
3139d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH |
3149d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
3159d26e4fcSRobert Mustacchi
31609aee612SRyan Zezeski if ((ret = i40e_aq_add_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt, 1,
3179d26e4fcSRobert Mustacchi NULL)) != I40E_SUCCESS) {
3189d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to add mac address "
3196158afa4SDan McDonald "%02x:%02x:%02x:%02x:%02x:%02x to multicast filter: %d",
3209d26e4fcSRobert Mustacchi multicast_address[0], multicast_address[1],
3219d26e4fcSRobert Mustacchi multicast_address[2], multicast_address[3],
3229d26e4fcSRobert Mustacchi multicast_address[4], multicast_address[5],
3239d26e4fcSRobert Mustacchi ret);
3249d26e4fcSRobert Mustacchi return (EIO);
3259d26e4fcSRobert Mustacchi }
3269d26e4fcSRobert Mustacchi
3279d26e4fcSRobert Mustacchi bcopy(multicast_address, mc->ima_mac, ETHERADDRL);
3289d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmcastfilt_used++;
3299d26e4fcSRobert Mustacchi return (0);
3309d26e4fcSRobert Mustacchi }
3319d26e4fcSRobert Mustacchi
3329d26e4fcSRobert Mustacchi /*
3339d26e4fcSRobert Mustacchi * See the big theory statement in i40e_main.c for multicast address management.
3349d26e4fcSRobert Mustacchi */
3359d26e4fcSRobert Mustacchi static int
i40e_multicast_remove(i40e_t * i40e,const uint8_t * multicast_address)3369d26e4fcSRobert Mustacchi i40e_multicast_remove(i40e_t *i40e, const uint8_t *multicast_address)
3379d26e4fcSRobert Mustacchi {
3389d26e4fcSRobert Mustacchi int i, ret;
3399d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space;
3409d26e4fcSRobert Mustacchi
3419d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
3429d26e4fcSRobert Mustacchi
3439d26e4fcSRobert Mustacchi for (i = 0; i < i40e->i40e_resources.ifr_nmcastfilt_used; i++) {
3449d26e4fcSRobert Mustacchi struct i40e_aqc_remove_macvlan_element_data filt;
3459d26e4fcSRobert Mustacchi int last;
3469d26e4fcSRobert Mustacchi
3479d26e4fcSRobert Mustacchi if (bcmp(multicast_address, i40e->i40e_maddrs[i].ima_mac,
3489d26e4fcSRobert Mustacchi ETHERADDRL) != 0) {
3499d26e4fcSRobert Mustacchi continue;
3509d26e4fcSRobert Mustacchi }
3519d26e4fcSRobert Mustacchi
3529d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt));
3539d26e4fcSRobert Mustacchi bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
3549d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH |
3559d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
3569d26e4fcSRobert Mustacchi
35709aee612SRyan Zezeski if (i40e_aq_remove_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt,
35809aee612SRyan Zezeski 1, NULL) != I40E_SUCCESS) {
3599d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to remove mac address "
3606158afa4SDan McDonald "%02x:%02x:%02x:%02x:%02x:%02x from multicast "
3619d26e4fcSRobert Mustacchi "filter: %d",
3629d26e4fcSRobert Mustacchi multicast_address[0], multicast_address[1],
3639d26e4fcSRobert Mustacchi multicast_address[2], multicast_address[3],
3649d26e4fcSRobert Mustacchi multicast_address[4], multicast_address[5],
3659d26e4fcSRobert Mustacchi filt.error_code);
3669d26e4fcSRobert Mustacchi return (EIO);
3679d26e4fcSRobert Mustacchi }
3689d26e4fcSRobert Mustacchi
3699d26e4fcSRobert Mustacchi last = i40e->i40e_resources.ifr_nmcastfilt_used - 1;
3709d26e4fcSRobert Mustacchi if (i != last) {
3719d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_maddrs[last], &i40e->i40e_maddrs[i],
3729d26e4fcSRobert Mustacchi sizeof (i40e_maddr_t));
3739d26e4fcSRobert Mustacchi bzero(&i40e->i40e_maddrs[last], sizeof (i40e_maddr_t));
3749d26e4fcSRobert Mustacchi }
3759d26e4fcSRobert Mustacchi
3769d26e4fcSRobert Mustacchi ASSERT(i40e->i40e_resources.ifr_nmcastfilt_used > 0);
3779d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmcastfilt_used--;
3789d26e4fcSRobert Mustacchi return (0);
3799d26e4fcSRobert Mustacchi }
3809d26e4fcSRobert Mustacchi
3819d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count > 0) {
3829d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count == 1 &&
3839d26e4fcSRobert Mustacchi i40e->i40e_promisc_on == B_FALSE) {
3849d26e4fcSRobert Mustacchi ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
38509aee612SRyan Zezeski I40E_DEF_VSI_SEID(i40e), B_FALSE, NULL);
3869d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) {
3879d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to disable "
3889d26e4fcSRobert Mustacchi "multicast promiscuous mode on VSI %d: %d",
38909aee612SRyan Zezeski I40E_DEF_VSI_SEID(i40e), ret);
3909d26e4fcSRobert Mustacchi return (EIO);
3919d26e4fcSRobert Mustacchi }
3929d26e4fcSRobert Mustacchi }
3939d26e4fcSRobert Mustacchi i40e->i40e_mcast_promisc_count--;
3949d26e4fcSRobert Mustacchi
3959d26e4fcSRobert Mustacchi return (0);
3969d26e4fcSRobert Mustacchi }
3979d26e4fcSRobert Mustacchi
3989d26e4fcSRobert Mustacchi return (ENOENT);
3999d26e4fcSRobert Mustacchi }
4009d26e4fcSRobert Mustacchi
4019d26e4fcSRobert Mustacchi static int
i40e_m_multicast(void * arg,boolean_t add,const uint8_t * multicast_address)4029d26e4fcSRobert Mustacchi i40e_m_multicast(void *arg, boolean_t add, const uint8_t *multicast_address)
4039d26e4fcSRobert Mustacchi {
4049d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
4059d26e4fcSRobert Mustacchi int rc;
4069d26e4fcSRobert Mustacchi
4079d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
4089d26e4fcSRobert Mustacchi
4099d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) {
4109d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
4119d26e4fcSRobert Mustacchi return (ECANCELED);
4129d26e4fcSRobert Mustacchi }
4139d26e4fcSRobert Mustacchi
4149d26e4fcSRobert Mustacchi if (add == B_TRUE) {
4159d26e4fcSRobert Mustacchi rc = i40e_multicast_add(i40e, multicast_address);
4169d26e4fcSRobert Mustacchi } else {
4179d26e4fcSRobert Mustacchi rc = i40e_multicast_remove(i40e, multicast_address);
4189d26e4fcSRobert Mustacchi }
4199d26e4fcSRobert Mustacchi
4209d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
4219d26e4fcSRobert Mustacchi return (rc);
4229d26e4fcSRobert Mustacchi }
4239d26e4fcSRobert Mustacchi
4249d26e4fcSRobert Mustacchi /* ARGSUSED */
4259d26e4fcSRobert Mustacchi static void
i40e_m_ioctl(void * arg,queue_t * q,mblk_t * mp)4269d26e4fcSRobert Mustacchi i40e_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
4279d26e4fcSRobert Mustacchi {
4289d26e4fcSRobert Mustacchi /*
4299d26e4fcSRobert Mustacchi * At this time, we don't support toggling i40e into loopback mode. It's
4309d26e4fcSRobert Mustacchi * questionable how much value this has when there's no clear way to
4319d26e4fcSRobert Mustacchi * toggle this behavior from a supported way in userland.
4329d26e4fcSRobert Mustacchi */
4339d26e4fcSRobert Mustacchi miocnak(q, mp, 0, EINVAL);
4349d26e4fcSRobert Mustacchi }
4359d26e4fcSRobert Mustacchi
4369d26e4fcSRobert Mustacchi static int
i40e_ring_start(mac_ring_driver_t rh,uint64_t gen_num)4379d26e4fcSRobert Mustacchi i40e_ring_start(mac_ring_driver_t rh, uint64_t gen_num)
4389d26e4fcSRobert Mustacchi {
4399d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = (i40e_trqpair_t *)rh;
440aa2a44afSPaul Winder int rv;
441aa2a44afSPaul Winder
442aa2a44afSPaul Winder if ((rv = i40e_setup_ring(itrq)) != 0)
443aa2a44afSPaul Winder return (rv);
4449d26e4fcSRobert Mustacchi
4459d26e4fcSRobert Mustacchi /*
4469d26e4fcSRobert Mustacchi * GLDv3 requires we keep track of a generation number, as it uses
4479d26e4fcSRobert Mustacchi * that number to keep track of whether or not a ring is active.
4489d26e4fcSRobert Mustacchi */
4499d26e4fcSRobert Mustacchi mutex_enter(&itrq->itrq_rx_lock);
4509d26e4fcSRobert Mustacchi itrq->itrq_rxgen = gen_num;
4519d26e4fcSRobert Mustacchi mutex_exit(&itrq->itrq_rx_lock);
4529d26e4fcSRobert Mustacchi return (0);
4539d26e4fcSRobert Mustacchi }
4549d26e4fcSRobert Mustacchi
455aa2a44afSPaul Winder static void
i40e_ring_stop(mac_ring_driver_t rh)456aa2a44afSPaul Winder i40e_ring_stop(mac_ring_driver_t rh)
457aa2a44afSPaul Winder {
458aa2a44afSPaul Winder i40e_trqpair_t *itrq = (i40e_trqpair_t *)rh;
459aa2a44afSPaul Winder
460aa2a44afSPaul Winder if (!i40e_shutdown_ring(itrq)) {
461aa2a44afSPaul Winder i40e_t *i40e = itrq->itrq_i40e;
462aa2a44afSPaul Winder
463aa2a44afSPaul Winder ddi_fm_service_impact(i40e->i40e_dip, DDI_SERVICE_LOST);
464aa2a44afSPaul Winder i40e_error(i40e, "Failed to stop ring %u", itrq->itrq_index);
465aa2a44afSPaul Winder }
466aa2a44afSPaul Winder }
467aa2a44afSPaul Winder
4689d26e4fcSRobert Mustacchi /* ARGSUSED */
4699d26e4fcSRobert Mustacchi static int
i40e_rx_ring_intr_enable(mac_intr_handle_t intrh)4709d26e4fcSRobert Mustacchi i40e_rx_ring_intr_enable(mac_intr_handle_t intrh)
4719d26e4fcSRobert Mustacchi {
4729d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
4739d26e4fcSRobert Mustacchi
474396505afSPaul Winder mutex_enter(&itrq->itrq_rx_lock);
475396505afSPaul Winder ASSERT(itrq->itrq_intr_poll == B_TRUE);
476338749cbSRobert Mustacchi i40e_intr_rx_queue_enable(itrq);
477396505afSPaul Winder itrq->itrq_intr_poll = B_FALSE;
478396505afSPaul Winder mutex_exit(&itrq->itrq_rx_lock);
4799d26e4fcSRobert Mustacchi
4809d26e4fcSRobert Mustacchi return (0);
4819d26e4fcSRobert Mustacchi }
4829d26e4fcSRobert Mustacchi
4839d26e4fcSRobert Mustacchi /* ARGSUSED */
4849d26e4fcSRobert Mustacchi static int
i40e_rx_ring_intr_disable(mac_intr_handle_t intrh)4859d26e4fcSRobert Mustacchi i40e_rx_ring_intr_disable(mac_intr_handle_t intrh)
4869d26e4fcSRobert Mustacchi {
4879d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
4889d26e4fcSRobert Mustacchi
489396505afSPaul Winder mutex_enter(&itrq->itrq_rx_lock);
490338749cbSRobert Mustacchi i40e_intr_rx_queue_disable(itrq);
491396505afSPaul Winder itrq->itrq_intr_poll = B_TRUE;
492396505afSPaul Winder mutex_exit(&itrq->itrq_rx_lock);
4939d26e4fcSRobert Mustacchi
4949d26e4fcSRobert Mustacchi return (0);
4959d26e4fcSRobert Mustacchi }
4969d26e4fcSRobert Mustacchi
4979d26e4fcSRobert Mustacchi /* ARGSUSED */
4989d26e4fcSRobert Mustacchi static void
i40e_fill_tx_ring(void * arg,mac_ring_type_t rtype,const int group_index,const int ring_index,mac_ring_info_t * infop,mac_ring_handle_t rh)4999d26e4fcSRobert Mustacchi i40e_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
5009d26e4fcSRobert Mustacchi const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
5019d26e4fcSRobert Mustacchi {
5029d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
5039d26e4fcSRobert Mustacchi mac_intr_t *mintr = &infop->mri_intr;
5049d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = &(i40e->i40e_trqpairs[ring_index]);
5059d26e4fcSRobert Mustacchi
5069d26e4fcSRobert Mustacchi /*
5079d26e4fcSRobert Mustacchi * Note the group index here is expected to be -1 due to the fact that
5089d26e4fcSRobert Mustacchi * we're not actually grouping things tx-wise at this time.
5099d26e4fcSRobert Mustacchi */
5109d26e4fcSRobert Mustacchi ASSERT(group_index == -1);
51109aee612SRyan Zezeski ASSERT(ring_index < i40e->i40e_num_trqpairs_per_vsi);
5129d26e4fcSRobert Mustacchi
5139d26e4fcSRobert Mustacchi itrq->itrq_mactxring = rh;
5149d26e4fcSRobert Mustacchi infop->mri_driver = (mac_ring_driver_t)itrq;
5159d26e4fcSRobert Mustacchi infop->mri_start = NULL;
5169d26e4fcSRobert Mustacchi infop->mri_stop = NULL;
5179d26e4fcSRobert Mustacchi infop->mri_tx = i40e_ring_tx;
5189d26e4fcSRobert Mustacchi infop->mri_stat = i40e_tx_ring_stat;
5199d26e4fcSRobert Mustacchi
5209d26e4fcSRobert Mustacchi /*
5219d26e4fcSRobert Mustacchi * We only provide the handle in cases where we have MSI-X interrupts,
5229d26e4fcSRobert Mustacchi * to indicate that we'd actually support retargetting.
5239d26e4fcSRobert Mustacchi */
5249d26e4fcSRobert Mustacchi if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
5259d26e4fcSRobert Mustacchi mintr->mi_ddi_handle =
5269d26e4fcSRobert Mustacchi i40e->i40e_intr_handles[itrq->itrq_tx_intrvec];
5279d26e4fcSRobert Mustacchi }
5289d26e4fcSRobert Mustacchi }
5299d26e4fcSRobert Mustacchi
5309d26e4fcSRobert Mustacchi /* ARGSUSED */
5319d26e4fcSRobert Mustacchi static void
i40e_fill_rx_ring(void * arg,mac_ring_type_t rtype,const int group_index,const int ring_index,mac_ring_info_t * infop,mac_ring_handle_t rh)5329d26e4fcSRobert Mustacchi i40e_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
5339d26e4fcSRobert Mustacchi const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
5349d26e4fcSRobert Mustacchi {
5359d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
5369d26e4fcSRobert Mustacchi mac_intr_t *mintr = &infop->mri_intr;
53709aee612SRyan Zezeski uint_t trqpair_index;
53809aee612SRyan Zezeski i40e_trqpair_t *itrq;
5399d26e4fcSRobert Mustacchi
54009aee612SRyan Zezeski /* This assumes static groups. */
54109aee612SRyan Zezeski ASSERT3S(group_index, >=, 0);
54209aee612SRyan Zezeski ASSERT3S(ring_index, >=, 0);
54309aee612SRyan Zezeski trqpair_index = (group_index * i40e->i40e_num_trqpairs_per_vsi) +
54409aee612SRyan Zezeski ring_index;
54509aee612SRyan Zezeski ASSERT3U(trqpair_index, <, i40e->i40e_num_trqpairs);
54609aee612SRyan Zezeski itrq = &i40e->i40e_trqpairs[trqpair_index];
5479d26e4fcSRobert Mustacchi
5489d26e4fcSRobert Mustacchi itrq->itrq_macrxring = rh;
5499d26e4fcSRobert Mustacchi infop->mri_driver = (mac_ring_driver_t)itrq;
5509d26e4fcSRobert Mustacchi infop->mri_start = i40e_ring_start;
551aa2a44afSPaul Winder infop->mri_stop = i40e_ring_stop;
5529d26e4fcSRobert Mustacchi infop->mri_poll = i40e_ring_rx_poll;
5539d26e4fcSRobert Mustacchi infop->mri_stat = i40e_rx_ring_stat;
5549d26e4fcSRobert Mustacchi mintr->mi_handle = (mac_intr_handle_t)itrq;
5559d26e4fcSRobert Mustacchi mintr->mi_enable = i40e_rx_ring_intr_enable;
5569d26e4fcSRobert Mustacchi mintr->mi_disable = i40e_rx_ring_intr_disable;
5579d26e4fcSRobert Mustacchi
5589d26e4fcSRobert Mustacchi /*
5599d26e4fcSRobert Mustacchi * We only provide the handle in cases where we have MSI-X interrupts,
5609d26e4fcSRobert Mustacchi * to indicate that we'd actually support retargetting.
5619d26e4fcSRobert Mustacchi */
5629d26e4fcSRobert Mustacchi if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
5639d26e4fcSRobert Mustacchi mintr->mi_ddi_handle =
5649d26e4fcSRobert Mustacchi i40e->i40e_intr_handles[itrq->itrq_rx_intrvec];
5659d26e4fcSRobert Mustacchi }
5669d26e4fcSRobert Mustacchi }
5679d26e4fcSRobert Mustacchi
5689d26e4fcSRobert Mustacchi /* ARGSUSED */
5699d26e4fcSRobert Mustacchi static void
i40e_fill_rx_group(void * arg,mac_ring_type_t rtype,const int index,mac_group_info_t * infop,mac_group_handle_t gh)5709d26e4fcSRobert Mustacchi i40e_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index,
5719d26e4fcSRobert Mustacchi mac_group_info_t *infop, mac_group_handle_t gh)
5729d26e4fcSRobert Mustacchi {
5739d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
57409aee612SRyan Zezeski i40e_rx_group_t *rxg;
5759d26e4fcSRobert Mustacchi
5769d26e4fcSRobert Mustacchi if (rtype != MAC_RING_TYPE_RX)
5779d26e4fcSRobert Mustacchi return;
5789d26e4fcSRobert Mustacchi
57909aee612SRyan Zezeski rxg = &i40e->i40e_rx_groups[index];
58009aee612SRyan Zezeski rxg->irg_grp_hdl = gh;
58109aee612SRyan Zezeski
58209aee612SRyan Zezeski infop->mgi_driver = (mac_group_driver_t)rxg;
5839d26e4fcSRobert Mustacchi infop->mgi_start = NULL;
5849d26e4fcSRobert Mustacchi infop->mgi_stop = NULL;
5859d26e4fcSRobert Mustacchi infop->mgi_addmac = i40e_group_add_mac;
5869d26e4fcSRobert Mustacchi infop->mgi_remmac = i40e_group_remove_mac;
5879d26e4fcSRobert Mustacchi
58888628b1bSRyan Zezeski ASSERT3U(i40e->i40e_num_rx_groups, <=, I40E_MAX_NUM_RX_GROUPS);
58909aee612SRyan Zezeski infop->mgi_count = i40e->i40e_num_trqpairs_per_vsi;
5909d26e4fcSRobert Mustacchi }
5919d26e4fcSRobert Mustacchi
59245d3dd98SRobert Mustacchi static int
i40e_transceiver_info(void * arg,uint_t id,mac_transceiver_info_t * infop)59345d3dd98SRobert Mustacchi i40e_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
59445d3dd98SRobert Mustacchi {
59545d3dd98SRobert Mustacchi boolean_t present, usable;
59645d3dd98SRobert Mustacchi i40e_t *i40e = arg;
59745d3dd98SRobert Mustacchi
59845d3dd98SRobert Mustacchi if (id != 0 || infop == NULL)
59945d3dd98SRobert Mustacchi return (EINVAL);
60045d3dd98SRobert Mustacchi
60145d3dd98SRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
602286d309cSRobert Mustacchi switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
603286d309cSRobert Mustacchi case I40E_MODULE_TYPE_SFP:
604286d309cSRobert Mustacchi case I40E_MODULE_TYPE_QSFP:
605286d309cSRobert Mustacchi break;
606286d309cSRobert Mustacchi default:
607286d309cSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
608286d309cSRobert Mustacchi return (ENOTSUP);
609286d309cSRobert Mustacchi }
610286d309cSRobert Mustacchi
61145d3dd98SRobert Mustacchi present = !!(i40e->i40e_hw_space.phy.link_info.link_info &
61245d3dd98SRobert Mustacchi I40E_AQ_MEDIA_AVAILABLE);
61345d3dd98SRobert Mustacchi if (present) {
61445d3dd98SRobert Mustacchi usable = !!(i40e->i40e_hw_space.phy.link_info.an_info &
61545d3dd98SRobert Mustacchi I40E_AQ_QUALIFIED_MODULE);
61645d3dd98SRobert Mustacchi } else {
61745d3dd98SRobert Mustacchi usable = B_FALSE;
61845d3dd98SRobert Mustacchi }
61945d3dd98SRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
62045d3dd98SRobert Mustacchi
62145d3dd98SRobert Mustacchi mac_transceiver_info_set_usable(infop, usable);
62245d3dd98SRobert Mustacchi mac_transceiver_info_set_present(infop, present);
62345d3dd98SRobert Mustacchi
62445d3dd98SRobert Mustacchi return (0);
62545d3dd98SRobert Mustacchi }
62645d3dd98SRobert Mustacchi
627286d309cSRobert Mustacchi static int
i40e_transceiver_read(void * arg,uint_t id,uint_t page,void * buf,size_t nbytes,off_t offset,size_t * nread)628286d309cSRobert Mustacchi i40e_transceiver_read(void *arg, uint_t id, uint_t page, void *buf,
629286d309cSRobert Mustacchi size_t nbytes, off_t offset, size_t *nread)
630286d309cSRobert Mustacchi {
631286d309cSRobert Mustacchi i40e_t *i40e = arg;
632286d309cSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space;
633286d309cSRobert Mustacchi uint8_t *buf8 = buf;
634286d309cSRobert Mustacchi size_t i;
635286d309cSRobert Mustacchi
636286d309cSRobert Mustacchi if (id != 0 || buf == NULL || nbytes == 0 || nread == NULL ||
637286d309cSRobert Mustacchi (page != 0xa0 && page != 0xa2) || offset < 0)
638286d309cSRobert Mustacchi return (EINVAL);
639286d309cSRobert Mustacchi
640286d309cSRobert Mustacchi /*
641286d309cSRobert Mustacchi * Both supported pages have a length of 256 bytes, ensure nothing asks
642286d309cSRobert Mustacchi * us to go beyond that.
643286d309cSRobert Mustacchi */
644286d309cSRobert Mustacchi if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
645286d309cSRobert Mustacchi return (EINVAL);
646286d309cSRobert Mustacchi }
647286d309cSRobert Mustacchi
648286d309cSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
649286d309cSRobert Mustacchi switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
650286d309cSRobert Mustacchi case I40E_MODULE_TYPE_SFP:
651286d309cSRobert Mustacchi case I40E_MODULE_TYPE_QSFP:
652286d309cSRobert Mustacchi break;
653286d309cSRobert Mustacchi default:
654286d309cSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
655286d309cSRobert Mustacchi return (ENOTSUP);
656286d309cSRobert Mustacchi }
657286d309cSRobert Mustacchi
658286d309cSRobert Mustacchi /*
659286d309cSRobert Mustacchi * Make sure we have a sufficiently new firmware version to run this
660286d309cSRobert Mustacchi * command. This was introduced in firmware API 1.7. This is apparently
661286d309cSRobert Mustacchi * only supported on the XL710 MAC, not the XL722.
662286d309cSRobert Mustacchi */
663286d309cSRobert Mustacchi if (hw->mac.type != I40E_MAC_XL710 || hw->aq.api_maj_ver != 1 ||
664286d309cSRobert Mustacchi hw->aq.api_min_ver < 7) {
665286d309cSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
666286d309cSRobert Mustacchi return (ENOTSUP);
667286d309cSRobert Mustacchi }
668286d309cSRobert Mustacchi
669286d309cSRobert Mustacchi for (i = 0; i < nbytes; i++, offset++) {
670286d309cSRobert Mustacchi enum i40e_status_code status;
671286d309cSRobert Mustacchi uint32_t val;
672286d309cSRobert Mustacchi
673286d309cSRobert Mustacchi status = i40e_aq_get_phy_register(hw,
674df36e06dSRobert Mustacchi I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, page, TRUE, offset,
675286d309cSRobert Mustacchi &val, NULL);
676286d309cSRobert Mustacchi if (status != I40E_SUCCESS) {
677286d309cSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
678286d309cSRobert Mustacchi return (EIO);
679286d309cSRobert Mustacchi }
680286d309cSRobert Mustacchi
681286d309cSRobert Mustacchi buf8[i] = (uint8_t)val;
682286d309cSRobert Mustacchi }
683286d309cSRobert Mustacchi
684286d309cSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
685286d309cSRobert Mustacchi *nread = nbytes;
686286d309cSRobert Mustacchi
687286d309cSRobert Mustacchi return (0);
688286d309cSRobert Mustacchi }
689286d309cSRobert Mustacchi
690c1e9c696SRobert Mustacchi static int
i40e_gld_led_set(void * arg,mac_led_mode_t mode,uint_t flags)691c1e9c696SRobert Mustacchi i40e_gld_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
692c1e9c696SRobert Mustacchi {
693c1e9c696SRobert Mustacchi i40e_t *i40e = arg;
694c1e9c696SRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space;
695c1e9c696SRobert Mustacchi
696c1e9c696SRobert Mustacchi if (flags != 0)
697c1e9c696SRobert Mustacchi return (EINVAL);
698c1e9c696SRobert Mustacchi
699c1e9c696SRobert Mustacchi if (mode != MAC_LED_DEFAULT &&
700c1e9c696SRobert Mustacchi mode != MAC_LED_IDENT &&
701c1e9c696SRobert Mustacchi mode != MAC_LED_OFF &&
702c1e9c696SRobert Mustacchi mode != MAC_LED_ON)
703c1e9c696SRobert Mustacchi return (ENOTSUP);
704c1e9c696SRobert Mustacchi
705c1e9c696SRobert Mustacchi if (mode != MAC_LED_DEFAULT && !i40e->i40e_led_saved) {
706c1e9c696SRobert Mustacchi i40e->i40e_led_status = i40e_led_get(hw);
707c1e9c696SRobert Mustacchi i40e->i40e_led_saved = B_TRUE;
708c1e9c696SRobert Mustacchi }
709c1e9c696SRobert Mustacchi
710c1e9c696SRobert Mustacchi switch (mode) {
711c1e9c696SRobert Mustacchi case MAC_LED_DEFAULT:
712c1e9c696SRobert Mustacchi if (i40e->i40e_led_saved) {
713c1e9c696SRobert Mustacchi i40e_led_set(hw, i40e->i40e_led_status, B_FALSE);
714c1e9c696SRobert Mustacchi i40e->i40e_led_status = 0;
715c1e9c696SRobert Mustacchi i40e->i40e_led_saved = B_FALSE;
716c1e9c696SRobert Mustacchi }
717c1e9c696SRobert Mustacchi break;
718c1e9c696SRobert Mustacchi case MAC_LED_IDENT:
719c1e9c696SRobert Mustacchi i40e_led_set(hw, 0xf, B_TRUE);
720c1e9c696SRobert Mustacchi break;
721c1e9c696SRobert Mustacchi case MAC_LED_OFF:
722c1e9c696SRobert Mustacchi i40e_led_set(hw, 0x0, B_FALSE);
723c1e9c696SRobert Mustacchi break;
724c1e9c696SRobert Mustacchi case MAC_LED_ON:
725c1e9c696SRobert Mustacchi i40e_led_set(hw, 0xf, B_FALSE);
726c1e9c696SRobert Mustacchi break;
727c1e9c696SRobert Mustacchi default:
728c1e9c696SRobert Mustacchi return (ENOTSUP);
729c1e9c696SRobert Mustacchi }
730c1e9c696SRobert Mustacchi
731c1e9c696SRobert Mustacchi return (0);
732c1e9c696SRobert Mustacchi }
733c1e9c696SRobert Mustacchi
7349d26e4fcSRobert Mustacchi static boolean_t
i40e_m_getcapab(void * arg,mac_capab_t cap,void * cap_data)7359d26e4fcSRobert Mustacchi i40e_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
7369d26e4fcSRobert Mustacchi {
7379d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
7389d26e4fcSRobert Mustacchi mac_capab_rings_t *cap_rings;
73945d3dd98SRobert Mustacchi mac_capab_transceiver_t *mct;
740c1e9c696SRobert Mustacchi mac_capab_led_t *mcl;
7419d26e4fcSRobert Mustacchi
7429d26e4fcSRobert Mustacchi switch (cap) {
7439d26e4fcSRobert Mustacchi case MAC_CAPAB_HCKSUM: {
7449d26e4fcSRobert Mustacchi uint32_t *txflags = cap_data;
7459d26e4fcSRobert Mustacchi
7469d26e4fcSRobert Mustacchi *txflags = 0;
7479d26e4fcSRobert Mustacchi if (i40e->i40e_tx_hcksum_enable == B_TRUE)
7489d26e4fcSRobert Mustacchi *txflags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
7499d26e4fcSRobert Mustacchi break;
7509d26e4fcSRobert Mustacchi }
7519d26e4fcSRobert Mustacchi
75209aee612SRyan Zezeski case MAC_CAPAB_LSO: {
75309aee612SRyan Zezeski mac_capab_lso_t *cap_lso = cap_data;
75409aee612SRyan Zezeski
75509aee612SRyan Zezeski if (i40e->i40e_tx_lso_enable == B_TRUE) {
75685f496faSRobert Mustacchi cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
75785f496faSRobert Mustacchi LSO_TX_BASIC_TCP_IPV6;
75809aee612SRyan Zezeski cap_lso->lso_basic_tcp_ipv4.lso_max = I40E_LSO_MAXLEN;
75985f496faSRobert Mustacchi cap_lso->lso_basic_tcp_ipv6.lso_max = I40E_LSO_MAXLEN;
76009aee612SRyan Zezeski } else {
76109aee612SRyan Zezeski return (B_FALSE);
76209aee612SRyan Zezeski }
76309aee612SRyan Zezeski break;
76409aee612SRyan Zezeski }
76509aee612SRyan Zezeski
7669d26e4fcSRobert Mustacchi case MAC_CAPAB_RINGS:
7679d26e4fcSRobert Mustacchi cap_rings = cap_data;
7689d26e4fcSRobert Mustacchi cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
7699d26e4fcSRobert Mustacchi switch (cap_rings->mr_type) {
7709d26e4fcSRobert Mustacchi case MAC_RING_TYPE_TX:
7719d26e4fcSRobert Mustacchi /*
77209aee612SRyan Zezeski * Note, saying we have no groups, but some
77309aee612SRyan Zezeski * number of rings indicates to MAC that it
77409aee612SRyan Zezeski * should create psuedo-groups with one for
77509aee612SRyan Zezeski * each TX ring. This may not be the long term
77609aee612SRyan Zezeski * behavior we want, but it'll work for now.
7779d26e4fcSRobert Mustacchi */
7789d26e4fcSRobert Mustacchi cap_rings->mr_gnum = 0;
77909aee612SRyan Zezeski cap_rings->mr_rnum = i40e->i40e_num_trqpairs_per_vsi;
7809d26e4fcSRobert Mustacchi cap_rings->mr_rget = i40e_fill_tx_ring;
7819d26e4fcSRobert Mustacchi cap_rings->mr_gget = NULL;
7829d26e4fcSRobert Mustacchi cap_rings->mr_gaddring = NULL;
7839d26e4fcSRobert Mustacchi cap_rings->mr_gremring = NULL;
7849d26e4fcSRobert Mustacchi break;
7859d26e4fcSRobert Mustacchi case MAC_RING_TYPE_RX:
7869d26e4fcSRobert Mustacchi cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
7879d26e4fcSRobert Mustacchi cap_rings->mr_rget = i40e_fill_rx_ring;
78809aee612SRyan Zezeski cap_rings->mr_gnum = i40e->i40e_num_rx_groups;
7899d26e4fcSRobert Mustacchi cap_rings->mr_gget = i40e_fill_rx_group;
7909d26e4fcSRobert Mustacchi cap_rings->mr_gaddring = NULL;
7919d26e4fcSRobert Mustacchi cap_rings->mr_gremring = NULL;
7929d26e4fcSRobert Mustacchi break;
7939d26e4fcSRobert Mustacchi default:
7949d26e4fcSRobert Mustacchi return (B_FALSE);
7959d26e4fcSRobert Mustacchi }
7969d26e4fcSRobert Mustacchi break;
79745d3dd98SRobert Mustacchi case MAC_CAPAB_TRANSCEIVER:
79845d3dd98SRobert Mustacchi mct = cap_data;
79945d3dd98SRobert Mustacchi
80045d3dd98SRobert Mustacchi /*
80145d3dd98SRobert Mustacchi * Firmware doesn't have a great way of telling us in advance
80245d3dd98SRobert Mustacchi * whether we'd expect a SFF transceiver. As such, we always
80345d3dd98SRobert Mustacchi * advertise the support for this capability.
80445d3dd98SRobert Mustacchi */
80545d3dd98SRobert Mustacchi mct->mct_flags = 0;
80645d3dd98SRobert Mustacchi mct->mct_ntransceivers = 1;
80745d3dd98SRobert Mustacchi mct->mct_info = i40e_transceiver_info;
808286d309cSRobert Mustacchi mct->mct_read = i40e_transceiver_read;
80945d3dd98SRobert Mustacchi
81045d3dd98SRobert Mustacchi return (B_TRUE);
811c1e9c696SRobert Mustacchi case MAC_CAPAB_LED:
812c1e9c696SRobert Mustacchi mcl = cap_data;
813c1e9c696SRobert Mustacchi
814c1e9c696SRobert Mustacchi mcl->mcl_flags = 0;
815c1e9c696SRobert Mustacchi mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT | MAC_LED_OFF |
816c1e9c696SRobert Mustacchi MAC_LED_ON;
817c1e9c696SRobert Mustacchi mcl->mcl_set = i40e_gld_led_set;
818c1e9c696SRobert Mustacchi break;
819c1e9c696SRobert Mustacchi
8209d26e4fcSRobert Mustacchi default:
8219d26e4fcSRobert Mustacchi return (B_FALSE);
8229d26e4fcSRobert Mustacchi }
8239d26e4fcSRobert Mustacchi
8249d26e4fcSRobert Mustacchi return (B_TRUE);
8259d26e4fcSRobert Mustacchi }
8269d26e4fcSRobert Mustacchi
8279d26e4fcSRobert Mustacchi /* ARGSUSED */
8289d26e4fcSRobert Mustacchi static int
i40e_m_setprop_private(i40e_t * i40e,const char * pr_name,uint_t pr_valsize,const void * pr_val)8299d26e4fcSRobert Mustacchi i40e_m_setprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
8309d26e4fcSRobert Mustacchi const void *pr_val)
8319d26e4fcSRobert Mustacchi {
8329d26e4fcSRobert Mustacchi int ret;
8339d26e4fcSRobert Mustacchi long val;
8349d26e4fcSRobert Mustacchi char *eptr;
8359d26e4fcSRobert Mustacchi
8369d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
8379d26e4fcSRobert Mustacchi
8389d26e4fcSRobert Mustacchi if ((ret = ddi_strtol(pr_val, &eptr, 10, &val)) != 0 ||
8399d26e4fcSRobert Mustacchi *eptr != '\0') {
8409d26e4fcSRobert Mustacchi return (ret);
8419d26e4fcSRobert Mustacchi }
8429d26e4fcSRobert Mustacchi
8439d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
8449d26e4fcSRobert Mustacchi if (val < I40E_MIN_RX_DMA_THRESH ||
8459d26e4fcSRobert Mustacchi val > I40E_MAX_RX_DMA_THRESH) {
8469d26e4fcSRobert Mustacchi return (EINVAL);
8479d26e4fcSRobert Mustacchi }
8489d26e4fcSRobert Mustacchi i40e->i40e_rx_dma_min = (uint32_t)val;
8499d26e4fcSRobert Mustacchi return (0);
8509d26e4fcSRobert Mustacchi }
8519d26e4fcSRobert Mustacchi
8529d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
8539d26e4fcSRobert Mustacchi if (val < I40E_MIN_TX_DMA_THRESH ||
8549d26e4fcSRobert Mustacchi val > I40E_MAX_TX_DMA_THRESH) {
8559d26e4fcSRobert Mustacchi return (EINVAL);
8569d26e4fcSRobert Mustacchi }
8579d26e4fcSRobert Mustacchi i40e->i40e_tx_dma_min = (uint32_t)val;
8589d26e4fcSRobert Mustacchi return (0);
8599d26e4fcSRobert Mustacchi }
8609d26e4fcSRobert Mustacchi
8619d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
8629d26e4fcSRobert Mustacchi if (val < I40E_MIN_ITR ||
8639d26e4fcSRobert Mustacchi val > I40E_MAX_ITR) {
8649d26e4fcSRobert Mustacchi return (EINVAL);
8659d26e4fcSRobert Mustacchi }
8669d26e4fcSRobert Mustacchi i40e->i40e_rx_itr = (uint32_t)val;
8679d26e4fcSRobert Mustacchi i40e_intr_set_itr(i40e, I40E_ITR_INDEX_RX, i40e->i40e_rx_itr);
8689d26e4fcSRobert Mustacchi return (0);
8699d26e4fcSRobert Mustacchi }
8709d26e4fcSRobert Mustacchi
8719d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
8729d26e4fcSRobert Mustacchi if (val < I40E_MIN_ITR ||
8739d26e4fcSRobert Mustacchi val > I40E_MAX_ITR) {
8749d26e4fcSRobert Mustacchi return (EINVAL);
8759d26e4fcSRobert Mustacchi }
8769d26e4fcSRobert Mustacchi i40e->i40e_tx_itr = (uint32_t)val;
8779d26e4fcSRobert Mustacchi i40e_intr_set_itr(i40e, I40E_ITR_INDEX_TX, i40e->i40e_tx_itr);
8789d26e4fcSRobert Mustacchi return (0);
8799d26e4fcSRobert Mustacchi }
8809d26e4fcSRobert Mustacchi
8819d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
8829d26e4fcSRobert Mustacchi if (val < I40E_MIN_ITR ||
8839d26e4fcSRobert Mustacchi val > I40E_MAX_ITR) {
8849d26e4fcSRobert Mustacchi return (EINVAL);
8859d26e4fcSRobert Mustacchi }
8869d26e4fcSRobert Mustacchi i40e->i40e_tx_itr = (uint32_t)val;
8879d26e4fcSRobert Mustacchi i40e_intr_set_itr(i40e, I40E_ITR_INDEX_OTHER,
8889d26e4fcSRobert Mustacchi i40e->i40e_other_itr);
8899d26e4fcSRobert Mustacchi return (0);
8909d26e4fcSRobert Mustacchi }
8919d26e4fcSRobert Mustacchi
8929d26e4fcSRobert Mustacchi return (ENOTSUP);
8939d26e4fcSRobert Mustacchi }
8949d26e4fcSRobert Mustacchi
8959d26e4fcSRobert Mustacchi static int
i40e_m_getprop_private(i40e_t * i40e,const char * pr_name,uint_t pr_valsize,void * pr_val)8969d26e4fcSRobert Mustacchi i40e_m_getprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
8979d26e4fcSRobert Mustacchi void *pr_val)
8989d26e4fcSRobert Mustacchi {
8999d26e4fcSRobert Mustacchi uint32_t val;
9009d26e4fcSRobert Mustacchi
9019d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
9029d26e4fcSRobert Mustacchi
9039d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
9049d26e4fcSRobert Mustacchi val = i40e->i40e_rx_dma_min;
9059d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
9069d26e4fcSRobert Mustacchi val = i40e->i40e_tx_dma_min;
9079d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
9089d26e4fcSRobert Mustacchi val = i40e->i40e_rx_itr;
9099d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
9109d26e4fcSRobert Mustacchi val = i40e->i40e_tx_itr;
9119d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
9129d26e4fcSRobert Mustacchi val = i40e->i40e_other_itr;
9139d26e4fcSRobert Mustacchi } else {
9149d26e4fcSRobert Mustacchi return (ENOTSUP);
9159d26e4fcSRobert Mustacchi }
9169d26e4fcSRobert Mustacchi
9179d26e4fcSRobert Mustacchi if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize)
9189d26e4fcSRobert Mustacchi return (ERANGE);
9199d26e4fcSRobert Mustacchi return (0);
9209d26e4fcSRobert Mustacchi }
9219d26e4fcSRobert Mustacchi
9229d26e4fcSRobert Mustacchi /*
9239d26e4fcSRobert Mustacchi * Annoyingly for private properties MAC seems to ignore default values that
9249d26e4fcSRobert Mustacchi * aren't strings. That means that we have to translate all of these into
9259d26e4fcSRobert Mustacchi * uint32_t's and instead we size the buffer to be large enough to hold a
9269d26e4fcSRobert Mustacchi * uint32_t.
9279d26e4fcSRobert Mustacchi */
9289d26e4fcSRobert Mustacchi /* ARGSUSED */
9299d26e4fcSRobert Mustacchi static void
i40e_m_propinfo_private(i40e_t * i40e,const char * pr_name,mac_prop_info_handle_t prh)9309d26e4fcSRobert Mustacchi i40e_m_propinfo_private(i40e_t *i40e, const char *pr_name,
9319d26e4fcSRobert Mustacchi mac_prop_info_handle_t prh)
9329d26e4fcSRobert Mustacchi {
9339d26e4fcSRobert Mustacchi char buf[64];
9349d26e4fcSRobert Mustacchi uint32_t def;
9359d26e4fcSRobert Mustacchi
9369d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
9379d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
9389d26e4fcSRobert Mustacchi def = I40E_DEF_RX_DMA_THRESH;
9399d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh,
9409d26e4fcSRobert Mustacchi I40E_MIN_RX_DMA_THRESH,
9419d26e4fcSRobert Mustacchi I40E_MAX_RX_DMA_THRESH);
9429d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
9439d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
9449d26e4fcSRobert Mustacchi def = I40E_DEF_TX_DMA_THRESH;
9459d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh,
9469d26e4fcSRobert Mustacchi I40E_MIN_TX_DMA_THRESH,
9479d26e4fcSRobert Mustacchi I40E_MAX_TX_DMA_THRESH);
9489d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
9499d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
9509d26e4fcSRobert Mustacchi def = I40E_DEF_RX_ITR;
9519d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
9529d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
9539d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
9549d26e4fcSRobert Mustacchi def = I40E_DEF_TX_ITR;
9559d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
9569d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
9579d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
9589d26e4fcSRobert Mustacchi def = I40E_DEF_OTHER_ITR;
9599d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
9609d26e4fcSRobert Mustacchi } else {
9619d26e4fcSRobert Mustacchi return;
9629d26e4fcSRobert Mustacchi }
9639d26e4fcSRobert Mustacchi
9649d26e4fcSRobert Mustacchi (void) snprintf(buf, sizeof (buf), "%d", def);
9659d26e4fcSRobert Mustacchi mac_prop_info_set_default_str(prh, buf);
9669d26e4fcSRobert Mustacchi }
9679d26e4fcSRobert Mustacchi
96811a00484SPaul Winder static int
i40e_update_fec(i40e_t * i40e,link_fec_t fec)96911a00484SPaul Winder i40e_update_fec(i40e_t *i40e, link_fec_t fec)
97011a00484SPaul Winder {
97111a00484SPaul Winder struct i40e_hw *hw = &i40e->i40e_hw_space;
97211a00484SPaul Winder struct i40e_aq_get_phy_abilities_resp abilities;
97311a00484SPaul Winder struct i40e_aq_set_phy_config config;
97411a00484SPaul Winder link_fec_t fec_requested;
97511a00484SPaul Winder int req_fec;
97611a00484SPaul Winder
97711a00484SPaul Winder ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
97811a00484SPaul Winder
97911a00484SPaul Winder if (fec == i40e->i40e_fec_requested)
98011a00484SPaul Winder return (0);
98111a00484SPaul Winder
98211a00484SPaul Winder fec_requested = fec;
98311a00484SPaul Winder if ((fec & LINK_FEC_AUTO) != 0) {
98411a00484SPaul Winder req_fec = I40E_AQ_SET_FEC_AUTO;
98511a00484SPaul Winder fec &= ~LINK_FEC_AUTO;
98611a00484SPaul Winder } else if ((fec & LINK_FEC_NONE) != 0) {
98711a00484SPaul Winder req_fec = 0;
98811a00484SPaul Winder fec &= ~LINK_FEC_NONE;
98911a00484SPaul Winder } else {
99011a00484SPaul Winder req_fec = 0;
99111a00484SPaul Winder if ((fec & LINK_FEC_BASE_R) != 0) {
99211a00484SPaul Winder req_fec |= I40E_AQ_SET_FEC_ABILITY_KR |
99311a00484SPaul Winder I40E_AQ_SET_FEC_REQUEST_KR;
99411a00484SPaul Winder fec &= ~LINK_FEC_BASE_R;
99511a00484SPaul Winder }
99611a00484SPaul Winder if ((fec & LINK_FEC_RS) != 0) {
99711a00484SPaul Winder req_fec |= I40E_AQ_SET_FEC_ABILITY_RS |
99811a00484SPaul Winder I40E_AQ_SET_FEC_REQUEST_RS;
99911a00484SPaul Winder fec &= ~LINK_FEC_RS;
100011a00484SPaul Winder }
100111a00484SPaul Winder if (req_fec == 0)
100211a00484SPaul Winder return (EINVAL);
100311a00484SPaul Winder }
100411a00484SPaul Winder
100511a00484SPaul Winder /*
100611a00484SPaul Winder * if fec is not zero now, then there is an invalid fec or
100711a00484SPaul Winder * combination of settings.
100811a00484SPaul Winder */
100911a00484SPaul Winder if (fec != 0)
101011a00484SPaul Winder return (EINVAL);
101111a00484SPaul Winder
101211a00484SPaul Winder if (i40e_aq_get_phy_capabilities(hw, B_FALSE, B_FALSE, &abilities,
101311a00484SPaul Winder NULL) != I40E_SUCCESS)
101411a00484SPaul Winder return (EIO);
101511a00484SPaul Winder
101611a00484SPaul Winder bzero(&config, sizeof (config));
101711a00484SPaul Winder config.abilities = abilities.abilities;
101811a00484SPaul Winder /* Restart the link */
101911a00484SPaul Winder config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
102011a00484SPaul Winder config.phy_type = abilities.phy_type;
102111a00484SPaul Winder config.phy_type_ext = abilities.phy_type_ext;
102211a00484SPaul Winder config.link_speed = abilities.link_speed;
102311a00484SPaul Winder config.eee_capability = abilities.eee_capability;
102411a00484SPaul Winder config.eeer = abilities.eeer_val;
102511a00484SPaul Winder config.low_power_ctrl = abilities.d3_lpan;
102611a00484SPaul Winder config.fec_config = req_fec & I40E_AQ_PHY_FEC_CONFIG_MASK;
102711a00484SPaul Winder if (i40e_aq_set_phy_config(hw, &config, NULL) != I40E_SUCCESS)
102811a00484SPaul Winder return (EIO);
102911a00484SPaul Winder
103011a00484SPaul Winder if (i40e_update_link_info(hw) != I40E_SUCCESS)
103111a00484SPaul Winder return (EIO);
103211a00484SPaul Winder
103311a00484SPaul Winder i40e->i40e_fec_requested = fec_requested;
103411a00484SPaul Winder
103511a00484SPaul Winder return (0);
103611a00484SPaul Winder }
10379d26e4fcSRobert Mustacchi static int
i40e_m_setprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,const void * pr_val)10389d26e4fcSRobert Mustacchi i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
10399d26e4fcSRobert Mustacchi uint_t pr_valsize, const void *pr_val)
10409d26e4fcSRobert Mustacchi {
10419d26e4fcSRobert Mustacchi uint32_t new_mtu;
104211a00484SPaul Winder link_fec_t fec;
10439d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
10449d26e4fcSRobert Mustacchi int ret = 0;
10459d26e4fcSRobert Mustacchi
10469d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
10479d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) {
10489d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
10499d26e4fcSRobert Mustacchi return (ECANCELED);
10509d26e4fcSRobert Mustacchi }
10519d26e4fcSRobert Mustacchi
10529d26e4fcSRobert Mustacchi switch (pr_num) {
10539d26e4fcSRobert Mustacchi /*
10549d26e4fcSRobert Mustacchi * These properties are always read-only across every device.
10559d26e4fcSRobert Mustacchi */
10569d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX:
10579d26e4fcSRobert Mustacchi case MAC_PROP_SPEED:
10589d26e4fcSRobert Mustacchi case MAC_PROP_STATUS:
1059*63783c5cSRobert Mustacchi case MAC_PROP_MEDIA:
10609d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP:
10619d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP:
1062df36e06dSRobert Mustacchi case MAC_PROP_ADV_2500FDX_CAP:
1063df36e06dSRobert Mustacchi case MAC_PROP_ADV_5000FDX_CAP:
10649d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP:
10653d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP:
10669d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP:
10679d26e4fcSRobert Mustacchi ret = ENOTSUP;
10689d26e4fcSRobert Mustacchi break;
10699d26e4fcSRobert Mustacchi /*
10709d26e4fcSRobert Mustacchi * These are read-only at this time as we don't support configuring
10719d26e4fcSRobert Mustacchi * auto-negotiation. See the theory statement in i40e_main.c.
10729d26e4fcSRobert Mustacchi */
10739d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP:
10749d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP:
1075df36e06dSRobert Mustacchi case MAC_PROP_EN_2500FDX_CAP:
1076df36e06dSRobert Mustacchi case MAC_PROP_EN_5000FDX_CAP:
10779d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP:
10783d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP:
10799d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP:
10809d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG:
10819d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL:
10829d26e4fcSRobert Mustacchi ret = ENOTSUP;
10839d26e4fcSRobert Mustacchi break;
10849d26e4fcSRobert Mustacchi
10859d26e4fcSRobert Mustacchi case MAC_PROP_MTU:
10869d26e4fcSRobert Mustacchi bcopy(pr_val, &new_mtu, sizeof (new_mtu));
10879d26e4fcSRobert Mustacchi if (new_mtu == i40e->i40e_sdu)
10889d26e4fcSRobert Mustacchi break;
10899d26e4fcSRobert Mustacchi
10909d26e4fcSRobert Mustacchi if (new_mtu < I40E_MIN_MTU ||
10919d26e4fcSRobert Mustacchi new_mtu > I40E_MAX_MTU) {
10929d26e4fcSRobert Mustacchi ret = EINVAL;
10939d26e4fcSRobert Mustacchi break;
10949d26e4fcSRobert Mustacchi }
10959d26e4fcSRobert Mustacchi
10969d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_STARTED) {
10979d26e4fcSRobert Mustacchi ret = EBUSY;
10989d26e4fcSRobert Mustacchi break;
10999d26e4fcSRobert Mustacchi }
11009d26e4fcSRobert Mustacchi
11019d26e4fcSRobert Mustacchi ret = mac_maxsdu_update(i40e->i40e_mac_hdl, new_mtu);
11029d26e4fcSRobert Mustacchi if (ret == 0) {
11039d26e4fcSRobert Mustacchi i40e->i40e_sdu = new_mtu;
11049d26e4fcSRobert Mustacchi i40e_update_mtu(i40e);
11059d26e4fcSRobert Mustacchi }
11069d26e4fcSRobert Mustacchi break;
11079d26e4fcSRobert Mustacchi
110811a00484SPaul Winder case MAC_PROP_EN_FEC_CAP:
110911a00484SPaul Winder bcopy(pr_val, &fec, sizeof (fec));
111011a00484SPaul Winder
111111a00484SPaul Winder ret = i40e_update_fec(i40e, fec);
111211a00484SPaul Winder break;
111311a00484SPaul Winder
11149d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE:
11159d26e4fcSRobert Mustacchi ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val);
11169d26e4fcSRobert Mustacchi break;
11179d26e4fcSRobert Mustacchi default:
11189d26e4fcSRobert Mustacchi ret = ENOTSUP;
11199d26e4fcSRobert Mustacchi break;
11209d26e4fcSRobert Mustacchi }
11219d26e4fcSRobert Mustacchi
11229d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
11239d26e4fcSRobert Mustacchi return (ret);
11249d26e4fcSRobert Mustacchi }
11259d26e4fcSRobert Mustacchi
112611a00484SPaul Winder static link_fec_t
i40e_fec_to_linkfec(struct i40e_hw * hw)112711a00484SPaul Winder i40e_fec_to_linkfec(struct i40e_hw *hw)
112811a00484SPaul Winder {
112911a00484SPaul Winder struct i40e_link_status *ls = &hw->phy.link_info;
113011a00484SPaul Winder
113111a00484SPaul Winder if ((ls->fec_info & I40E_AQ_CONFIG_FEC_KR_ENA) != 0)
113211a00484SPaul Winder return (LINK_FEC_BASE_R);
113311a00484SPaul Winder
113411a00484SPaul Winder if ((ls->fec_info & I40E_AQ_CONFIG_FEC_RS_ENA) != 0)
113511a00484SPaul Winder return (LINK_FEC_RS);
113611a00484SPaul Winder
113711a00484SPaul Winder return (LINK_FEC_NONE);
113811a00484SPaul Winder }
113911a00484SPaul Winder
1140*63783c5cSRobert Mustacchi mac_ether_media_t
i40e_link_to_media(i40e_t * i40e)1141*63783c5cSRobert Mustacchi i40e_link_to_media(i40e_t *i40e)
1142*63783c5cSRobert Mustacchi {
1143*63783c5cSRobert Mustacchi switch (i40e->i40e_link_state) {
1144*63783c5cSRobert Mustacchi case LINK_STATE_UP:
1145*63783c5cSRobert Mustacchi break;
1146*63783c5cSRobert Mustacchi case LINK_STATE_DOWN:
1147*63783c5cSRobert Mustacchi return (ETHER_MEDIA_NONE);
1148*63783c5cSRobert Mustacchi default:
1149*63783c5cSRobert Mustacchi return (ETHER_MEDIA_UNKNOWN);
1150*63783c5cSRobert Mustacchi }
1151*63783c5cSRobert Mustacchi
1152*63783c5cSRobert Mustacchi switch (i40e->i40e_hw_space.phy.link_info.phy_type) {
1153*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_SGMII:
1154*63783c5cSRobert Mustacchi return (ETHER_MEDIA_1000_SGMII);
1155*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_1000BASE_KX:
1156*63783c5cSRobert Mustacchi return (ETHER_MEDIA_1000BASE_KX);
1157*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_KX4:
1158*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_KX4);
1159*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_KR:
1160*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_KR);
1161*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_40GBASE_KR4:
1162*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40GBASE_KR4);
1163*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_XAUI:
1164*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10G_XAUI);
1165*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_XFI:
1166*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10G_XFI);
1167*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_SFI:
1168*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10G_SFI);
1169*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_XLAUI:
1170*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40G_XLAUI);
1171*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_XLPPI:
1172*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40G_XLPPI);
1173*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_40GBASE_CR4_CU:
1174*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40GBASE_CR4);
1175*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_CR1_CU:
1176*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_CR);
1177*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_AOC:
1178*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_AOC);
1179*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_40GBASE_AOC:
1180*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40GBASE_AOC4);
1181*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_100BASE_TX:
1182*63783c5cSRobert Mustacchi return (ETHER_MEDIA_100BASE_TX);
1183*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_1000BASE_T:
1184*63783c5cSRobert Mustacchi return (ETHER_MEDIA_1000BASE_T);
1185*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_T:
1186*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_T);
1187*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_SR:
1188*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_SR);
1189*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_LR:
1190*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_LR);
1191*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_SFPP_CU:
1192*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_CR);
1193*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_10GBASE_CR1:
1194*63783c5cSRobert Mustacchi return (ETHER_MEDIA_10GBASE_CR);
1195*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_40GBASE_CR4:
1196*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40GBASE_CR4);
1197*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_40GBASE_SR4:
1198*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40GBASE_SR4);
1199*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_40GBASE_LR4:
1200*63783c5cSRobert Mustacchi return (ETHER_MEDIA_40GBASE_LR4);
1201*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_1000BASE_SX:
1202*63783c5cSRobert Mustacchi return (ETHER_MEDIA_1000BASE_SX);
1203*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_1000BASE_LX:
1204*63783c5cSRobert Mustacchi return (ETHER_MEDIA_1000BASE_LX);
1205*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_1000BASE_T_OPTICAL:
1206*63783c5cSRobert Mustacchi return (ETHER_MEDIA_1000BASE_T);
1207*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_25GBASE_KR:
1208*63783c5cSRobert Mustacchi return (ETHER_MEDIA_25GBASE_KR);
1209*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_25GBASE_CR:
1210*63783c5cSRobert Mustacchi return (ETHER_MEDIA_25GBASE_CR);
1211*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_25GBASE_SR:
1212*63783c5cSRobert Mustacchi return (ETHER_MEDIA_25GBASE_SR);
1213*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_25GBASE_LR:
1214*63783c5cSRobert Mustacchi return (ETHER_MEDIA_25GBASE_LR);
1215*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_25GBASE_AOC:
1216*63783c5cSRobert Mustacchi return (ETHER_MEDIA_25GBASE_AOC);
1217*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_25GBASE_ACC:
1218*63783c5cSRobert Mustacchi return (ETHER_MEDIA_25GBASE_ACC);
1219*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_2_5GBASE_T:
1220*63783c5cSRobert Mustacchi return (ETHER_MEDIA_2500BASE_T);
1221*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_5GBASE_T:
1222*63783c5cSRobert Mustacchi return (ETHER_MEDIA_5000BASE_T);
1223*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_EMPTY:
1224*63783c5cSRobert Mustacchi return (ETHER_MEDIA_NONE);
1225*63783c5cSRobert Mustacchi /*
1226*63783c5cSRobert Mustacchi * We don't currently support 20GBASE-KR2 in any way in the GLD. If
1227*63783c5cSRobert Mustacchi * someone actually can generate this, then we should do this.
1228*63783c5cSRobert Mustacchi */
1229*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_20GBASE_KR2:
1230*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_DEFAULT:
1231*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_UNRECOGNIZED:
1232*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_UNSUPPORTED:
1233*63783c5cSRobert Mustacchi case I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP:
1234*63783c5cSRobert Mustacchi default:
1235*63783c5cSRobert Mustacchi return (ETHER_MEDIA_UNKNOWN);
1236*63783c5cSRobert Mustacchi }
1237*63783c5cSRobert Mustacchi }
1238*63783c5cSRobert Mustacchi
12399d26e4fcSRobert Mustacchi static int
i40e_m_getprop(void * arg,const char * pr_name,mac_prop_id_t pr_num,uint_t pr_valsize,void * pr_val)12409d26e4fcSRobert Mustacchi i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
12419d26e4fcSRobert Mustacchi uint_t pr_valsize, void *pr_val)
12429d26e4fcSRobert Mustacchi {
12439d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
12449d26e4fcSRobert Mustacchi uint64_t speed;
12459d26e4fcSRobert Mustacchi int ret = 0;
12469d26e4fcSRobert Mustacchi uint8_t *u8;
12479d26e4fcSRobert Mustacchi link_flowctrl_t fctl;
12489d26e4fcSRobert Mustacchi
12499d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
12509d26e4fcSRobert Mustacchi
12519d26e4fcSRobert Mustacchi switch (pr_num) {
12529d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX:
12539d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_duplex_t)) {
12549d26e4fcSRobert Mustacchi ret = EOVERFLOW;
12559d26e4fcSRobert Mustacchi break;
12569d26e4fcSRobert Mustacchi }
12579d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_link_duplex, pr_val, sizeof (link_duplex_t));
12589d26e4fcSRobert Mustacchi break;
12599d26e4fcSRobert Mustacchi case MAC_PROP_SPEED:
12609d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint64_t)) {
12619d26e4fcSRobert Mustacchi ret = EOVERFLOW;
12629d26e4fcSRobert Mustacchi break;
12639d26e4fcSRobert Mustacchi }
12649d26e4fcSRobert Mustacchi speed = i40e->i40e_link_speed * 1000000ULL;
12659d26e4fcSRobert Mustacchi bcopy(&speed, pr_val, sizeof (speed));
12669d26e4fcSRobert Mustacchi break;
12679d26e4fcSRobert Mustacchi case MAC_PROP_STATUS:
12689d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_state_t)) {
12699d26e4fcSRobert Mustacchi ret = EOVERFLOW;
12709d26e4fcSRobert Mustacchi break;
12719d26e4fcSRobert Mustacchi }
12729d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_link_state, pr_val, sizeof (link_state_t));
12739d26e4fcSRobert Mustacchi break;
1274*63783c5cSRobert Mustacchi case MAC_PROP_MEDIA:
1275*63783c5cSRobert Mustacchi *(mac_ether_media_t *)pr_val = i40e_link_to_media(i40e);
1276*63783c5cSRobert Mustacchi break;
12779d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG:
12789d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
12799d26e4fcSRobert Mustacchi ret = EOVERFLOW;
12809d26e4fcSRobert Mustacchi break;
12819d26e4fcSRobert Mustacchi }
12829d26e4fcSRobert Mustacchi u8 = pr_val;
12839d26e4fcSRobert Mustacchi *u8 = 1;
12849d26e4fcSRobert Mustacchi break;
12859d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL:
12869d26e4fcSRobert Mustacchi /*
12879d26e4fcSRobert Mustacchi * Because we don't currently support hardware flow control, we
12889d26e4fcSRobert Mustacchi * just hardcode this to be none.
12899d26e4fcSRobert Mustacchi */
12909d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_flowctrl_t)) {
12919d26e4fcSRobert Mustacchi ret = EOVERFLOW;
12929d26e4fcSRobert Mustacchi break;
12939d26e4fcSRobert Mustacchi }
12949d26e4fcSRobert Mustacchi fctl = LINK_FLOWCTRL_NONE;
12959d26e4fcSRobert Mustacchi bcopy(&fctl, pr_val, sizeof (link_flowctrl_t));
12969d26e4fcSRobert Mustacchi break;
12979d26e4fcSRobert Mustacchi case MAC_PROP_MTU:
12989d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint32_t)) {
12999d26e4fcSRobert Mustacchi ret = EOVERFLOW;
13009d26e4fcSRobert Mustacchi break;
13019d26e4fcSRobert Mustacchi }
13029d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t));
13039d26e4fcSRobert Mustacchi break;
130411a00484SPaul Winder case MAC_PROP_ADV_FEC_CAP:
130511a00484SPaul Winder if (pr_valsize < sizeof (link_fec_t)) {
130611a00484SPaul Winder ret = EOVERFLOW;
130711a00484SPaul Winder break;
130811a00484SPaul Winder }
130911a00484SPaul Winder *(link_fec_t *)pr_val =
131011a00484SPaul Winder i40e_fec_to_linkfec(&i40e->i40e_hw_space);
131111a00484SPaul Winder break;
131211a00484SPaul Winder case MAC_PROP_EN_FEC_CAP:
131311a00484SPaul Winder if (pr_valsize < sizeof (link_fec_t)) {
131411a00484SPaul Winder ret = EOVERFLOW;
131511a00484SPaul Winder break;
131611a00484SPaul Winder }
131711a00484SPaul Winder *(link_fec_t *)pr_val = i40e->i40e_fec_requested;
131811a00484SPaul Winder break;
13199d26e4fcSRobert Mustacchi
13209d26e4fcSRobert Mustacchi /*
13219d26e4fcSRobert Mustacchi * Because we don't let users control the speeds we may auto-negotiate
13229d26e4fcSRobert Mustacchi * to, the values of the ADV_ and EN_ will always be the same.
13239d26e4fcSRobert Mustacchi */
13249d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP:
13259d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP:
13269d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
13279d26e4fcSRobert Mustacchi ret = EOVERFLOW;
13289d26e4fcSRobert Mustacchi break;
13299d26e4fcSRobert Mustacchi }
13309d26e4fcSRobert Mustacchi u8 = pr_val;
13319d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0;
13329d26e4fcSRobert Mustacchi break;
13339d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP:
13349d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP:
13359d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
13369d26e4fcSRobert Mustacchi ret = EOVERFLOW;
13379d26e4fcSRobert Mustacchi break;
13389d26e4fcSRobert Mustacchi }
13399d26e4fcSRobert Mustacchi u8 = pr_val;
13409d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0;
13419d26e4fcSRobert Mustacchi break;
1342df36e06dSRobert Mustacchi case MAC_PROP_ADV_2500FDX_CAP:
1343df36e06dSRobert Mustacchi case MAC_PROP_EN_2500FDX_CAP:
1344df36e06dSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
1345df36e06dSRobert Mustacchi ret = EOVERFLOW;
1346df36e06dSRobert Mustacchi break;
1347df36e06dSRobert Mustacchi }
1348df36e06dSRobert Mustacchi u8 = pr_val;
1349df36e06dSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_2_5GB) != 0;
1350df36e06dSRobert Mustacchi break;
1351df36e06dSRobert Mustacchi case MAC_PROP_ADV_5000FDX_CAP:
1352df36e06dSRobert Mustacchi case MAC_PROP_EN_5000FDX_CAP:
1353df36e06dSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
1354df36e06dSRobert Mustacchi ret = EOVERFLOW;
1355df36e06dSRobert Mustacchi break;
1356df36e06dSRobert Mustacchi }
1357df36e06dSRobert Mustacchi u8 = pr_val;
1358df36e06dSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_5GB) != 0;
1359df36e06dSRobert Mustacchi break;
13609d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP:
13619d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP:
13629d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
13639d26e4fcSRobert Mustacchi ret = EOVERFLOW;
13649d26e4fcSRobert Mustacchi break;
13659d26e4fcSRobert Mustacchi }
13669d26e4fcSRobert Mustacchi u8 = pr_val;
13679d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0;
13689d26e4fcSRobert Mustacchi break;
13693d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP:
13703d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP:
13713d75a287SRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
13723d75a287SRobert Mustacchi ret = EOVERFLOW;
13733d75a287SRobert Mustacchi break;
13743d75a287SRobert Mustacchi }
13753d75a287SRobert Mustacchi u8 = pr_val;
13763d75a287SRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0;
13773d75a287SRobert Mustacchi break;
13789d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP:
13799d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP:
13809d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) {
13819d26e4fcSRobert Mustacchi ret = EOVERFLOW;
13829d26e4fcSRobert Mustacchi break;
13839d26e4fcSRobert Mustacchi }
13849d26e4fcSRobert Mustacchi u8 = pr_val;
13859d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0;
13869d26e4fcSRobert Mustacchi break;
13879d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE:
13889d26e4fcSRobert Mustacchi ret = i40e_m_getprop_private(i40e, pr_name, pr_valsize, pr_val);
13899d26e4fcSRobert Mustacchi break;
13909d26e4fcSRobert Mustacchi default:
13919d26e4fcSRobert Mustacchi ret = ENOTSUP;
13929d26e4fcSRobert Mustacchi break;
13939d26e4fcSRobert Mustacchi }
13949d26e4fcSRobert Mustacchi
13959d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
13969d26e4fcSRobert Mustacchi
13979d26e4fcSRobert Mustacchi return (ret);
13989d26e4fcSRobert Mustacchi }
13999d26e4fcSRobert Mustacchi
14009d26e4fcSRobert Mustacchi static void
i40e_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)14019d26e4fcSRobert Mustacchi i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
14029d26e4fcSRobert Mustacchi mac_prop_info_handle_t prh)
14039d26e4fcSRobert Mustacchi {
14049d26e4fcSRobert Mustacchi i40e_t *i40e = arg;
14059d26e4fcSRobert Mustacchi
14069d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock);
14079d26e4fcSRobert Mustacchi
14089d26e4fcSRobert Mustacchi switch (pr_num) {
14099d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX:
14109d26e4fcSRobert Mustacchi case MAC_PROP_SPEED:
14119d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14129d26e4fcSRobert Mustacchi break;
14139d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL:
14149d26e4fcSRobert Mustacchi /*
14159d26e4fcSRobert Mustacchi * At the moment, the driver doesn't support flow control, hence
14169d26e4fcSRobert Mustacchi * why this is set to read-only and none.
14179d26e4fcSRobert Mustacchi */
14189d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14199d26e4fcSRobert Mustacchi mac_prop_info_set_default_link_flowctrl(prh,
14209d26e4fcSRobert Mustacchi LINK_FLOWCTRL_NONE);
14219d26e4fcSRobert Mustacchi break;
14229d26e4fcSRobert Mustacchi case MAC_PROP_MTU:
14239d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU);
14249d26e4fcSRobert Mustacchi break;
142511a00484SPaul Winder case MAC_PROP_ADV_FEC_CAP:
142611a00484SPaul Winder mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
142711a00484SPaul Winder if (i40e_is_25G_device(i40e->i40e_hw_space.device_id))
142811a00484SPaul Winder mac_prop_info_set_default_fec(prh, LINK_FEC_AUTO);
142911a00484SPaul Winder break;
143011a00484SPaul Winder case MAC_PROP_EN_FEC_CAP:
143111a00484SPaul Winder if (i40e_is_25G_device(i40e->i40e_hw_space.device_id)) {
143211a00484SPaul Winder mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
143311a00484SPaul Winder mac_prop_info_set_default_fec(prh, LINK_FEC_AUTO);
143411a00484SPaul Winder } else {
143511a00484SPaul Winder mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
143611a00484SPaul Winder }
143711a00484SPaul Winder break;
14389d26e4fcSRobert Mustacchi
14399d26e4fcSRobert Mustacchi /*
14409d26e4fcSRobert Mustacchi * We set the defaults for these based upon the phy's ability to
14419d26e4fcSRobert Mustacchi * support the speeds. Note, auto-negotiation is required for fiber,
14429d26e4fcSRobert Mustacchi * hence it is read-only and always enabled. When we have access to
14439d26e4fcSRobert Mustacchi * copper phys we can revisit this.
14449d26e4fcSRobert Mustacchi */
14459d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG:
14469d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14479d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 1);
14489d26e4fcSRobert Mustacchi break;
14499d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP:
14509d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14519d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14529d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
14539d26e4fcSRobert Mustacchi break;
14549d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP:
14559d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14569d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14579d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
14589d26e4fcSRobert Mustacchi break;
14599d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP:
14609d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14619d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14629d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
14639d26e4fcSRobert Mustacchi break;
14649d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP:
14659d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14669d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14679d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
14689d26e4fcSRobert Mustacchi break;
14699d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP:
14709d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14719d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14729d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
14739d26e4fcSRobert Mustacchi break;
14749d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP:
14759d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14769d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14779d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
14789d26e4fcSRobert Mustacchi break;
14793d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP:
14803d75a287SRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14813d75a287SRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14823d75a287SRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
14833d75a287SRobert Mustacchi break;
14843d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP:
14853d75a287SRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14863d75a287SRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14873d75a287SRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
14883d75a287SRobert Mustacchi break;
14899d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP:
14909d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14919d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14929d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
14939d26e4fcSRobert Mustacchi break;
14949d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP:
14959d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
14969d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh,
14979d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
14989d26e4fcSRobert Mustacchi break;
14999d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE:
15009d26e4fcSRobert Mustacchi i40e_m_propinfo_private(i40e, pr_name, prh);
15019d26e4fcSRobert Mustacchi break;
15029d26e4fcSRobert Mustacchi default:
15039d26e4fcSRobert Mustacchi break;
15049d26e4fcSRobert Mustacchi }
15059d26e4fcSRobert Mustacchi
15069d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock);
15079d26e4fcSRobert Mustacchi }
15089d26e4fcSRobert Mustacchi
15099d26e4fcSRobert Mustacchi #define I40E_M_CALLBACK_FLAGS \
15109d26e4fcSRobert Mustacchi (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
15119d26e4fcSRobert Mustacchi
15129d26e4fcSRobert Mustacchi static mac_callbacks_t i40e_m_callbacks = {
15139d26e4fcSRobert Mustacchi I40E_M_CALLBACK_FLAGS,
15149d26e4fcSRobert Mustacchi i40e_m_stat,
15159d26e4fcSRobert Mustacchi i40e_m_start,
15169d26e4fcSRobert Mustacchi i40e_m_stop,
15179d26e4fcSRobert Mustacchi i40e_m_promisc,
15189d26e4fcSRobert Mustacchi i40e_m_multicast,
15199d26e4fcSRobert Mustacchi NULL,
15209d26e4fcSRobert Mustacchi NULL,
15219d26e4fcSRobert Mustacchi NULL,
15229d26e4fcSRobert Mustacchi i40e_m_ioctl,
15239d26e4fcSRobert Mustacchi i40e_m_getcapab,
15249d26e4fcSRobert Mustacchi NULL,
15259d26e4fcSRobert Mustacchi NULL,
15269d26e4fcSRobert Mustacchi i40e_m_setprop,
15279d26e4fcSRobert Mustacchi i40e_m_getprop,
15289d26e4fcSRobert Mustacchi i40e_m_propinfo
15299d26e4fcSRobert Mustacchi };
15309d26e4fcSRobert Mustacchi
15319d26e4fcSRobert Mustacchi boolean_t
i40e_register_mac(i40e_t * i40e)15329d26e4fcSRobert Mustacchi i40e_register_mac(i40e_t *i40e)
15339d26e4fcSRobert Mustacchi {
15349d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space;
15359d26e4fcSRobert Mustacchi int status;
15369d26e4fcSRobert Mustacchi mac_register_t *mac = mac_alloc(MAC_VERSION);
15379d26e4fcSRobert Mustacchi
15389d26e4fcSRobert Mustacchi if (mac == NULL)
15399d26e4fcSRobert Mustacchi return (B_FALSE);
15409d26e4fcSRobert Mustacchi
15419d26e4fcSRobert Mustacchi mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
15429d26e4fcSRobert Mustacchi mac->m_driver = i40e;
15439d26e4fcSRobert Mustacchi mac->m_dip = i40e->i40e_dip;
15449d26e4fcSRobert Mustacchi mac->m_src_addr = hw->mac.addr;
15459d26e4fcSRobert Mustacchi mac->m_callbacks = &i40e_m_callbacks;
15469d26e4fcSRobert Mustacchi mac->m_min_sdu = 0;
15479d26e4fcSRobert Mustacchi mac->m_max_sdu = i40e->i40e_sdu;
15489d26e4fcSRobert Mustacchi mac->m_margin = VLAN_TAGSZ;
15499d26e4fcSRobert Mustacchi mac->m_priv_props = i40e_priv_props;
15509d26e4fcSRobert Mustacchi mac->m_v12n = MAC_VIRT_LEVEL1;
15519d26e4fcSRobert Mustacchi
15529d26e4fcSRobert Mustacchi status = mac_register(mac, &i40e->i40e_mac_hdl);
15539d26e4fcSRobert Mustacchi if (status != 0)
15549d26e4fcSRobert Mustacchi i40e_error(i40e, "mac_register() returned %d", status);
15559d26e4fcSRobert Mustacchi mac_free(mac);
15569d26e4fcSRobert Mustacchi
15579d26e4fcSRobert Mustacchi return (status == 0);
15589d26e4fcSRobert Mustacchi }
1559