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. 14286d309cSRobert Mustacchi * Copyright (c) 2018, 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*df36e06dSRobert Mustacchi * Copyright 2021 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 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 " 849d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x 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 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 " 1529d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x 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 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 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 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 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 " 3199d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x 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 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 " 3609d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x 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 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 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 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 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 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 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 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 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 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 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 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, 674*df36e06dSRobert 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 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 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 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 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 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 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 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: 10599d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP: 10609d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP: 1061*df36e06dSRobert Mustacchi case MAC_PROP_ADV_2500FDX_CAP: 1062*df36e06dSRobert Mustacchi case MAC_PROP_ADV_5000FDX_CAP: 10639d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP: 10643d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP: 10659d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP: 10669d26e4fcSRobert Mustacchi ret = ENOTSUP; 10679d26e4fcSRobert Mustacchi break; 10689d26e4fcSRobert Mustacchi /* 10699d26e4fcSRobert Mustacchi * These are read-only at this time as we don't support configuring 10709d26e4fcSRobert Mustacchi * auto-negotiation. See the theory statement in i40e_main.c. 10719d26e4fcSRobert Mustacchi */ 10729d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP: 10739d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP: 1074*df36e06dSRobert Mustacchi case MAC_PROP_EN_2500FDX_CAP: 1075*df36e06dSRobert Mustacchi case MAC_PROP_EN_5000FDX_CAP: 10769d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP: 10773d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP: 10789d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP: 10799d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG: 10809d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL: 10819d26e4fcSRobert Mustacchi ret = ENOTSUP; 10829d26e4fcSRobert Mustacchi break; 10839d26e4fcSRobert Mustacchi 10849d26e4fcSRobert Mustacchi case MAC_PROP_MTU: 10859d26e4fcSRobert Mustacchi bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 10869d26e4fcSRobert Mustacchi if (new_mtu == i40e->i40e_sdu) 10879d26e4fcSRobert Mustacchi break; 10889d26e4fcSRobert Mustacchi 10899d26e4fcSRobert Mustacchi if (new_mtu < I40E_MIN_MTU || 10909d26e4fcSRobert Mustacchi new_mtu > I40E_MAX_MTU) { 10919d26e4fcSRobert Mustacchi ret = EINVAL; 10929d26e4fcSRobert Mustacchi break; 10939d26e4fcSRobert Mustacchi } 10949d26e4fcSRobert Mustacchi 10959d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_STARTED) { 10969d26e4fcSRobert Mustacchi ret = EBUSY; 10979d26e4fcSRobert Mustacchi break; 10989d26e4fcSRobert Mustacchi } 10999d26e4fcSRobert Mustacchi 11009d26e4fcSRobert Mustacchi ret = mac_maxsdu_update(i40e->i40e_mac_hdl, new_mtu); 11019d26e4fcSRobert Mustacchi if (ret == 0) { 11029d26e4fcSRobert Mustacchi i40e->i40e_sdu = new_mtu; 11039d26e4fcSRobert Mustacchi i40e_update_mtu(i40e); 11049d26e4fcSRobert Mustacchi } 11059d26e4fcSRobert Mustacchi break; 11069d26e4fcSRobert Mustacchi 110711a00484SPaul Winder case MAC_PROP_EN_FEC_CAP: 110811a00484SPaul Winder bcopy(pr_val, &fec, sizeof (fec)); 110911a00484SPaul Winder 111011a00484SPaul Winder ret = i40e_update_fec(i40e, fec); 111111a00484SPaul Winder break; 111211a00484SPaul Winder 11139d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE: 11149d26e4fcSRobert Mustacchi ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val); 11159d26e4fcSRobert Mustacchi break; 11169d26e4fcSRobert Mustacchi default: 11179d26e4fcSRobert Mustacchi ret = ENOTSUP; 11189d26e4fcSRobert Mustacchi break; 11199d26e4fcSRobert Mustacchi } 11209d26e4fcSRobert Mustacchi 11219d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 11229d26e4fcSRobert Mustacchi return (ret); 11239d26e4fcSRobert Mustacchi } 11249d26e4fcSRobert Mustacchi 112511a00484SPaul Winder static link_fec_t 112611a00484SPaul Winder i40e_fec_to_linkfec(struct i40e_hw *hw) 112711a00484SPaul Winder { 112811a00484SPaul Winder struct i40e_link_status *ls = &hw->phy.link_info; 112911a00484SPaul Winder 113011a00484SPaul Winder if ((ls->fec_info & I40E_AQ_CONFIG_FEC_KR_ENA) != 0) 113111a00484SPaul Winder return (LINK_FEC_BASE_R); 113211a00484SPaul Winder 113311a00484SPaul Winder if ((ls->fec_info & I40E_AQ_CONFIG_FEC_RS_ENA) != 0) 113411a00484SPaul Winder return (LINK_FEC_RS); 113511a00484SPaul Winder 113611a00484SPaul Winder return (LINK_FEC_NONE); 113711a00484SPaul Winder } 113811a00484SPaul Winder 11399d26e4fcSRobert Mustacchi static int 11409d26e4fcSRobert Mustacchi i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 11419d26e4fcSRobert Mustacchi uint_t pr_valsize, void *pr_val) 11429d26e4fcSRobert Mustacchi { 11439d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 11449d26e4fcSRobert Mustacchi uint64_t speed; 11459d26e4fcSRobert Mustacchi int ret = 0; 11469d26e4fcSRobert Mustacchi uint8_t *u8; 11479d26e4fcSRobert Mustacchi link_flowctrl_t fctl; 11489d26e4fcSRobert Mustacchi 11499d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 11509d26e4fcSRobert Mustacchi 11519d26e4fcSRobert Mustacchi switch (pr_num) { 11529d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX: 11539d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_duplex_t)) { 11549d26e4fcSRobert Mustacchi ret = EOVERFLOW; 11559d26e4fcSRobert Mustacchi break; 11569d26e4fcSRobert Mustacchi } 11579d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_link_duplex, pr_val, sizeof (link_duplex_t)); 11589d26e4fcSRobert Mustacchi break; 11599d26e4fcSRobert Mustacchi case MAC_PROP_SPEED: 11609d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint64_t)) { 11619d26e4fcSRobert Mustacchi ret = EOVERFLOW; 11629d26e4fcSRobert Mustacchi break; 11639d26e4fcSRobert Mustacchi } 11649d26e4fcSRobert Mustacchi speed = i40e->i40e_link_speed * 1000000ULL; 11659d26e4fcSRobert Mustacchi bcopy(&speed, pr_val, sizeof (speed)); 11669d26e4fcSRobert Mustacchi break; 11679d26e4fcSRobert Mustacchi case MAC_PROP_STATUS: 11689d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_state_t)) { 11699d26e4fcSRobert Mustacchi ret = EOVERFLOW; 11709d26e4fcSRobert Mustacchi break; 11719d26e4fcSRobert Mustacchi } 11729d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_link_state, pr_val, sizeof (link_state_t)); 11739d26e4fcSRobert Mustacchi break; 11749d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG: 11759d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 11769d26e4fcSRobert Mustacchi ret = EOVERFLOW; 11779d26e4fcSRobert Mustacchi break; 11789d26e4fcSRobert Mustacchi } 11799d26e4fcSRobert Mustacchi u8 = pr_val; 11809d26e4fcSRobert Mustacchi *u8 = 1; 11819d26e4fcSRobert Mustacchi break; 11829d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL: 11839d26e4fcSRobert Mustacchi /* 11849d26e4fcSRobert Mustacchi * Because we don't currently support hardware flow control, we 11859d26e4fcSRobert Mustacchi * just hardcode this to be none. 11869d26e4fcSRobert Mustacchi */ 11879d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_flowctrl_t)) { 11889d26e4fcSRobert Mustacchi ret = EOVERFLOW; 11899d26e4fcSRobert Mustacchi break; 11909d26e4fcSRobert Mustacchi } 11919d26e4fcSRobert Mustacchi fctl = LINK_FLOWCTRL_NONE; 11929d26e4fcSRobert Mustacchi bcopy(&fctl, pr_val, sizeof (link_flowctrl_t)); 11939d26e4fcSRobert Mustacchi break; 11949d26e4fcSRobert Mustacchi case MAC_PROP_MTU: 11959d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint32_t)) { 11969d26e4fcSRobert Mustacchi ret = EOVERFLOW; 11979d26e4fcSRobert Mustacchi break; 11989d26e4fcSRobert Mustacchi } 11999d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t)); 12009d26e4fcSRobert Mustacchi break; 120111a00484SPaul Winder case MAC_PROP_ADV_FEC_CAP: 120211a00484SPaul Winder if (pr_valsize < sizeof (link_fec_t)) { 120311a00484SPaul Winder ret = EOVERFLOW; 120411a00484SPaul Winder break; 120511a00484SPaul Winder } 120611a00484SPaul Winder *(link_fec_t *)pr_val = 120711a00484SPaul Winder i40e_fec_to_linkfec(&i40e->i40e_hw_space); 120811a00484SPaul Winder break; 120911a00484SPaul Winder case MAC_PROP_EN_FEC_CAP: 121011a00484SPaul Winder if (pr_valsize < sizeof (link_fec_t)) { 121111a00484SPaul Winder ret = EOVERFLOW; 121211a00484SPaul Winder break; 121311a00484SPaul Winder } 121411a00484SPaul Winder *(link_fec_t *)pr_val = i40e->i40e_fec_requested; 121511a00484SPaul Winder break; 12169d26e4fcSRobert Mustacchi 12179d26e4fcSRobert Mustacchi /* 12189d26e4fcSRobert Mustacchi * Because we don't let users control the speeds we may auto-negotiate 12199d26e4fcSRobert Mustacchi * to, the values of the ADV_ and EN_ will always be the same. 12209d26e4fcSRobert Mustacchi */ 12219d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP: 12229d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP: 12239d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 12249d26e4fcSRobert Mustacchi ret = EOVERFLOW; 12259d26e4fcSRobert Mustacchi break; 12269d26e4fcSRobert Mustacchi } 12279d26e4fcSRobert Mustacchi u8 = pr_val; 12289d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0; 12299d26e4fcSRobert Mustacchi break; 12309d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP: 12319d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP: 12329d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 12339d26e4fcSRobert Mustacchi ret = EOVERFLOW; 12349d26e4fcSRobert Mustacchi break; 12359d26e4fcSRobert Mustacchi } 12369d26e4fcSRobert Mustacchi u8 = pr_val; 12379d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0; 12389d26e4fcSRobert Mustacchi break; 1239*df36e06dSRobert Mustacchi case MAC_PROP_ADV_2500FDX_CAP: 1240*df36e06dSRobert Mustacchi case MAC_PROP_EN_2500FDX_CAP: 1241*df36e06dSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 1242*df36e06dSRobert Mustacchi ret = EOVERFLOW; 1243*df36e06dSRobert Mustacchi break; 1244*df36e06dSRobert Mustacchi } 1245*df36e06dSRobert Mustacchi u8 = pr_val; 1246*df36e06dSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_2_5GB) != 0; 1247*df36e06dSRobert Mustacchi break; 1248*df36e06dSRobert Mustacchi case MAC_PROP_ADV_5000FDX_CAP: 1249*df36e06dSRobert Mustacchi case MAC_PROP_EN_5000FDX_CAP: 1250*df36e06dSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 1251*df36e06dSRobert Mustacchi ret = EOVERFLOW; 1252*df36e06dSRobert Mustacchi break; 1253*df36e06dSRobert Mustacchi } 1254*df36e06dSRobert Mustacchi u8 = pr_val; 1255*df36e06dSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_5GB) != 0; 1256*df36e06dSRobert Mustacchi break; 12579d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP: 12589d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP: 12599d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 12609d26e4fcSRobert Mustacchi ret = EOVERFLOW; 12619d26e4fcSRobert Mustacchi break; 12629d26e4fcSRobert Mustacchi } 12639d26e4fcSRobert Mustacchi u8 = pr_val; 12649d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0; 12659d26e4fcSRobert Mustacchi break; 12663d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP: 12673d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP: 12683d75a287SRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 12693d75a287SRobert Mustacchi ret = EOVERFLOW; 12703d75a287SRobert Mustacchi break; 12713d75a287SRobert Mustacchi } 12723d75a287SRobert Mustacchi u8 = pr_val; 12733d75a287SRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0; 12743d75a287SRobert Mustacchi break; 12759d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP: 12769d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP: 12779d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 12789d26e4fcSRobert Mustacchi ret = EOVERFLOW; 12799d26e4fcSRobert Mustacchi break; 12809d26e4fcSRobert Mustacchi } 12819d26e4fcSRobert Mustacchi u8 = pr_val; 12829d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0; 12839d26e4fcSRobert Mustacchi break; 12849d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE: 12859d26e4fcSRobert Mustacchi ret = i40e_m_getprop_private(i40e, pr_name, pr_valsize, pr_val); 12869d26e4fcSRobert Mustacchi break; 12879d26e4fcSRobert Mustacchi default: 12889d26e4fcSRobert Mustacchi ret = ENOTSUP; 12899d26e4fcSRobert Mustacchi break; 12909d26e4fcSRobert Mustacchi } 12919d26e4fcSRobert Mustacchi 12929d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 12939d26e4fcSRobert Mustacchi 12949d26e4fcSRobert Mustacchi return (ret); 12959d26e4fcSRobert Mustacchi } 12969d26e4fcSRobert Mustacchi 12979d26e4fcSRobert Mustacchi static void 12989d26e4fcSRobert Mustacchi i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, 12999d26e4fcSRobert Mustacchi mac_prop_info_handle_t prh) 13009d26e4fcSRobert Mustacchi { 13019d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 13029d26e4fcSRobert Mustacchi 13039d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 13049d26e4fcSRobert Mustacchi 13059d26e4fcSRobert Mustacchi switch (pr_num) { 13069d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX: 13079d26e4fcSRobert Mustacchi case MAC_PROP_SPEED: 13089d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13099d26e4fcSRobert Mustacchi break; 13109d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL: 13119d26e4fcSRobert Mustacchi /* 13129d26e4fcSRobert Mustacchi * At the moment, the driver doesn't support flow control, hence 13139d26e4fcSRobert Mustacchi * why this is set to read-only and none. 13149d26e4fcSRobert Mustacchi */ 13159d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13169d26e4fcSRobert Mustacchi mac_prop_info_set_default_link_flowctrl(prh, 13179d26e4fcSRobert Mustacchi LINK_FLOWCTRL_NONE); 13189d26e4fcSRobert Mustacchi break; 13199d26e4fcSRobert Mustacchi case MAC_PROP_MTU: 13209d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU); 13219d26e4fcSRobert Mustacchi break; 132211a00484SPaul Winder case MAC_PROP_ADV_FEC_CAP: 132311a00484SPaul Winder mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 132411a00484SPaul Winder if (i40e_is_25G_device(i40e->i40e_hw_space.device_id)) 132511a00484SPaul Winder mac_prop_info_set_default_fec(prh, LINK_FEC_AUTO); 132611a00484SPaul Winder break; 132711a00484SPaul Winder case MAC_PROP_EN_FEC_CAP: 132811a00484SPaul Winder if (i40e_is_25G_device(i40e->i40e_hw_space.device_id)) { 132911a00484SPaul Winder mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 133011a00484SPaul Winder mac_prop_info_set_default_fec(prh, LINK_FEC_AUTO); 133111a00484SPaul Winder } else { 133211a00484SPaul Winder mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 133311a00484SPaul Winder } 133411a00484SPaul Winder break; 13359d26e4fcSRobert Mustacchi 13369d26e4fcSRobert Mustacchi /* 13379d26e4fcSRobert Mustacchi * We set the defaults for these based upon the phy's ability to 13389d26e4fcSRobert Mustacchi * support the speeds. Note, auto-negotiation is required for fiber, 13399d26e4fcSRobert Mustacchi * hence it is read-only and always enabled. When we have access to 13409d26e4fcSRobert Mustacchi * copper phys we can revisit this. 13419d26e4fcSRobert Mustacchi */ 13429d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG: 13439d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13449d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 1); 13459d26e4fcSRobert Mustacchi break; 13469d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP: 13479d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13489d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13499d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0); 13509d26e4fcSRobert Mustacchi break; 13519d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP: 13529d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13539d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13549d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0); 13559d26e4fcSRobert Mustacchi break; 13569d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP: 13579d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13589d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13599d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0); 13609d26e4fcSRobert Mustacchi break; 13619d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP: 13629d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13639d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13649d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0); 13659d26e4fcSRobert Mustacchi break; 13669d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP: 13679d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13689d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13699d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0); 13709d26e4fcSRobert Mustacchi break; 13719d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP: 13729d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13739d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13749d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0); 13759d26e4fcSRobert Mustacchi break; 13763d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP: 13773d75a287SRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13783d75a287SRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13793d75a287SRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0); 13803d75a287SRobert Mustacchi break; 13813d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP: 13823d75a287SRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13833d75a287SRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13843d75a287SRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0); 13853d75a287SRobert Mustacchi break; 13869d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP: 13879d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13889d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13899d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0); 13909d26e4fcSRobert Mustacchi break; 13919d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP: 13929d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 13939d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 13949d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0); 13959d26e4fcSRobert Mustacchi break; 13969d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE: 13979d26e4fcSRobert Mustacchi i40e_m_propinfo_private(i40e, pr_name, prh); 13989d26e4fcSRobert Mustacchi break; 13999d26e4fcSRobert Mustacchi default: 14009d26e4fcSRobert Mustacchi break; 14019d26e4fcSRobert Mustacchi } 14029d26e4fcSRobert Mustacchi 14039d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 14049d26e4fcSRobert Mustacchi } 14059d26e4fcSRobert Mustacchi 14069d26e4fcSRobert Mustacchi #define I40E_M_CALLBACK_FLAGS \ 14079d26e4fcSRobert Mustacchi (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO) 14089d26e4fcSRobert Mustacchi 14099d26e4fcSRobert Mustacchi static mac_callbacks_t i40e_m_callbacks = { 14109d26e4fcSRobert Mustacchi I40E_M_CALLBACK_FLAGS, 14119d26e4fcSRobert Mustacchi i40e_m_stat, 14129d26e4fcSRobert Mustacchi i40e_m_start, 14139d26e4fcSRobert Mustacchi i40e_m_stop, 14149d26e4fcSRobert Mustacchi i40e_m_promisc, 14159d26e4fcSRobert Mustacchi i40e_m_multicast, 14169d26e4fcSRobert Mustacchi NULL, 14179d26e4fcSRobert Mustacchi NULL, 14189d26e4fcSRobert Mustacchi NULL, 14199d26e4fcSRobert Mustacchi i40e_m_ioctl, 14209d26e4fcSRobert Mustacchi i40e_m_getcapab, 14219d26e4fcSRobert Mustacchi NULL, 14229d26e4fcSRobert Mustacchi NULL, 14239d26e4fcSRobert Mustacchi i40e_m_setprop, 14249d26e4fcSRobert Mustacchi i40e_m_getprop, 14259d26e4fcSRobert Mustacchi i40e_m_propinfo 14269d26e4fcSRobert Mustacchi }; 14279d26e4fcSRobert Mustacchi 14289d26e4fcSRobert Mustacchi boolean_t 14299d26e4fcSRobert Mustacchi i40e_register_mac(i40e_t *i40e) 14309d26e4fcSRobert Mustacchi { 14319d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space; 14329d26e4fcSRobert Mustacchi int status; 14339d26e4fcSRobert Mustacchi mac_register_t *mac = mac_alloc(MAC_VERSION); 14349d26e4fcSRobert Mustacchi 14359d26e4fcSRobert Mustacchi if (mac == NULL) 14369d26e4fcSRobert Mustacchi return (B_FALSE); 14379d26e4fcSRobert Mustacchi 14389d26e4fcSRobert Mustacchi mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 14399d26e4fcSRobert Mustacchi mac->m_driver = i40e; 14409d26e4fcSRobert Mustacchi mac->m_dip = i40e->i40e_dip; 14419d26e4fcSRobert Mustacchi mac->m_src_addr = hw->mac.addr; 14429d26e4fcSRobert Mustacchi mac->m_callbacks = &i40e_m_callbacks; 14439d26e4fcSRobert Mustacchi mac->m_min_sdu = 0; 14449d26e4fcSRobert Mustacchi mac->m_max_sdu = i40e->i40e_sdu; 14459d26e4fcSRobert Mustacchi mac->m_margin = VLAN_TAGSZ; 14469d26e4fcSRobert Mustacchi mac->m_priv_props = i40e_priv_props; 14479d26e4fcSRobert Mustacchi mac->m_v12n = MAC_VIRT_LEVEL1; 14489d26e4fcSRobert Mustacchi 14499d26e4fcSRobert Mustacchi status = mac_register(mac, &i40e->i40e_mac_hdl); 14509d26e4fcSRobert Mustacchi if (status != 0) 14519d26e4fcSRobert Mustacchi i40e_error(i40e, "mac_register() returned %d", status); 14529d26e4fcSRobert Mustacchi mac_free(mac); 14539d26e4fcSRobert Mustacchi 14549d26e4fcSRobert Mustacchi return (status == 0); 14559d26e4fcSRobert Mustacchi } 1456