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. 14338749cbSRobert Mustacchi * Copyright (c) 2017, Joyent, Inc. 15396505afSPaul Winder * Copyright 2017 Tegile Systems, Inc. All rights reserved. 169d26e4fcSRobert Mustacchi */ 179d26e4fcSRobert Mustacchi 189d26e4fcSRobert Mustacchi /* 199d26e4fcSRobert Mustacchi * For more information, please see the big theory statement in i40e_main.c. 209d26e4fcSRobert Mustacchi */ 219d26e4fcSRobert Mustacchi 229d26e4fcSRobert Mustacchi #include "i40e_sw.h" 239d26e4fcSRobert Mustacchi 249d26e4fcSRobert Mustacchi #define I40E_PROP_RX_DMA_THRESH "_rx_dma_threshold" 259d26e4fcSRobert Mustacchi #define I40E_PROP_TX_DMA_THRESH "_tx_dma_threshold" 269d26e4fcSRobert Mustacchi #define I40E_PROP_RX_ITR "_rx_intr_throttle" 279d26e4fcSRobert Mustacchi #define I40E_PROP_TX_ITR "_tx_intr_throttle" 289d26e4fcSRobert Mustacchi #define I40E_PROP_OTHER_ITR "_other_intr_throttle" 299d26e4fcSRobert Mustacchi 309d26e4fcSRobert Mustacchi char *i40e_priv_props[] = { 319d26e4fcSRobert Mustacchi I40E_PROP_RX_DMA_THRESH, 329d26e4fcSRobert Mustacchi I40E_PROP_TX_DMA_THRESH, 339d26e4fcSRobert Mustacchi I40E_PROP_RX_ITR, 349d26e4fcSRobert Mustacchi I40E_PROP_TX_ITR, 359d26e4fcSRobert Mustacchi I40E_PROP_OTHER_ITR, 369d26e4fcSRobert Mustacchi NULL 379d26e4fcSRobert Mustacchi }; 389d26e4fcSRobert Mustacchi 399d26e4fcSRobert Mustacchi static int 409d26e4fcSRobert Mustacchi i40e_group_remove_mac(void *arg, const uint8_t *mac_addr) 419d26e4fcSRobert Mustacchi { 429d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 439d26e4fcSRobert Mustacchi struct i40e_aqc_remove_macvlan_element_data filt; 449d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space; 459d26e4fcSRobert Mustacchi int ret, i, last; 469d26e4fcSRobert Mustacchi i40e_uaddr_t *iua; 479d26e4fcSRobert Mustacchi 489d26e4fcSRobert Mustacchi if (I40E_IS_MULTICAST(mac_addr)) 499d26e4fcSRobert Mustacchi return (EINVAL); 509d26e4fcSRobert Mustacchi 519d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 529d26e4fcSRobert Mustacchi 539d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) { 549d26e4fcSRobert Mustacchi ret = ECANCELED; 559d26e4fcSRobert Mustacchi goto done; 569d26e4fcSRobert Mustacchi } 579d26e4fcSRobert Mustacchi 589d26e4fcSRobert Mustacchi for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) { 599d26e4fcSRobert Mustacchi if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac, 609d26e4fcSRobert Mustacchi ETHERADDRL) == 0) 619d26e4fcSRobert Mustacchi break; 629d26e4fcSRobert Mustacchi } 639d26e4fcSRobert Mustacchi 649d26e4fcSRobert Mustacchi if (i == i40e->i40e_resources.ifr_nmacfilt_used) { 659d26e4fcSRobert Mustacchi ret = ENOENT; 669d26e4fcSRobert Mustacchi goto done; 679d26e4fcSRobert Mustacchi } 689d26e4fcSRobert Mustacchi 699d26e4fcSRobert Mustacchi iua = &i40e->i40e_uaddrs[i]; 709d26e4fcSRobert Mustacchi ASSERT(i40e->i40e_resources.ifr_nmacfilt_used > 0); 719d26e4fcSRobert Mustacchi 729d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt)); 739d26e4fcSRobert Mustacchi bcopy(mac_addr, filt.mac_addr, ETHERADDRL); 749d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH | 759d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; 769d26e4fcSRobert Mustacchi 779d26e4fcSRobert Mustacchi if (i40e_aq_remove_macvlan(hw, iua->iua_vsi, &filt, 1, NULL) != 789d26e4fcSRobert Mustacchi I40E_SUCCESS) { 799d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to remove mac address " 809d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d", 819d26e4fcSRobert Mustacchi mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], 829d26e4fcSRobert Mustacchi mac_addr[4], mac_addr[5], filt.error_code); 839d26e4fcSRobert Mustacchi ret = EIO; 849d26e4fcSRobert Mustacchi goto done; 859d26e4fcSRobert Mustacchi } 869d26e4fcSRobert Mustacchi 879d26e4fcSRobert Mustacchi last = i40e->i40e_resources.ifr_nmacfilt_used - 1; 889d26e4fcSRobert Mustacchi if (i != last) { 899d26e4fcSRobert Mustacchi i40e_uaddr_t *src = &i40e->i40e_uaddrs[last]; 909d26e4fcSRobert Mustacchi bcopy(src, iua, sizeof (i40e_uaddr_t)); 919d26e4fcSRobert Mustacchi } 929d26e4fcSRobert Mustacchi 939d26e4fcSRobert Mustacchi /* 949d26e4fcSRobert Mustacchi * Set the multicast bit in the last one to indicate to ourselves that 959d26e4fcSRobert Mustacchi * it's invalid. 969d26e4fcSRobert Mustacchi */ 979d26e4fcSRobert Mustacchi bzero(&i40e->i40e_uaddrs[last], sizeof (i40e_uaddr_t)); 989d26e4fcSRobert Mustacchi i40e->i40e_uaddrs[last].iua_mac[0] = 0x01; 999d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt_used--; 1009d26e4fcSRobert Mustacchi ret = 0; 1019d26e4fcSRobert Mustacchi done: 1029d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 1039d26e4fcSRobert Mustacchi 1049d26e4fcSRobert Mustacchi return (ret); 1059d26e4fcSRobert Mustacchi } 1069d26e4fcSRobert Mustacchi 1079d26e4fcSRobert Mustacchi static int 1089d26e4fcSRobert Mustacchi i40e_group_add_mac(void *arg, const uint8_t *mac_addr) 1099d26e4fcSRobert Mustacchi { 1109d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 1119d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space; 1129d26e4fcSRobert Mustacchi int i, ret; 1139d26e4fcSRobert Mustacchi i40e_uaddr_t *iua; 1149d26e4fcSRobert Mustacchi struct i40e_aqc_add_macvlan_element_data filt; 1159d26e4fcSRobert Mustacchi 1169d26e4fcSRobert Mustacchi if (I40E_IS_MULTICAST(mac_addr)) 1179d26e4fcSRobert Mustacchi return (EINVAL); 1189d26e4fcSRobert Mustacchi 1199d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 1209d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) { 1219d26e4fcSRobert Mustacchi ret = ECANCELED; 1229d26e4fcSRobert Mustacchi goto done; 1239d26e4fcSRobert Mustacchi } 1249d26e4fcSRobert Mustacchi 1259d26e4fcSRobert Mustacchi if (i40e->i40e_resources.ifr_nmacfilt == 1269d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt_used) { 1279d26e4fcSRobert Mustacchi ret = ENOSPC; 1289d26e4fcSRobert Mustacchi goto done; 1299d26e4fcSRobert Mustacchi } 1309d26e4fcSRobert Mustacchi 1319d26e4fcSRobert Mustacchi for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) { 1329d26e4fcSRobert Mustacchi if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac, 1339d26e4fcSRobert Mustacchi ETHERADDRL) == 0) { 1349d26e4fcSRobert Mustacchi ret = EEXIST; 1359d26e4fcSRobert Mustacchi goto done; 1369d26e4fcSRobert Mustacchi } 1379d26e4fcSRobert Mustacchi } 1389d26e4fcSRobert Mustacchi 1399d26e4fcSRobert Mustacchi /* 1409d26e4fcSRobert Mustacchi * Note, the general use of the i40e_vsi_id will have to be refactored 1419d26e4fcSRobert Mustacchi * when we have proper group support. 1429d26e4fcSRobert Mustacchi */ 1439d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt)); 1449d26e4fcSRobert Mustacchi bcopy(mac_addr, filt.mac_addr, ETHERADDRL); 1459d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH | 1469d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; 1479d26e4fcSRobert Mustacchi 1489d26e4fcSRobert Mustacchi if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1, 1499d26e4fcSRobert Mustacchi NULL)) != I40E_SUCCESS) { 1509d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to add mac address " 1519d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d", 1529d26e4fcSRobert Mustacchi mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], 1539d26e4fcSRobert Mustacchi mac_addr[4], mac_addr[5], ret); 1549d26e4fcSRobert Mustacchi ret = EIO; 1559d26e4fcSRobert Mustacchi goto done; 1569d26e4fcSRobert Mustacchi } 1579d26e4fcSRobert Mustacchi 1589d26e4fcSRobert Mustacchi iua = &i40e->i40e_uaddrs[i40e->i40e_resources.ifr_nmacfilt_used]; 1599d26e4fcSRobert Mustacchi bcopy(mac_addr, iua->iua_mac, ETHERADDRL); 1609d26e4fcSRobert Mustacchi iua->iua_vsi = i40e->i40e_vsi_id; 1619d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt_used++; 1629d26e4fcSRobert Mustacchi ASSERT(i40e->i40e_resources.ifr_nmacfilt_used <= 1639d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmacfilt); 1649d26e4fcSRobert Mustacchi ret = 0; 1659d26e4fcSRobert Mustacchi done: 1669d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 1679d26e4fcSRobert Mustacchi return (ret); 1689d26e4fcSRobert Mustacchi } 1699d26e4fcSRobert Mustacchi 1709d26e4fcSRobert Mustacchi static int 1719d26e4fcSRobert Mustacchi i40e_m_start(void *arg) 1729d26e4fcSRobert Mustacchi { 1739d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 1749d26e4fcSRobert Mustacchi int rc = 0; 1759d26e4fcSRobert Mustacchi 1769d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 1779d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) { 1789d26e4fcSRobert Mustacchi rc = ECANCELED; 1799d26e4fcSRobert Mustacchi goto done; 1809d26e4fcSRobert Mustacchi } 1819d26e4fcSRobert Mustacchi 1829d26e4fcSRobert Mustacchi if (!i40e_start(i40e, B_TRUE)) { 1839d26e4fcSRobert Mustacchi rc = EIO; 1849d26e4fcSRobert Mustacchi goto done; 1859d26e4fcSRobert Mustacchi } 1869d26e4fcSRobert Mustacchi 1879d26e4fcSRobert Mustacchi atomic_or_32(&i40e->i40e_state, I40E_STARTED); 1889d26e4fcSRobert Mustacchi done: 1899d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 1909d26e4fcSRobert Mustacchi 1919d26e4fcSRobert Mustacchi return (rc); 1929d26e4fcSRobert Mustacchi } 1939d26e4fcSRobert Mustacchi 1949d26e4fcSRobert Mustacchi static void 1959d26e4fcSRobert Mustacchi i40e_m_stop(void *arg) 1969d26e4fcSRobert Mustacchi { 1979d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 1989d26e4fcSRobert Mustacchi 1999d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 2009d26e4fcSRobert Mustacchi 2019d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) 2029d26e4fcSRobert Mustacchi goto done; 2039d26e4fcSRobert Mustacchi 2049d26e4fcSRobert Mustacchi atomic_and_32(&i40e->i40e_state, ~I40E_STARTED); 2059d26e4fcSRobert Mustacchi i40e_stop(i40e, B_TRUE); 2069d26e4fcSRobert Mustacchi done: 2079d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 2089d26e4fcSRobert Mustacchi } 2099d26e4fcSRobert Mustacchi 2109d26e4fcSRobert Mustacchi /* 2119d26e4fcSRobert Mustacchi * Enable and disable promiscuous mode as requested. We have to toggle both 2129d26e4fcSRobert Mustacchi * unicast and multicast. Note that multicast may already be enabled due to the 2139d26e4fcSRobert Mustacchi * i40e_m_multicast may toggle it itself. See i40e_main.c for more information 2149d26e4fcSRobert Mustacchi * on this. 2159d26e4fcSRobert Mustacchi */ 2169d26e4fcSRobert Mustacchi static int 2179d26e4fcSRobert Mustacchi i40e_m_promisc(void *arg, boolean_t on) 2189d26e4fcSRobert Mustacchi { 2199d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 2209d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space; 2219d26e4fcSRobert Mustacchi int ret = 0, err = 0; 2229d26e4fcSRobert Mustacchi 2239d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 2249d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) { 2259d26e4fcSRobert Mustacchi ret = ECANCELED; 2269d26e4fcSRobert Mustacchi goto done; 2279d26e4fcSRobert Mustacchi } 2289d26e4fcSRobert Mustacchi 2299d26e4fcSRobert Mustacchi 2309d26e4fcSRobert Mustacchi ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id, 2313d75a287SRobert Mustacchi on, NULL, B_FALSE); 2329d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) { 2339d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to %s unicast promiscuity on " 2349d26e4fcSRobert Mustacchi "the default VSI: %d", on == B_TRUE ? "enable" : "disable", 2359d26e4fcSRobert Mustacchi ret); 2369d26e4fcSRobert Mustacchi err = EIO; 2379d26e4fcSRobert Mustacchi goto done; 2389d26e4fcSRobert Mustacchi } 2399d26e4fcSRobert Mustacchi 2409d26e4fcSRobert Mustacchi /* 2419d26e4fcSRobert Mustacchi * If we have a non-zero mcast_promisc_count, then it has already been 2429d26e4fcSRobert Mustacchi * enabled or we need to leave it that way and not touch it. 2439d26e4fcSRobert Mustacchi */ 2449d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count > 0) { 2459d26e4fcSRobert Mustacchi i40e->i40e_promisc_on = on; 2469d26e4fcSRobert Mustacchi goto done; 2479d26e4fcSRobert Mustacchi } 2489d26e4fcSRobert Mustacchi 2499d26e4fcSRobert Mustacchi ret = i40e_aq_set_vsi_multicast_promiscuous(hw, i40e->i40e_vsi_id, 2509d26e4fcSRobert Mustacchi on, NULL); 2519d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) { 2529d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to %s multicast promiscuity on " 2539d26e4fcSRobert Mustacchi "the default VSI: %d", on == B_TRUE ? "enable" : "disable", 2549d26e4fcSRobert Mustacchi ret); 2559d26e4fcSRobert Mustacchi 2569d26e4fcSRobert Mustacchi /* 2579d26e4fcSRobert Mustacchi * Try our best to put us back into a state that MAC expects us 2589d26e4fcSRobert Mustacchi * to be in. 2599d26e4fcSRobert Mustacchi */ 2609d26e4fcSRobert Mustacchi ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id, 2613d75a287SRobert Mustacchi !on, NULL, B_FALSE); 2629d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) { 2639d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to %s unicast promiscuity on " 2649d26e4fcSRobert Mustacchi "the default VSI after toggling multicast failed: " 2659d26e4fcSRobert Mustacchi "%d", on == B_TRUE ? "disable" : "enable", ret); 2669d26e4fcSRobert Mustacchi } 2679d26e4fcSRobert Mustacchi 2689d26e4fcSRobert Mustacchi err = EIO; 2699d26e4fcSRobert Mustacchi goto done; 2709d26e4fcSRobert Mustacchi } else { 2719d26e4fcSRobert Mustacchi i40e->i40e_promisc_on = on; 2729d26e4fcSRobert Mustacchi } 2739d26e4fcSRobert Mustacchi 2749d26e4fcSRobert Mustacchi done: 2759d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 2769d26e4fcSRobert Mustacchi return (err); 2779d26e4fcSRobert Mustacchi } 2789d26e4fcSRobert Mustacchi 2799d26e4fcSRobert Mustacchi /* 2809d26e4fcSRobert Mustacchi * See the big theory statement in i40e_main.c for multicast address management. 2819d26e4fcSRobert Mustacchi */ 2829d26e4fcSRobert Mustacchi static int 2839d26e4fcSRobert Mustacchi i40e_multicast_add(i40e_t *i40e, const uint8_t *multicast_address) 2849d26e4fcSRobert Mustacchi { 2859d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space; 2869d26e4fcSRobert Mustacchi struct i40e_aqc_add_macvlan_element_data filt; 2879d26e4fcSRobert Mustacchi i40e_maddr_t *mc; 2889d26e4fcSRobert Mustacchi int ret; 2899d26e4fcSRobert Mustacchi 2909d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock)); 2919d26e4fcSRobert Mustacchi 2929d26e4fcSRobert Mustacchi if (i40e->i40e_resources.ifr_nmcastfilt_used == 2939d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmcastfilt) { 2949d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count == 0 && 2959d26e4fcSRobert Mustacchi i40e->i40e_promisc_on == B_FALSE) { 2969d26e4fcSRobert Mustacchi ret = i40e_aq_set_vsi_multicast_promiscuous(hw, 2979d26e4fcSRobert Mustacchi i40e->i40e_vsi_id, B_TRUE, NULL); 2989d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) { 2999d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to enable multicast " 3009d26e4fcSRobert Mustacchi "promiscuous mode on VSI %d: %d", 3019d26e4fcSRobert Mustacchi i40e->i40e_vsi_id, ret); 3029d26e4fcSRobert Mustacchi return (EIO); 3039d26e4fcSRobert Mustacchi } 3049d26e4fcSRobert Mustacchi } 3059d26e4fcSRobert Mustacchi i40e->i40e_mcast_promisc_count++; 3069d26e4fcSRobert Mustacchi return (0); 3079d26e4fcSRobert Mustacchi } 3089d26e4fcSRobert Mustacchi 3099d26e4fcSRobert Mustacchi mc = &i40e->i40e_maddrs[i40e->i40e_resources.ifr_nmcastfilt_used]; 3109d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt)); 3119d26e4fcSRobert Mustacchi bcopy(multicast_address, filt.mac_addr, ETHERADDRL); 3129d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH | 3139d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; 3149d26e4fcSRobert Mustacchi 3159d26e4fcSRobert Mustacchi if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1, 3169d26e4fcSRobert Mustacchi NULL)) != I40E_SUCCESS) { 3179d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to add mac address " 3189d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x to multicast filter: %d", 3199d26e4fcSRobert Mustacchi multicast_address[0], multicast_address[1], 3209d26e4fcSRobert Mustacchi multicast_address[2], multicast_address[3], 3219d26e4fcSRobert Mustacchi multicast_address[4], multicast_address[5], 3229d26e4fcSRobert Mustacchi ret); 3239d26e4fcSRobert Mustacchi return (EIO); 3249d26e4fcSRobert Mustacchi } 3259d26e4fcSRobert Mustacchi 3269d26e4fcSRobert Mustacchi bcopy(multicast_address, mc->ima_mac, ETHERADDRL); 3279d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmcastfilt_used++; 3289d26e4fcSRobert Mustacchi return (0); 3299d26e4fcSRobert Mustacchi } 3309d26e4fcSRobert Mustacchi 3319d26e4fcSRobert Mustacchi /* 3329d26e4fcSRobert Mustacchi * See the big theory statement in i40e_main.c for multicast address management. 3339d26e4fcSRobert Mustacchi */ 3349d26e4fcSRobert Mustacchi static int 3359d26e4fcSRobert Mustacchi i40e_multicast_remove(i40e_t *i40e, const uint8_t *multicast_address) 3369d26e4fcSRobert Mustacchi { 3379d26e4fcSRobert Mustacchi int i, ret; 3389d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space; 3399d26e4fcSRobert Mustacchi 3409d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock)); 3419d26e4fcSRobert Mustacchi 3429d26e4fcSRobert Mustacchi for (i = 0; i < i40e->i40e_resources.ifr_nmcastfilt_used; i++) { 3439d26e4fcSRobert Mustacchi struct i40e_aqc_remove_macvlan_element_data filt; 3449d26e4fcSRobert Mustacchi int last; 3459d26e4fcSRobert Mustacchi 3469d26e4fcSRobert Mustacchi if (bcmp(multicast_address, i40e->i40e_maddrs[i].ima_mac, 3479d26e4fcSRobert Mustacchi ETHERADDRL) != 0) { 3489d26e4fcSRobert Mustacchi continue; 3499d26e4fcSRobert Mustacchi } 3509d26e4fcSRobert Mustacchi 3519d26e4fcSRobert Mustacchi bzero(&filt, sizeof (filt)); 3529d26e4fcSRobert Mustacchi bcopy(multicast_address, filt.mac_addr, ETHERADDRL); 3539d26e4fcSRobert Mustacchi filt.flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH | 3549d26e4fcSRobert Mustacchi I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; 3559d26e4fcSRobert Mustacchi 3569d26e4fcSRobert Mustacchi if (i40e_aq_remove_macvlan(hw, i40e->i40e_vsi_id, 3579d26e4fcSRobert Mustacchi &filt, 1, NULL) != I40E_SUCCESS) { 3589d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to remove mac address " 3599d26e4fcSRobert Mustacchi "%2x:%2x:%2x:%2x:%2x:%2x from multicast " 3609d26e4fcSRobert Mustacchi "filter: %d", 3619d26e4fcSRobert Mustacchi multicast_address[0], multicast_address[1], 3629d26e4fcSRobert Mustacchi multicast_address[2], multicast_address[3], 3639d26e4fcSRobert Mustacchi multicast_address[4], multicast_address[5], 3649d26e4fcSRobert Mustacchi filt.error_code); 3659d26e4fcSRobert Mustacchi return (EIO); 3669d26e4fcSRobert Mustacchi } 3679d26e4fcSRobert Mustacchi 3689d26e4fcSRobert Mustacchi last = i40e->i40e_resources.ifr_nmcastfilt_used - 1; 3699d26e4fcSRobert Mustacchi if (i != last) { 3709d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_maddrs[last], &i40e->i40e_maddrs[i], 3719d26e4fcSRobert Mustacchi sizeof (i40e_maddr_t)); 3729d26e4fcSRobert Mustacchi bzero(&i40e->i40e_maddrs[last], sizeof (i40e_maddr_t)); 3739d26e4fcSRobert Mustacchi } 3749d26e4fcSRobert Mustacchi 3759d26e4fcSRobert Mustacchi ASSERT(i40e->i40e_resources.ifr_nmcastfilt_used > 0); 3769d26e4fcSRobert Mustacchi i40e->i40e_resources.ifr_nmcastfilt_used--; 3779d26e4fcSRobert Mustacchi return (0); 3789d26e4fcSRobert Mustacchi } 3799d26e4fcSRobert Mustacchi 3809d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count > 0) { 3819d26e4fcSRobert Mustacchi if (i40e->i40e_mcast_promisc_count == 1 && 3829d26e4fcSRobert Mustacchi i40e->i40e_promisc_on == B_FALSE) { 3839d26e4fcSRobert Mustacchi ret = i40e_aq_set_vsi_multicast_promiscuous(hw, 3849d26e4fcSRobert Mustacchi i40e->i40e_vsi_id, B_FALSE, NULL); 3859d26e4fcSRobert Mustacchi if (ret != I40E_SUCCESS) { 3869d26e4fcSRobert Mustacchi i40e_error(i40e, "failed to disable " 3879d26e4fcSRobert Mustacchi "multicast promiscuous mode on VSI %d: %d", 3889d26e4fcSRobert Mustacchi i40e->i40e_vsi_id, ret); 3899d26e4fcSRobert Mustacchi return (EIO); 3909d26e4fcSRobert Mustacchi } 3919d26e4fcSRobert Mustacchi } 3929d26e4fcSRobert Mustacchi i40e->i40e_mcast_promisc_count--; 3939d26e4fcSRobert Mustacchi 3949d26e4fcSRobert Mustacchi return (0); 3959d26e4fcSRobert Mustacchi } 3969d26e4fcSRobert Mustacchi 3979d26e4fcSRobert Mustacchi return (ENOENT); 3989d26e4fcSRobert Mustacchi } 3999d26e4fcSRobert Mustacchi 4009d26e4fcSRobert Mustacchi static int 4019d26e4fcSRobert Mustacchi i40e_m_multicast(void *arg, boolean_t add, const uint8_t *multicast_address) 4029d26e4fcSRobert Mustacchi { 4039d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 4049d26e4fcSRobert Mustacchi int rc; 4059d26e4fcSRobert Mustacchi 4069d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 4079d26e4fcSRobert Mustacchi 4089d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) { 4099d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 4109d26e4fcSRobert Mustacchi return (ECANCELED); 4119d26e4fcSRobert Mustacchi } 4129d26e4fcSRobert Mustacchi 4139d26e4fcSRobert Mustacchi if (add == B_TRUE) { 4149d26e4fcSRobert Mustacchi rc = i40e_multicast_add(i40e, multicast_address); 4159d26e4fcSRobert Mustacchi } else { 4169d26e4fcSRobert Mustacchi rc = i40e_multicast_remove(i40e, multicast_address); 4179d26e4fcSRobert Mustacchi } 4189d26e4fcSRobert Mustacchi 4199d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 4209d26e4fcSRobert Mustacchi return (rc); 4219d26e4fcSRobert Mustacchi } 4229d26e4fcSRobert Mustacchi 4239d26e4fcSRobert Mustacchi /* ARGSUSED */ 4249d26e4fcSRobert Mustacchi static void 4259d26e4fcSRobert Mustacchi i40e_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 4269d26e4fcSRobert Mustacchi { 4279d26e4fcSRobert Mustacchi /* 4289d26e4fcSRobert Mustacchi * At this time, we don't support toggling i40e into loopback mode. It's 4299d26e4fcSRobert Mustacchi * questionable how much value this has when there's no clear way to 4309d26e4fcSRobert Mustacchi * toggle this behavior from a supported way in userland. 4319d26e4fcSRobert Mustacchi */ 4329d26e4fcSRobert Mustacchi miocnak(q, mp, 0, EINVAL); 4339d26e4fcSRobert Mustacchi } 4349d26e4fcSRobert Mustacchi 4359d26e4fcSRobert Mustacchi static int 4369d26e4fcSRobert Mustacchi i40e_ring_start(mac_ring_driver_t rh, uint64_t gen_num) 4379d26e4fcSRobert Mustacchi { 4389d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = (i40e_trqpair_t *)rh; 4399d26e4fcSRobert Mustacchi 4409d26e4fcSRobert Mustacchi /* 4419d26e4fcSRobert Mustacchi * GLDv3 requires we keep track of a generation number, as it uses 4429d26e4fcSRobert Mustacchi * that number to keep track of whether or not a ring is active. 4439d26e4fcSRobert Mustacchi */ 4449d26e4fcSRobert Mustacchi mutex_enter(&itrq->itrq_rx_lock); 4459d26e4fcSRobert Mustacchi itrq->itrq_rxgen = gen_num; 4469d26e4fcSRobert Mustacchi mutex_exit(&itrq->itrq_rx_lock); 4479d26e4fcSRobert Mustacchi return (0); 4489d26e4fcSRobert Mustacchi } 4499d26e4fcSRobert Mustacchi 4509d26e4fcSRobert Mustacchi /* ARGSUSED */ 4519d26e4fcSRobert Mustacchi static int 4529d26e4fcSRobert Mustacchi i40e_rx_ring_intr_enable(mac_intr_handle_t intrh) 4539d26e4fcSRobert Mustacchi { 4549d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh; 4559d26e4fcSRobert Mustacchi 456396505afSPaul Winder mutex_enter(&itrq->itrq_rx_lock); 457396505afSPaul Winder ASSERT(itrq->itrq_intr_poll == B_TRUE); 458338749cbSRobert Mustacchi i40e_intr_rx_queue_enable(itrq); 459396505afSPaul Winder itrq->itrq_intr_poll = B_FALSE; 460396505afSPaul Winder mutex_exit(&itrq->itrq_rx_lock); 4619d26e4fcSRobert Mustacchi 4629d26e4fcSRobert Mustacchi return (0); 4639d26e4fcSRobert Mustacchi } 4649d26e4fcSRobert Mustacchi 4659d26e4fcSRobert Mustacchi /* ARGSUSED */ 4669d26e4fcSRobert Mustacchi static int 4679d26e4fcSRobert Mustacchi i40e_rx_ring_intr_disable(mac_intr_handle_t intrh) 4689d26e4fcSRobert Mustacchi { 4699d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh; 4709d26e4fcSRobert Mustacchi 471396505afSPaul Winder mutex_enter(&itrq->itrq_rx_lock); 472338749cbSRobert Mustacchi i40e_intr_rx_queue_disable(itrq); 473396505afSPaul Winder itrq->itrq_intr_poll = B_TRUE; 474396505afSPaul Winder mutex_exit(&itrq->itrq_rx_lock); 4759d26e4fcSRobert Mustacchi 4769d26e4fcSRobert Mustacchi return (0); 4779d26e4fcSRobert Mustacchi } 4789d26e4fcSRobert Mustacchi 4799d26e4fcSRobert Mustacchi /* ARGSUSED */ 4809d26e4fcSRobert Mustacchi static void 4819d26e4fcSRobert Mustacchi i40e_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_index, 4829d26e4fcSRobert Mustacchi const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh) 4839d26e4fcSRobert Mustacchi { 4849d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 4859d26e4fcSRobert Mustacchi mac_intr_t *mintr = &infop->mri_intr; 4869d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = &(i40e->i40e_trqpairs[ring_index]); 4879d26e4fcSRobert Mustacchi 4889d26e4fcSRobert Mustacchi /* 4899d26e4fcSRobert Mustacchi * Note the group index here is expected to be -1 due to the fact that 4909d26e4fcSRobert Mustacchi * we're not actually grouping things tx-wise at this time. 4919d26e4fcSRobert Mustacchi */ 4929d26e4fcSRobert Mustacchi ASSERT(group_index == -1); 4939d26e4fcSRobert Mustacchi ASSERT(ring_index < i40e->i40e_num_trqpairs); 4949d26e4fcSRobert Mustacchi 4959d26e4fcSRobert Mustacchi itrq->itrq_mactxring = rh; 4969d26e4fcSRobert Mustacchi infop->mri_driver = (mac_ring_driver_t)itrq; 4979d26e4fcSRobert Mustacchi infop->mri_start = NULL; 4989d26e4fcSRobert Mustacchi infop->mri_stop = NULL; 4999d26e4fcSRobert Mustacchi infop->mri_tx = i40e_ring_tx; 5009d26e4fcSRobert Mustacchi infop->mri_stat = i40e_tx_ring_stat; 5019d26e4fcSRobert Mustacchi 5029d26e4fcSRobert Mustacchi /* 5039d26e4fcSRobert Mustacchi * We only provide the handle in cases where we have MSI-X interrupts, 5049d26e4fcSRobert Mustacchi * to indicate that we'd actually support retargetting. 5059d26e4fcSRobert Mustacchi */ 5069d26e4fcSRobert Mustacchi if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) { 5079d26e4fcSRobert Mustacchi mintr->mi_ddi_handle = 5089d26e4fcSRobert Mustacchi i40e->i40e_intr_handles[itrq->itrq_tx_intrvec]; 5099d26e4fcSRobert Mustacchi } 5109d26e4fcSRobert Mustacchi } 5119d26e4fcSRobert Mustacchi 5129d26e4fcSRobert Mustacchi /* ARGSUSED */ 5139d26e4fcSRobert Mustacchi static void 5149d26e4fcSRobert Mustacchi i40e_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_index, 5159d26e4fcSRobert Mustacchi const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh) 5169d26e4fcSRobert Mustacchi { 5179d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 5189d26e4fcSRobert Mustacchi mac_intr_t *mintr = &infop->mri_intr; 5199d26e4fcSRobert Mustacchi i40e_trqpair_t *itrq = &i40e->i40e_trqpairs[ring_index]; 5209d26e4fcSRobert Mustacchi 5219d26e4fcSRobert Mustacchi /* 5229d26e4fcSRobert Mustacchi * We assert the group number and ring index to help sanity check 5239d26e4fcSRobert Mustacchi * ourselves and mark that we'll need to rework this when we have 5249d26e4fcSRobert Mustacchi * multiple groups. 5259d26e4fcSRobert Mustacchi */ 5269d26e4fcSRobert Mustacchi ASSERT3S(group_index, ==, 0); 5279d26e4fcSRobert Mustacchi ASSERT3S(ring_index, <, i40e->i40e_num_trqpairs); 5289d26e4fcSRobert Mustacchi 5299d26e4fcSRobert Mustacchi itrq->itrq_macrxring = rh; 5309d26e4fcSRobert Mustacchi infop->mri_driver = (mac_ring_driver_t)itrq; 5319d26e4fcSRobert Mustacchi infop->mri_start = i40e_ring_start; 5329d26e4fcSRobert Mustacchi infop->mri_stop = NULL; 5339d26e4fcSRobert Mustacchi infop->mri_poll = i40e_ring_rx_poll; 5349d26e4fcSRobert Mustacchi infop->mri_stat = i40e_rx_ring_stat; 5359d26e4fcSRobert Mustacchi mintr->mi_handle = (mac_intr_handle_t)itrq; 5369d26e4fcSRobert Mustacchi mintr->mi_enable = i40e_rx_ring_intr_enable; 5379d26e4fcSRobert Mustacchi mintr->mi_disable = i40e_rx_ring_intr_disable; 5389d26e4fcSRobert Mustacchi 5399d26e4fcSRobert Mustacchi /* 5409d26e4fcSRobert Mustacchi * We only provide the handle in cases where we have MSI-X interrupts, 5419d26e4fcSRobert Mustacchi * to indicate that we'd actually support retargetting. 5429d26e4fcSRobert Mustacchi */ 5439d26e4fcSRobert Mustacchi if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) { 5449d26e4fcSRobert Mustacchi mintr->mi_ddi_handle = 5459d26e4fcSRobert Mustacchi i40e->i40e_intr_handles[itrq->itrq_rx_intrvec]; 5469d26e4fcSRobert Mustacchi } 5479d26e4fcSRobert Mustacchi } 5489d26e4fcSRobert Mustacchi 5499d26e4fcSRobert Mustacchi /* ARGSUSED */ 5509d26e4fcSRobert Mustacchi static void 5519d26e4fcSRobert Mustacchi i40e_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index, 5529d26e4fcSRobert Mustacchi mac_group_info_t *infop, mac_group_handle_t gh) 5539d26e4fcSRobert Mustacchi { 5549d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 5559d26e4fcSRobert Mustacchi 5569d26e4fcSRobert Mustacchi if (rtype != MAC_RING_TYPE_RX) 5579d26e4fcSRobert Mustacchi return; 5589d26e4fcSRobert Mustacchi 5599d26e4fcSRobert Mustacchi /* 5609d26e4fcSRobert Mustacchi * Note, this is a simplified view of a group, given that we only have a 5619d26e4fcSRobert Mustacchi * single group and a single ring at the moment. We'll want to expand 5629d26e4fcSRobert Mustacchi * upon this as we leverage more hardware functionality. 5639d26e4fcSRobert Mustacchi */ 5649d26e4fcSRobert Mustacchi i40e->i40e_rx_group_handle = gh; 5659d26e4fcSRobert Mustacchi infop->mgi_driver = (mac_group_driver_t)i40e; 5669d26e4fcSRobert Mustacchi infop->mgi_start = NULL; 5679d26e4fcSRobert Mustacchi infop->mgi_stop = NULL; 5689d26e4fcSRobert Mustacchi infop->mgi_addmac = i40e_group_add_mac; 5699d26e4fcSRobert Mustacchi infop->mgi_remmac = i40e_group_remove_mac; 5709d26e4fcSRobert Mustacchi 5719d26e4fcSRobert Mustacchi ASSERT(i40e->i40e_num_rx_groups == I40E_GROUP_MAX); 5729d26e4fcSRobert Mustacchi infop->mgi_count = i40e->i40e_num_trqpairs; 5739d26e4fcSRobert Mustacchi } 5749d26e4fcSRobert Mustacchi 575*45d3dd98SRobert Mustacchi static int 576*45d3dd98SRobert Mustacchi i40e_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop) 577*45d3dd98SRobert Mustacchi { 578*45d3dd98SRobert Mustacchi boolean_t present, usable; 579*45d3dd98SRobert Mustacchi i40e_t *i40e = arg; 580*45d3dd98SRobert Mustacchi 581*45d3dd98SRobert Mustacchi if (id != 0 || infop == NULL) 582*45d3dd98SRobert Mustacchi return (EINVAL); 583*45d3dd98SRobert Mustacchi 584*45d3dd98SRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 585*45d3dd98SRobert Mustacchi present = !!(i40e->i40e_hw_space.phy.link_info.link_info & 586*45d3dd98SRobert Mustacchi I40E_AQ_MEDIA_AVAILABLE); 587*45d3dd98SRobert Mustacchi if (present) { 588*45d3dd98SRobert Mustacchi usable = !!(i40e->i40e_hw_space.phy.link_info.an_info & 589*45d3dd98SRobert Mustacchi I40E_AQ_QUALIFIED_MODULE); 590*45d3dd98SRobert Mustacchi } else { 591*45d3dd98SRobert Mustacchi usable = B_FALSE; 592*45d3dd98SRobert Mustacchi } 593*45d3dd98SRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 594*45d3dd98SRobert Mustacchi 595*45d3dd98SRobert Mustacchi mac_transceiver_info_set_usable(infop, usable); 596*45d3dd98SRobert Mustacchi mac_transceiver_info_set_present(infop, present); 597*45d3dd98SRobert Mustacchi 598*45d3dd98SRobert Mustacchi return (0); 599*45d3dd98SRobert Mustacchi } 600*45d3dd98SRobert Mustacchi 6019d26e4fcSRobert Mustacchi static boolean_t 6029d26e4fcSRobert Mustacchi i40e_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 6039d26e4fcSRobert Mustacchi { 6049d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 6059d26e4fcSRobert Mustacchi mac_capab_rings_t *cap_rings; 606*45d3dd98SRobert Mustacchi mac_capab_transceiver_t *mct; 6079d26e4fcSRobert Mustacchi 6089d26e4fcSRobert Mustacchi switch (cap) { 6099d26e4fcSRobert Mustacchi case MAC_CAPAB_HCKSUM: { 6109d26e4fcSRobert Mustacchi uint32_t *txflags = cap_data; 6119d26e4fcSRobert Mustacchi 6129d26e4fcSRobert Mustacchi *txflags = 0; 6139d26e4fcSRobert Mustacchi if (i40e->i40e_tx_hcksum_enable == B_TRUE) 6149d26e4fcSRobert Mustacchi *txflags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 6159d26e4fcSRobert Mustacchi break; 6169d26e4fcSRobert Mustacchi } 6179d26e4fcSRobert Mustacchi 6189d26e4fcSRobert Mustacchi case MAC_CAPAB_RINGS: 6199d26e4fcSRobert Mustacchi cap_rings = cap_data; 6209d26e4fcSRobert Mustacchi cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 6219d26e4fcSRobert Mustacchi switch (cap_rings->mr_type) { 6229d26e4fcSRobert Mustacchi case MAC_RING_TYPE_TX: 6239d26e4fcSRobert Mustacchi /* 6249d26e4fcSRobert Mustacchi * Note, saying we have no rings, but some number of 6259d26e4fcSRobert Mustacchi * groups indicates to MAC that it should create 6269d26e4fcSRobert Mustacchi * psuedo-groups with one for each TX ring. This may not 6279d26e4fcSRobert Mustacchi * be the long term behavior we want, but it'll work for 6289d26e4fcSRobert Mustacchi * now. 6299d26e4fcSRobert Mustacchi */ 6309d26e4fcSRobert Mustacchi cap_rings->mr_gnum = 0; 6319d26e4fcSRobert Mustacchi cap_rings->mr_rnum = i40e->i40e_num_trqpairs; 6329d26e4fcSRobert Mustacchi cap_rings->mr_rget = i40e_fill_tx_ring; 6339d26e4fcSRobert Mustacchi cap_rings->mr_gget = NULL; 6349d26e4fcSRobert Mustacchi cap_rings->mr_gaddring = NULL; 6359d26e4fcSRobert Mustacchi cap_rings->mr_gremring = NULL; 6369d26e4fcSRobert Mustacchi break; 6379d26e4fcSRobert Mustacchi case MAC_RING_TYPE_RX: 6389d26e4fcSRobert Mustacchi cap_rings->mr_rnum = i40e->i40e_num_trqpairs; 6399d26e4fcSRobert Mustacchi cap_rings->mr_rget = i40e_fill_rx_ring; 6409d26e4fcSRobert Mustacchi cap_rings->mr_gnum = I40E_GROUP_MAX; 6419d26e4fcSRobert Mustacchi cap_rings->mr_gget = i40e_fill_rx_group; 6429d26e4fcSRobert Mustacchi cap_rings->mr_gaddring = NULL; 6439d26e4fcSRobert Mustacchi cap_rings->mr_gremring = NULL; 6449d26e4fcSRobert Mustacchi break; 6459d26e4fcSRobert Mustacchi default: 6469d26e4fcSRobert Mustacchi return (B_FALSE); 6479d26e4fcSRobert Mustacchi } 6489d26e4fcSRobert Mustacchi break; 649*45d3dd98SRobert Mustacchi case MAC_CAPAB_TRANSCEIVER: 650*45d3dd98SRobert Mustacchi mct = cap_data; 651*45d3dd98SRobert Mustacchi 652*45d3dd98SRobert Mustacchi /* 653*45d3dd98SRobert Mustacchi * Firmware doesn't have a great way of telling us in advance 654*45d3dd98SRobert Mustacchi * whether we'd expect a SFF transceiver. As such, we always 655*45d3dd98SRobert Mustacchi * advertise the support for this capability. 656*45d3dd98SRobert Mustacchi */ 657*45d3dd98SRobert Mustacchi mct->mct_flags = 0; 658*45d3dd98SRobert Mustacchi mct->mct_ntransceivers = 1; 659*45d3dd98SRobert Mustacchi mct->mct_info = i40e_transceiver_info; 660*45d3dd98SRobert Mustacchi mct->mct_read = NULL; 661*45d3dd98SRobert Mustacchi 662*45d3dd98SRobert Mustacchi return (B_TRUE); 6639d26e4fcSRobert Mustacchi default: 6649d26e4fcSRobert Mustacchi return (B_FALSE); 6659d26e4fcSRobert Mustacchi } 6669d26e4fcSRobert Mustacchi 6679d26e4fcSRobert Mustacchi return (B_TRUE); 6689d26e4fcSRobert Mustacchi } 6699d26e4fcSRobert Mustacchi 6709d26e4fcSRobert Mustacchi /* ARGSUSED */ 6719d26e4fcSRobert Mustacchi static int 6729d26e4fcSRobert Mustacchi i40e_m_setprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize, 6739d26e4fcSRobert Mustacchi const void *pr_val) 6749d26e4fcSRobert Mustacchi { 6759d26e4fcSRobert Mustacchi int ret; 6769d26e4fcSRobert Mustacchi long val; 6779d26e4fcSRobert Mustacchi char *eptr; 6789d26e4fcSRobert Mustacchi 6799d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock)); 6809d26e4fcSRobert Mustacchi 6819d26e4fcSRobert Mustacchi if ((ret = ddi_strtol(pr_val, &eptr, 10, &val)) != 0 || 6829d26e4fcSRobert Mustacchi *eptr != '\0') { 6839d26e4fcSRobert Mustacchi return (ret); 6849d26e4fcSRobert Mustacchi } 6859d26e4fcSRobert Mustacchi 6869d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) { 6879d26e4fcSRobert Mustacchi if (val < I40E_MIN_RX_DMA_THRESH || 6889d26e4fcSRobert Mustacchi val > I40E_MAX_RX_DMA_THRESH) { 6899d26e4fcSRobert Mustacchi return (EINVAL); 6909d26e4fcSRobert Mustacchi } 6919d26e4fcSRobert Mustacchi i40e->i40e_rx_dma_min = (uint32_t)val; 6929d26e4fcSRobert Mustacchi return (0); 6939d26e4fcSRobert Mustacchi } 6949d26e4fcSRobert Mustacchi 6959d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) { 6969d26e4fcSRobert Mustacchi if (val < I40E_MIN_TX_DMA_THRESH || 6979d26e4fcSRobert Mustacchi val > I40E_MAX_TX_DMA_THRESH) { 6989d26e4fcSRobert Mustacchi return (EINVAL); 6999d26e4fcSRobert Mustacchi } 7009d26e4fcSRobert Mustacchi i40e->i40e_tx_dma_min = (uint32_t)val; 7019d26e4fcSRobert Mustacchi return (0); 7029d26e4fcSRobert Mustacchi } 7039d26e4fcSRobert Mustacchi 7049d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) { 7059d26e4fcSRobert Mustacchi if (val < I40E_MIN_ITR || 7069d26e4fcSRobert Mustacchi val > I40E_MAX_ITR) { 7079d26e4fcSRobert Mustacchi return (EINVAL); 7089d26e4fcSRobert Mustacchi } 7099d26e4fcSRobert Mustacchi i40e->i40e_rx_itr = (uint32_t)val; 7109d26e4fcSRobert Mustacchi i40e_intr_set_itr(i40e, I40E_ITR_INDEX_RX, i40e->i40e_rx_itr); 7119d26e4fcSRobert Mustacchi return (0); 7129d26e4fcSRobert Mustacchi } 7139d26e4fcSRobert Mustacchi 7149d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) { 7159d26e4fcSRobert Mustacchi if (val < I40E_MIN_ITR || 7169d26e4fcSRobert Mustacchi val > I40E_MAX_ITR) { 7179d26e4fcSRobert Mustacchi return (EINVAL); 7189d26e4fcSRobert Mustacchi } 7199d26e4fcSRobert Mustacchi i40e->i40e_tx_itr = (uint32_t)val; 7209d26e4fcSRobert Mustacchi i40e_intr_set_itr(i40e, I40E_ITR_INDEX_TX, i40e->i40e_tx_itr); 7219d26e4fcSRobert Mustacchi return (0); 7229d26e4fcSRobert Mustacchi } 7239d26e4fcSRobert Mustacchi 7249d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) { 7259d26e4fcSRobert Mustacchi if (val < I40E_MIN_ITR || 7269d26e4fcSRobert Mustacchi val > I40E_MAX_ITR) { 7279d26e4fcSRobert Mustacchi return (EINVAL); 7289d26e4fcSRobert Mustacchi } 7299d26e4fcSRobert Mustacchi i40e->i40e_tx_itr = (uint32_t)val; 7309d26e4fcSRobert Mustacchi i40e_intr_set_itr(i40e, I40E_ITR_INDEX_OTHER, 7319d26e4fcSRobert Mustacchi i40e->i40e_other_itr); 7329d26e4fcSRobert Mustacchi return (0); 7339d26e4fcSRobert Mustacchi } 7349d26e4fcSRobert Mustacchi 7359d26e4fcSRobert Mustacchi return (ENOTSUP); 7369d26e4fcSRobert Mustacchi } 7379d26e4fcSRobert Mustacchi 7389d26e4fcSRobert Mustacchi static int 7399d26e4fcSRobert Mustacchi i40e_m_getprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize, 7409d26e4fcSRobert Mustacchi void *pr_val) 7419d26e4fcSRobert Mustacchi { 7429d26e4fcSRobert Mustacchi uint32_t val; 7439d26e4fcSRobert Mustacchi 7449d26e4fcSRobert Mustacchi ASSERT(MUTEX_HELD(&i40e->i40e_general_lock)); 7459d26e4fcSRobert Mustacchi 7469d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) { 7479d26e4fcSRobert Mustacchi val = i40e->i40e_rx_dma_min; 7489d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) { 7499d26e4fcSRobert Mustacchi val = i40e->i40e_tx_dma_min; 7509d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) { 7519d26e4fcSRobert Mustacchi val = i40e->i40e_rx_itr; 7529d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) { 7539d26e4fcSRobert Mustacchi val = i40e->i40e_tx_itr; 7549d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) { 7559d26e4fcSRobert Mustacchi val = i40e->i40e_other_itr; 7569d26e4fcSRobert Mustacchi } else { 7579d26e4fcSRobert Mustacchi return (ENOTSUP); 7589d26e4fcSRobert Mustacchi } 7599d26e4fcSRobert Mustacchi 7609d26e4fcSRobert Mustacchi if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize) 7619d26e4fcSRobert Mustacchi return (ERANGE); 7629d26e4fcSRobert Mustacchi return (0); 7639d26e4fcSRobert Mustacchi } 7649d26e4fcSRobert Mustacchi 7659d26e4fcSRobert Mustacchi /* 7669d26e4fcSRobert Mustacchi * Annoyingly for private properties MAC seems to ignore default values that 7679d26e4fcSRobert Mustacchi * aren't strings. That means that we have to translate all of these into 7689d26e4fcSRobert Mustacchi * uint32_t's and instead we size the buffer to be large enough to hold a 7699d26e4fcSRobert Mustacchi * uint32_t. 7709d26e4fcSRobert Mustacchi */ 7719d26e4fcSRobert Mustacchi /* ARGSUSED */ 7729d26e4fcSRobert Mustacchi static void 7739d26e4fcSRobert Mustacchi i40e_m_propinfo_private(i40e_t *i40e, const char *pr_name, 7749d26e4fcSRobert Mustacchi mac_prop_info_handle_t prh) 7759d26e4fcSRobert Mustacchi { 7769d26e4fcSRobert Mustacchi char buf[64]; 7779d26e4fcSRobert Mustacchi uint32_t def; 7789d26e4fcSRobert Mustacchi 7799d26e4fcSRobert Mustacchi if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) { 7809d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 7819d26e4fcSRobert Mustacchi def = I40E_DEF_RX_DMA_THRESH; 7829d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, 7839d26e4fcSRobert Mustacchi I40E_MIN_RX_DMA_THRESH, 7849d26e4fcSRobert Mustacchi I40E_MAX_RX_DMA_THRESH); 7859d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) { 7869d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 7879d26e4fcSRobert Mustacchi def = I40E_DEF_TX_DMA_THRESH; 7889d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, 7899d26e4fcSRobert Mustacchi I40E_MIN_TX_DMA_THRESH, 7909d26e4fcSRobert Mustacchi I40E_MAX_TX_DMA_THRESH); 7919d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) { 7929d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 7939d26e4fcSRobert Mustacchi def = I40E_DEF_RX_ITR; 7949d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR); 7959d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) { 7969d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 7979d26e4fcSRobert Mustacchi def = I40E_DEF_TX_ITR; 7989d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR); 7999d26e4fcSRobert Mustacchi } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) { 8009d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 8019d26e4fcSRobert Mustacchi def = I40E_DEF_OTHER_ITR; 8029d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR); 8039d26e4fcSRobert Mustacchi } else { 8049d26e4fcSRobert Mustacchi return; 8059d26e4fcSRobert Mustacchi } 8069d26e4fcSRobert Mustacchi 8079d26e4fcSRobert Mustacchi (void) snprintf(buf, sizeof (buf), "%d", def); 8089d26e4fcSRobert Mustacchi mac_prop_info_set_default_str(prh, buf); 8099d26e4fcSRobert Mustacchi } 8109d26e4fcSRobert Mustacchi 8119d26e4fcSRobert Mustacchi static int 8129d26e4fcSRobert Mustacchi i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 8139d26e4fcSRobert Mustacchi uint_t pr_valsize, const void *pr_val) 8149d26e4fcSRobert Mustacchi { 8159d26e4fcSRobert Mustacchi uint32_t new_mtu; 8169d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 8179d26e4fcSRobert Mustacchi int ret = 0; 8189d26e4fcSRobert Mustacchi 8199d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 8209d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_SUSPENDED) { 8219d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 8229d26e4fcSRobert Mustacchi return (ECANCELED); 8239d26e4fcSRobert Mustacchi } 8249d26e4fcSRobert Mustacchi 8259d26e4fcSRobert Mustacchi switch (pr_num) { 8269d26e4fcSRobert Mustacchi /* 8279d26e4fcSRobert Mustacchi * These properties are always read-only across every device. 8289d26e4fcSRobert Mustacchi */ 8299d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX: 8309d26e4fcSRobert Mustacchi case MAC_PROP_SPEED: 8319d26e4fcSRobert Mustacchi case MAC_PROP_STATUS: 8329d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP: 8339d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP: 8349d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP: 8353d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP: 8369d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP: 8379d26e4fcSRobert Mustacchi ret = ENOTSUP; 8389d26e4fcSRobert Mustacchi break; 8399d26e4fcSRobert Mustacchi /* 8409d26e4fcSRobert Mustacchi * These are read-only at this time as we don't support configuring 8419d26e4fcSRobert Mustacchi * auto-negotiation. See the theory statement in i40e_main.c. 8429d26e4fcSRobert Mustacchi */ 8439d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP: 8449d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP: 8459d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP: 8463d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP: 8479d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP: 8489d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG: 8499d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL: 8509d26e4fcSRobert Mustacchi ret = ENOTSUP; 8519d26e4fcSRobert Mustacchi break; 8529d26e4fcSRobert Mustacchi 8539d26e4fcSRobert Mustacchi case MAC_PROP_MTU: 8549d26e4fcSRobert Mustacchi bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 8559d26e4fcSRobert Mustacchi if (new_mtu == i40e->i40e_sdu) 8569d26e4fcSRobert Mustacchi break; 8579d26e4fcSRobert Mustacchi 8589d26e4fcSRobert Mustacchi if (new_mtu < I40E_MIN_MTU || 8599d26e4fcSRobert Mustacchi new_mtu > I40E_MAX_MTU) { 8609d26e4fcSRobert Mustacchi ret = EINVAL; 8619d26e4fcSRobert Mustacchi break; 8629d26e4fcSRobert Mustacchi } 8639d26e4fcSRobert Mustacchi 8649d26e4fcSRobert Mustacchi if (i40e->i40e_state & I40E_STARTED) { 8659d26e4fcSRobert Mustacchi ret = EBUSY; 8669d26e4fcSRobert Mustacchi break; 8679d26e4fcSRobert Mustacchi } 8689d26e4fcSRobert Mustacchi 8699d26e4fcSRobert Mustacchi ret = mac_maxsdu_update(i40e->i40e_mac_hdl, new_mtu); 8709d26e4fcSRobert Mustacchi if (ret == 0) { 8719d26e4fcSRobert Mustacchi i40e->i40e_sdu = new_mtu; 8729d26e4fcSRobert Mustacchi i40e_update_mtu(i40e); 8739d26e4fcSRobert Mustacchi } 8749d26e4fcSRobert Mustacchi break; 8759d26e4fcSRobert Mustacchi 8769d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE: 8779d26e4fcSRobert Mustacchi ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val); 8789d26e4fcSRobert Mustacchi break; 8799d26e4fcSRobert Mustacchi default: 8809d26e4fcSRobert Mustacchi ret = ENOTSUP; 8819d26e4fcSRobert Mustacchi break; 8829d26e4fcSRobert Mustacchi } 8839d26e4fcSRobert Mustacchi 8849d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 8859d26e4fcSRobert Mustacchi return (ret); 8869d26e4fcSRobert Mustacchi } 8879d26e4fcSRobert Mustacchi 8889d26e4fcSRobert Mustacchi static int 8899d26e4fcSRobert Mustacchi i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 8909d26e4fcSRobert Mustacchi uint_t pr_valsize, void *pr_val) 8919d26e4fcSRobert Mustacchi { 8929d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 8939d26e4fcSRobert Mustacchi uint64_t speed; 8949d26e4fcSRobert Mustacchi int ret = 0; 8959d26e4fcSRobert Mustacchi uint8_t *u8; 8969d26e4fcSRobert Mustacchi link_flowctrl_t fctl; 8979d26e4fcSRobert Mustacchi 8989d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 8999d26e4fcSRobert Mustacchi 9009d26e4fcSRobert Mustacchi switch (pr_num) { 9019d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX: 9029d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_duplex_t)) { 9039d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9049d26e4fcSRobert Mustacchi break; 9059d26e4fcSRobert Mustacchi } 9069d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_link_duplex, pr_val, sizeof (link_duplex_t)); 9079d26e4fcSRobert Mustacchi break; 9089d26e4fcSRobert Mustacchi case MAC_PROP_SPEED: 9099d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint64_t)) { 9109d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9119d26e4fcSRobert Mustacchi break; 9129d26e4fcSRobert Mustacchi } 9139d26e4fcSRobert Mustacchi speed = i40e->i40e_link_speed * 1000000ULL; 9149d26e4fcSRobert Mustacchi bcopy(&speed, pr_val, sizeof (speed)); 9159d26e4fcSRobert Mustacchi break; 9169d26e4fcSRobert Mustacchi case MAC_PROP_STATUS: 9179d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_state_t)) { 9189d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9199d26e4fcSRobert Mustacchi break; 9209d26e4fcSRobert Mustacchi } 9219d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_link_state, pr_val, sizeof (link_state_t)); 9229d26e4fcSRobert Mustacchi break; 9239d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG: 9249d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 9259d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9269d26e4fcSRobert Mustacchi break; 9279d26e4fcSRobert Mustacchi } 9289d26e4fcSRobert Mustacchi u8 = pr_val; 9299d26e4fcSRobert Mustacchi *u8 = 1; 9309d26e4fcSRobert Mustacchi break; 9319d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL: 9329d26e4fcSRobert Mustacchi /* 9339d26e4fcSRobert Mustacchi * Because we don't currently support hardware flow control, we 9349d26e4fcSRobert Mustacchi * just hardcode this to be none. 9359d26e4fcSRobert Mustacchi */ 9369d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (link_flowctrl_t)) { 9379d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9389d26e4fcSRobert Mustacchi break; 9399d26e4fcSRobert Mustacchi } 9409d26e4fcSRobert Mustacchi fctl = LINK_FLOWCTRL_NONE; 9419d26e4fcSRobert Mustacchi bcopy(&fctl, pr_val, sizeof (link_flowctrl_t)); 9429d26e4fcSRobert Mustacchi break; 9439d26e4fcSRobert Mustacchi case MAC_PROP_MTU: 9449d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint32_t)) { 9459d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9469d26e4fcSRobert Mustacchi break; 9479d26e4fcSRobert Mustacchi } 9489d26e4fcSRobert Mustacchi bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t)); 9499d26e4fcSRobert Mustacchi break; 9509d26e4fcSRobert Mustacchi 9519d26e4fcSRobert Mustacchi /* 9529d26e4fcSRobert Mustacchi * Because we don't let users control the speeds we may auto-negotiate 9539d26e4fcSRobert Mustacchi * to, the values of the ADV_ and EN_ will always be the same. 9549d26e4fcSRobert Mustacchi */ 9559d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP: 9569d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP: 9579d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 9589d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9599d26e4fcSRobert Mustacchi break; 9609d26e4fcSRobert Mustacchi } 9619d26e4fcSRobert Mustacchi u8 = pr_val; 9629d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0; 9639d26e4fcSRobert Mustacchi break; 9649d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP: 9659d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP: 9669d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 9679d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9689d26e4fcSRobert Mustacchi break; 9699d26e4fcSRobert Mustacchi } 9709d26e4fcSRobert Mustacchi u8 = pr_val; 9719d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0; 9729d26e4fcSRobert Mustacchi break; 9739d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP: 9749d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP: 9759d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 9769d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9779d26e4fcSRobert Mustacchi break; 9789d26e4fcSRobert Mustacchi } 9799d26e4fcSRobert Mustacchi u8 = pr_val; 9809d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0; 9819d26e4fcSRobert Mustacchi break; 9823d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP: 9833d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP: 9843d75a287SRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 9853d75a287SRobert Mustacchi ret = EOVERFLOW; 9863d75a287SRobert Mustacchi break; 9873d75a287SRobert Mustacchi } 9883d75a287SRobert Mustacchi u8 = pr_val; 9893d75a287SRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0; 9903d75a287SRobert Mustacchi break; 9919d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP: 9929d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP: 9939d26e4fcSRobert Mustacchi if (pr_valsize < sizeof (uint8_t)) { 9949d26e4fcSRobert Mustacchi ret = EOVERFLOW; 9959d26e4fcSRobert Mustacchi break; 9969d26e4fcSRobert Mustacchi } 9979d26e4fcSRobert Mustacchi u8 = pr_val; 9989d26e4fcSRobert Mustacchi *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0; 9999d26e4fcSRobert Mustacchi break; 10009d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE: 10019d26e4fcSRobert Mustacchi ret = i40e_m_getprop_private(i40e, pr_name, pr_valsize, pr_val); 10029d26e4fcSRobert Mustacchi break; 10039d26e4fcSRobert Mustacchi default: 10049d26e4fcSRobert Mustacchi ret = ENOTSUP; 10059d26e4fcSRobert Mustacchi break; 10069d26e4fcSRobert Mustacchi } 10079d26e4fcSRobert Mustacchi 10089d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 10099d26e4fcSRobert Mustacchi 10109d26e4fcSRobert Mustacchi return (ret); 10119d26e4fcSRobert Mustacchi } 10129d26e4fcSRobert Mustacchi 10139d26e4fcSRobert Mustacchi static void 10149d26e4fcSRobert Mustacchi i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, 10159d26e4fcSRobert Mustacchi mac_prop_info_handle_t prh) 10169d26e4fcSRobert Mustacchi { 10179d26e4fcSRobert Mustacchi i40e_t *i40e = arg; 10189d26e4fcSRobert Mustacchi 10199d26e4fcSRobert Mustacchi mutex_enter(&i40e->i40e_general_lock); 10209d26e4fcSRobert Mustacchi 10219d26e4fcSRobert Mustacchi switch (pr_num) { 10229d26e4fcSRobert Mustacchi case MAC_PROP_DUPLEX: 10239d26e4fcSRobert Mustacchi case MAC_PROP_SPEED: 10249d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10259d26e4fcSRobert Mustacchi break; 10269d26e4fcSRobert Mustacchi case MAC_PROP_FLOWCTRL: 10279d26e4fcSRobert Mustacchi /* 10289d26e4fcSRobert Mustacchi * At the moment, the driver doesn't support flow control, hence 10299d26e4fcSRobert Mustacchi * why this is set to read-only and none. 10309d26e4fcSRobert Mustacchi */ 10319d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10329d26e4fcSRobert Mustacchi mac_prop_info_set_default_link_flowctrl(prh, 10339d26e4fcSRobert Mustacchi LINK_FLOWCTRL_NONE); 10349d26e4fcSRobert Mustacchi break; 10359d26e4fcSRobert Mustacchi case MAC_PROP_MTU: 10369d26e4fcSRobert Mustacchi mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU); 10379d26e4fcSRobert Mustacchi break; 10389d26e4fcSRobert Mustacchi 10399d26e4fcSRobert Mustacchi /* 10409d26e4fcSRobert Mustacchi * We set the defaults for these based upon the phy's ability to 10419d26e4fcSRobert Mustacchi * support the speeds. Note, auto-negotiation is required for fiber, 10429d26e4fcSRobert Mustacchi * hence it is read-only and always enabled. When we have access to 10439d26e4fcSRobert Mustacchi * copper phys we can revisit this. 10449d26e4fcSRobert Mustacchi */ 10459d26e4fcSRobert Mustacchi case MAC_PROP_AUTONEG: 10469d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10479d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 1); 10489d26e4fcSRobert Mustacchi break; 10499d26e4fcSRobert Mustacchi case MAC_PROP_ADV_100FDX_CAP: 10509d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10519d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10529d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0); 10539d26e4fcSRobert Mustacchi break; 10549d26e4fcSRobert Mustacchi case MAC_PROP_EN_100FDX_CAP: 10559d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10569d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10579d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0); 10589d26e4fcSRobert Mustacchi break; 10599d26e4fcSRobert Mustacchi case MAC_PROP_ADV_1000FDX_CAP: 10609d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10619d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10629d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0); 10639d26e4fcSRobert Mustacchi break; 10649d26e4fcSRobert Mustacchi case MAC_PROP_EN_1000FDX_CAP: 10659d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10669d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10679d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0); 10689d26e4fcSRobert Mustacchi break; 10699d26e4fcSRobert Mustacchi case MAC_PROP_ADV_10GFDX_CAP: 10709d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10719d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10729d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0); 10739d26e4fcSRobert Mustacchi break; 10749d26e4fcSRobert Mustacchi case MAC_PROP_EN_10GFDX_CAP: 10759d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10769d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10779d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0); 10789d26e4fcSRobert Mustacchi break; 10793d75a287SRobert Mustacchi case MAC_PROP_ADV_25GFDX_CAP: 10803d75a287SRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10813d75a287SRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10823d75a287SRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0); 10833d75a287SRobert Mustacchi break; 10843d75a287SRobert Mustacchi case MAC_PROP_EN_25GFDX_CAP: 10853d75a287SRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10863d75a287SRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10873d75a287SRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0); 10883d75a287SRobert Mustacchi break; 10899d26e4fcSRobert Mustacchi case MAC_PROP_ADV_40GFDX_CAP: 10909d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10919d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10929d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0); 10939d26e4fcSRobert Mustacchi break; 10949d26e4fcSRobert Mustacchi case MAC_PROP_EN_40GFDX_CAP: 10959d26e4fcSRobert Mustacchi mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 10969d26e4fcSRobert Mustacchi mac_prop_info_set_default_uint8(prh, 10979d26e4fcSRobert Mustacchi (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0); 10989d26e4fcSRobert Mustacchi break; 10999d26e4fcSRobert Mustacchi case MAC_PROP_PRIVATE: 11009d26e4fcSRobert Mustacchi i40e_m_propinfo_private(i40e, pr_name, prh); 11019d26e4fcSRobert Mustacchi break; 11029d26e4fcSRobert Mustacchi default: 11039d26e4fcSRobert Mustacchi break; 11049d26e4fcSRobert Mustacchi } 11059d26e4fcSRobert Mustacchi 11069d26e4fcSRobert Mustacchi mutex_exit(&i40e->i40e_general_lock); 11079d26e4fcSRobert Mustacchi } 11089d26e4fcSRobert Mustacchi 11099d26e4fcSRobert Mustacchi #define I40E_M_CALLBACK_FLAGS \ 11109d26e4fcSRobert Mustacchi (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO) 11119d26e4fcSRobert Mustacchi 11129d26e4fcSRobert Mustacchi static mac_callbacks_t i40e_m_callbacks = { 11139d26e4fcSRobert Mustacchi I40E_M_CALLBACK_FLAGS, 11149d26e4fcSRobert Mustacchi i40e_m_stat, 11159d26e4fcSRobert Mustacchi i40e_m_start, 11169d26e4fcSRobert Mustacchi i40e_m_stop, 11179d26e4fcSRobert Mustacchi i40e_m_promisc, 11189d26e4fcSRobert Mustacchi i40e_m_multicast, 11199d26e4fcSRobert Mustacchi NULL, 11209d26e4fcSRobert Mustacchi NULL, 11219d26e4fcSRobert Mustacchi NULL, 11229d26e4fcSRobert Mustacchi i40e_m_ioctl, 11239d26e4fcSRobert Mustacchi i40e_m_getcapab, 11249d26e4fcSRobert Mustacchi NULL, 11259d26e4fcSRobert Mustacchi NULL, 11269d26e4fcSRobert Mustacchi i40e_m_setprop, 11279d26e4fcSRobert Mustacchi i40e_m_getprop, 11289d26e4fcSRobert Mustacchi i40e_m_propinfo 11299d26e4fcSRobert Mustacchi }; 11309d26e4fcSRobert Mustacchi 11319d26e4fcSRobert Mustacchi boolean_t 11329d26e4fcSRobert Mustacchi i40e_register_mac(i40e_t *i40e) 11339d26e4fcSRobert Mustacchi { 11349d26e4fcSRobert Mustacchi struct i40e_hw *hw = &i40e->i40e_hw_space; 11359d26e4fcSRobert Mustacchi int status; 11369d26e4fcSRobert Mustacchi mac_register_t *mac = mac_alloc(MAC_VERSION); 11379d26e4fcSRobert Mustacchi 11389d26e4fcSRobert Mustacchi if (mac == NULL) 11399d26e4fcSRobert Mustacchi return (B_FALSE); 11409d26e4fcSRobert Mustacchi 11419d26e4fcSRobert Mustacchi mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 11429d26e4fcSRobert Mustacchi mac->m_driver = i40e; 11439d26e4fcSRobert Mustacchi mac->m_dip = i40e->i40e_dip; 11449d26e4fcSRobert Mustacchi mac->m_src_addr = hw->mac.addr; 11459d26e4fcSRobert Mustacchi mac->m_callbacks = &i40e_m_callbacks; 11469d26e4fcSRobert Mustacchi mac->m_min_sdu = 0; 11479d26e4fcSRobert Mustacchi mac->m_max_sdu = i40e->i40e_sdu; 11489d26e4fcSRobert Mustacchi mac->m_margin = VLAN_TAGSZ; 11499d26e4fcSRobert Mustacchi mac->m_priv_props = i40e_priv_props; 11509d26e4fcSRobert Mustacchi mac->m_v12n = MAC_VIRT_LEVEL1; 11519d26e4fcSRobert Mustacchi 11529d26e4fcSRobert Mustacchi status = mac_register(mac, &i40e->i40e_mac_hdl); 11539d26e4fcSRobert Mustacchi if (status != 0) 11549d26e4fcSRobert Mustacchi i40e_error(i40e, "mac_register() returned %d", status); 11559d26e4fcSRobert Mustacchi mac_free(mac); 11569d26e4fcSRobert Mustacchi 11579d26e4fcSRobert Mustacchi return (status == 0); 11589d26e4fcSRobert Mustacchi } 1159