1fcea6f3dSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 2fcea6f3dSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 3fcea6f3dSAnirudh Venkataramanan 4fcea6f3dSAnirudh Venkataramanan /* ethtool support for ice */ 5fcea6f3dSAnirudh Venkataramanan 6fcea6f3dSAnirudh Venkataramanan #include "ice.h" 73a257a14SAnirudh Venkataramanan #include "ice_lib.h" 83a257a14SAnirudh Venkataramanan #include "ice_dcb_lib.h" 9fcea6f3dSAnirudh Venkataramanan 10fcea6f3dSAnirudh Venkataramanan struct ice_stats { 11fcea6f3dSAnirudh Venkataramanan char stat_string[ETH_GSTRING_LEN]; 12fcea6f3dSAnirudh Venkataramanan int sizeof_stat; 13fcea6f3dSAnirudh Venkataramanan int stat_offset; 14fcea6f3dSAnirudh Venkataramanan }; 15fcea6f3dSAnirudh Venkataramanan 16fcea6f3dSAnirudh Venkataramanan #define ICE_STAT(_type, _name, _stat) { \ 17fcea6f3dSAnirudh Venkataramanan .stat_string = _name, \ 18fcea6f3dSAnirudh Venkataramanan .sizeof_stat = FIELD_SIZEOF(_type, _stat), \ 19fcea6f3dSAnirudh Venkataramanan .stat_offset = offsetof(_type, _stat) \ 20fcea6f3dSAnirudh Venkataramanan } 21fcea6f3dSAnirudh Venkataramanan 22fcea6f3dSAnirudh Venkataramanan #define ICE_VSI_STAT(_name, _stat) \ 23fcea6f3dSAnirudh Venkataramanan ICE_STAT(struct ice_vsi, _name, _stat) 24fcea6f3dSAnirudh Venkataramanan #define ICE_PF_STAT(_name, _stat) \ 25fcea6f3dSAnirudh Venkataramanan ICE_STAT(struct ice_pf, _name, _stat) 26fcea6f3dSAnirudh Venkataramanan 27fcea6f3dSAnirudh Venkataramanan static int ice_q_stats_len(struct net_device *netdev) 28fcea6f3dSAnirudh Venkataramanan { 29fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 30fcea6f3dSAnirudh Venkataramanan 31f8ba7db8SJacob Keller return ((np->vsi->alloc_txq + np->vsi->alloc_rxq) * 32fcea6f3dSAnirudh Venkataramanan (sizeof(struct ice_q_stats) / sizeof(u64))); 33fcea6f3dSAnirudh Venkataramanan } 34fcea6f3dSAnirudh Venkataramanan 35fcea6f3dSAnirudh Venkataramanan #define ICE_PF_STATS_LEN ARRAY_SIZE(ice_gstrings_pf_stats) 36fcea6f3dSAnirudh Venkataramanan #define ICE_VSI_STATS_LEN ARRAY_SIZE(ice_gstrings_vsi_stats) 37fcea6f3dSAnirudh Venkataramanan 384b0fdcebSAnirudh Venkataramanan #define ICE_PFC_STATS_LEN ( \ 394b0fdcebSAnirudh Venkataramanan (FIELD_SIZEOF(struct ice_pf, stats.priority_xoff_rx) + \ 404b0fdcebSAnirudh Venkataramanan FIELD_SIZEOF(struct ice_pf, stats.priority_xon_rx) + \ 414b0fdcebSAnirudh Venkataramanan FIELD_SIZEOF(struct ice_pf, stats.priority_xoff_tx) + \ 424b0fdcebSAnirudh Venkataramanan FIELD_SIZEOF(struct ice_pf, stats.priority_xon_tx)) \ 434b0fdcebSAnirudh Venkataramanan / sizeof(u64)) 444b0fdcebSAnirudh Venkataramanan #define ICE_ALL_STATS_LEN(n) (ICE_PF_STATS_LEN + ICE_PFC_STATS_LEN + \ 454b0fdcebSAnirudh Venkataramanan ICE_VSI_STATS_LEN + ice_q_stats_len(n)) 46fcea6f3dSAnirudh Venkataramanan 47fcea6f3dSAnirudh Venkataramanan static const struct ice_stats ice_gstrings_vsi_stats[] = { 48fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("tx_unicast", eth_stats.tx_unicast), 49fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_unicast", eth_stats.rx_unicast), 50fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("tx_multicast", eth_stats.tx_multicast), 51fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_multicast", eth_stats.rx_multicast), 52fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("tx_broadcast", eth_stats.tx_broadcast), 53fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_broadcast", eth_stats.rx_broadcast), 54fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("tx_bytes", eth_stats.tx_bytes), 55fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_bytes", eth_stats.rx_bytes), 56fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_discards", eth_stats.rx_discards), 57fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("tx_errors", eth_stats.tx_errors), 58fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("tx_linearize", tx_linearize), 59fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol), 60fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_alloc_fail", rx_buf_failed), 61fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_pg_alloc_fail", rx_page_failed), 62fcea6f3dSAnirudh Venkataramanan }; 63fcea6f3dSAnirudh Venkataramanan 64fcea6f3dSAnirudh Venkataramanan /* These PF_STATs might look like duplicates of some NETDEV_STATs, 65fcea6f3dSAnirudh Venkataramanan * but they aren't. This device is capable of supporting multiple 66fcea6f3dSAnirudh Venkataramanan * VSIs/netdevs on a single PF. The NETDEV_STATs are for individual 67fcea6f3dSAnirudh Venkataramanan * netdevs whereas the PF_STATs are for the physical function that's 68fcea6f3dSAnirudh Venkataramanan * hosting these netdevs. 69fcea6f3dSAnirudh Venkataramanan * 70fcea6f3dSAnirudh Venkataramanan * The PF_STATs are appended to the netdev stats only when ethtool -S 71fcea6f3dSAnirudh Venkataramanan * is queried on the base PF netdev. 72fcea6f3dSAnirudh Venkataramanan */ 7355aa141eSBruce Allan static const struct ice_stats ice_gstrings_pf_stats[] = { 741fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_bytes", stats.eth.tx_bytes), 751fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_bytes", stats.eth.rx_bytes), 761fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_unicast", stats.eth.tx_unicast), 771fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_unicast", stats.eth.rx_unicast), 781fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_multicast", stats.eth.tx_multicast), 791fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_multicast", stats.eth.rx_multicast), 801fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_broadcast", stats.eth.tx_broadcast), 811fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_broadcast", stats.eth.rx_broadcast), 821fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_errors", stats.eth.tx_errors), 831fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_size_64", stats.tx_size_64), 841fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_size_64", stats.rx_size_64), 851fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_size_127", stats.tx_size_127), 861fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_size_127", stats.rx_size_127), 871fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_size_255", stats.tx_size_255), 881fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_size_255", stats.rx_size_255), 891fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_size_511", stats.tx_size_511), 901fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_size_511", stats.rx_size_511), 911fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_size_1023", stats.tx_size_1023), 921fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_size_1023", stats.rx_size_1023), 931fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_size_1522", stats.tx_size_1522), 941fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_size_1522", stats.rx_size_1522), 951fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_size_big", stats.tx_size_big), 961fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_size_big", stats.rx_size_big), 971fa6e138SJesse Brandeburg ICE_PF_STAT("port.link_xon_tx", stats.link_xon_tx), 981fa6e138SJesse Brandeburg ICE_PF_STAT("port.link_xon_rx", stats.link_xon_rx), 991fa6e138SJesse Brandeburg ICE_PF_STAT("port.link_xoff_tx", stats.link_xoff_tx), 1001fa6e138SJesse Brandeburg ICE_PF_STAT("port.link_xoff_rx", stats.link_xoff_rx), 1011fa6e138SJesse Brandeburg ICE_PF_STAT("port.tx_dropped_link_down", stats.tx_dropped_link_down), 1021fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_undersize", stats.rx_undersize), 1031fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_fragments", stats.rx_fragments), 1041fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_oversize", stats.rx_oversize), 1051fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_jabber", stats.rx_jabber), 1061fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_csum_bad", hw_csum_rx_error), 1071fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_length_errors", stats.rx_len_errors), 1081fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_dropped", stats.eth.rx_discards), 1091fa6e138SJesse Brandeburg ICE_PF_STAT("port.rx_crc_errors", stats.crc_errors), 1101fa6e138SJesse Brandeburg ICE_PF_STAT("port.illegal_bytes", stats.illegal_bytes), 1111fa6e138SJesse Brandeburg ICE_PF_STAT("port.mac_local_faults", stats.mac_local_faults), 1121fa6e138SJesse Brandeburg ICE_PF_STAT("port.mac_remote_faults", stats.mac_remote_faults), 113fcea6f3dSAnirudh Venkataramanan }; 114fcea6f3dSAnirudh Venkataramanan 11555aa141eSBruce Allan static const u32 ice_regs_dump_list[] = { 116fcea6f3dSAnirudh Venkataramanan PFGEN_STATE, 117fcea6f3dSAnirudh Venkataramanan PRTGEN_STATUS, 118fcea6f3dSAnirudh Venkataramanan QRX_CTRL(0), 119fcea6f3dSAnirudh Venkataramanan QINT_TQCTL(0), 120fcea6f3dSAnirudh Venkataramanan QINT_RQCTL(0), 121fcea6f3dSAnirudh Venkataramanan PFINT_OICR_ENA, 122fcea6f3dSAnirudh Venkataramanan QRX_ITR(0), 123fcea6f3dSAnirudh Venkataramanan }; 124fcea6f3dSAnirudh Venkataramanan 125ab4ab73fSBruce Allan struct ice_priv_flag { 126ab4ab73fSBruce Allan char name[ETH_GSTRING_LEN]; 127ab4ab73fSBruce Allan u32 bitno; /* bit position in pf->flags */ 128ab4ab73fSBruce Allan }; 129ab4ab73fSBruce Allan 130ab4ab73fSBruce Allan #define ICE_PRIV_FLAG(_name, _bitno) { \ 131ab4ab73fSBruce Allan .name = _name, \ 132ab4ab73fSBruce Allan .bitno = _bitno, \ 133ab4ab73fSBruce Allan } 134ab4ab73fSBruce Allan 135ab4ab73fSBruce Allan static const struct ice_priv_flag ice_gstrings_priv_flags[] = { 136ab4ab73fSBruce Allan ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA), 13731eafa40SAnirudh Venkataramanan ICE_PRIV_FLAG("enable-fw-lldp", ICE_FLAG_ENABLE_FW_LLDP), 138ab4ab73fSBruce Allan }; 139ab4ab73fSBruce Allan 140ab4ab73fSBruce Allan #define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags) 141ab4ab73fSBruce Allan 142fcea6f3dSAnirudh Venkataramanan /** 143fcea6f3dSAnirudh Venkataramanan * ice_nvm_version_str - format the NVM version strings 144fcea6f3dSAnirudh Venkataramanan * @hw: ptr to the hardware info 145fcea6f3dSAnirudh Venkataramanan */ 146fcea6f3dSAnirudh Venkataramanan static char *ice_nvm_version_str(struct ice_hw *hw) 147fcea6f3dSAnirudh Venkataramanan { 148fcea6f3dSAnirudh Venkataramanan static char buf[ICE_ETHTOOL_FWVER_LEN]; 149fcea6f3dSAnirudh Venkataramanan u8 ver, patch; 150fcea6f3dSAnirudh Venkataramanan u32 full_ver; 151fcea6f3dSAnirudh Venkataramanan u16 build; 152fcea6f3dSAnirudh Venkataramanan 153fcea6f3dSAnirudh Venkataramanan full_ver = hw->nvm.oem_ver; 154fcea6f3dSAnirudh Venkataramanan ver = (u8)((full_ver & ICE_OEM_VER_MASK) >> ICE_OEM_VER_SHIFT); 155fcea6f3dSAnirudh Venkataramanan build = (u16)((full_ver & ICE_OEM_VER_BUILD_MASK) >> 156fcea6f3dSAnirudh Venkataramanan ICE_OEM_VER_BUILD_SHIFT); 157fcea6f3dSAnirudh Venkataramanan patch = (u8)(full_ver & ICE_OEM_VER_PATCH_MASK); 158fcea6f3dSAnirudh Venkataramanan 159fcea6f3dSAnirudh Venkataramanan snprintf(buf, sizeof(buf), "%x.%02x 0x%x %d.%d.%d", 160fcea6f3dSAnirudh Venkataramanan (hw->nvm.ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT, 161fcea6f3dSAnirudh Venkataramanan (hw->nvm.ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT, 162fcea6f3dSAnirudh Venkataramanan hw->nvm.eetrack, ver, build, patch); 163fcea6f3dSAnirudh Venkataramanan 164fcea6f3dSAnirudh Venkataramanan return buf; 165fcea6f3dSAnirudh Venkataramanan } 166fcea6f3dSAnirudh Venkataramanan 167fcea6f3dSAnirudh Venkataramanan static void 168fcea6f3dSAnirudh Venkataramanan ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) 169fcea6f3dSAnirudh Venkataramanan { 170fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 171fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 172fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 173fcea6f3dSAnirudh Venkataramanan 174fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); 175fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->version, ice_drv_ver, sizeof(drvinfo->version)); 176fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->fw_version, ice_nvm_version_str(&pf->hw), 177fcea6f3dSAnirudh Venkataramanan sizeof(drvinfo->fw_version)); 178fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->bus_info, pci_name(pf->pdev), 179fcea6f3dSAnirudh Venkataramanan sizeof(drvinfo->bus_info)); 180ab4ab73fSBruce Allan drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE; 181fcea6f3dSAnirudh Venkataramanan } 182fcea6f3dSAnirudh Venkataramanan 183fcea6f3dSAnirudh Venkataramanan static int ice_get_regs_len(struct net_device __always_unused *netdev) 184fcea6f3dSAnirudh Venkataramanan { 185cba5957dSAnirudh Venkataramanan return sizeof(ice_regs_dump_list); 186fcea6f3dSAnirudh Venkataramanan } 187fcea6f3dSAnirudh Venkataramanan 188fcea6f3dSAnirudh Venkataramanan static void 189fcea6f3dSAnirudh Venkataramanan ice_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) 190fcea6f3dSAnirudh Venkataramanan { 191fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 192fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 193fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 194fcea6f3dSAnirudh Venkataramanan u32 *regs_buf = (u32 *)p; 195fcea6f3dSAnirudh Venkataramanan int i; 196fcea6f3dSAnirudh Venkataramanan 197fcea6f3dSAnirudh Venkataramanan regs->version = 1; 198fcea6f3dSAnirudh Venkataramanan 199cba5957dSAnirudh Venkataramanan for (i = 0; i < ARRAY_SIZE(ice_regs_dump_list); ++i) 200fcea6f3dSAnirudh Venkataramanan regs_buf[i] = rd32(hw, ice_regs_dump_list[i]); 201fcea6f3dSAnirudh Venkataramanan } 202fcea6f3dSAnirudh Venkataramanan 203fcea6f3dSAnirudh Venkataramanan static u32 ice_get_msglevel(struct net_device *netdev) 204fcea6f3dSAnirudh Venkataramanan { 205fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 206fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 207fcea6f3dSAnirudh Venkataramanan 208fcea6f3dSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 209fcea6f3dSAnirudh Venkataramanan if (pf->hw.debug_mask) 210fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "hw debug_mask: 0x%llX\n", 211fcea6f3dSAnirudh Venkataramanan pf->hw.debug_mask); 212fcea6f3dSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 213fcea6f3dSAnirudh Venkataramanan 214fcea6f3dSAnirudh Venkataramanan return pf->msg_enable; 215fcea6f3dSAnirudh Venkataramanan } 216fcea6f3dSAnirudh Venkataramanan 217fcea6f3dSAnirudh Venkataramanan static void ice_set_msglevel(struct net_device *netdev, u32 data) 218fcea6f3dSAnirudh Venkataramanan { 219fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 220fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 221fcea6f3dSAnirudh Venkataramanan 222fcea6f3dSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 223fcea6f3dSAnirudh Venkataramanan if (ICE_DBG_USER & data) 224fcea6f3dSAnirudh Venkataramanan pf->hw.debug_mask = data; 225fcea6f3dSAnirudh Venkataramanan else 226fcea6f3dSAnirudh Venkataramanan pf->msg_enable = data; 227fcea6f3dSAnirudh Venkataramanan #else 228fcea6f3dSAnirudh Venkataramanan pf->msg_enable = data; 229fcea6f3dSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 230fcea6f3dSAnirudh Venkataramanan } 231fcea6f3dSAnirudh Venkataramanan 2324c98ab55SBruce Allan static int ice_get_eeprom_len(struct net_device *netdev) 2334c98ab55SBruce Allan { 2344c98ab55SBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 2354c98ab55SBruce Allan struct ice_pf *pf = np->vsi->back; 2364c98ab55SBruce Allan 2374c98ab55SBruce Allan return (int)(pf->hw.nvm.sr_words * sizeof(u16)); 2384c98ab55SBruce Allan } 2394c98ab55SBruce Allan 2404c98ab55SBruce Allan static int 2414c98ab55SBruce Allan ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, 2424c98ab55SBruce Allan u8 *bytes) 2434c98ab55SBruce Allan { 2444c98ab55SBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 2454c98ab55SBruce Allan u16 first_word, last_word, nwords; 2464c98ab55SBruce Allan struct ice_vsi *vsi = np->vsi; 2474c98ab55SBruce Allan struct ice_pf *pf = vsi->back; 2484c98ab55SBruce Allan struct ice_hw *hw = &pf->hw; 2494c98ab55SBruce Allan enum ice_status status; 2504c98ab55SBruce Allan struct device *dev; 2514c98ab55SBruce Allan int ret = 0; 2524c98ab55SBruce Allan u16 *buf; 2534c98ab55SBruce Allan 2544c98ab55SBruce Allan dev = &pf->pdev->dev; 2554c98ab55SBruce Allan 2564c98ab55SBruce Allan eeprom->magic = hw->vendor_id | (hw->device_id << 16); 2574c98ab55SBruce Allan 2584c98ab55SBruce Allan first_word = eeprom->offset >> 1; 2594c98ab55SBruce Allan last_word = (eeprom->offset + eeprom->len - 1) >> 1; 2604c98ab55SBruce Allan nwords = last_word - first_word + 1; 2614c98ab55SBruce Allan 2624c98ab55SBruce Allan buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL); 2634c98ab55SBruce Allan if (!buf) 2644c98ab55SBruce Allan return -ENOMEM; 2654c98ab55SBruce Allan 2664c98ab55SBruce Allan status = ice_read_sr_buf(hw, first_word, &nwords, buf); 2674c98ab55SBruce Allan if (status) { 2684c98ab55SBruce Allan dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n", 2694c98ab55SBruce Allan status, hw->adminq.sq_last_status); 2704c98ab55SBruce Allan eeprom->len = sizeof(u16) * nwords; 2714c98ab55SBruce Allan ret = -EIO; 2724c98ab55SBruce Allan goto out; 2734c98ab55SBruce Allan } 2744c98ab55SBruce Allan 2754c98ab55SBruce Allan memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len); 2764c98ab55SBruce Allan out: 2774c98ab55SBruce Allan devm_kfree(dev, buf); 2784c98ab55SBruce Allan return ret; 2794c98ab55SBruce Allan } 2804c98ab55SBruce Allan 281fcea6f3dSAnirudh Venkataramanan static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) 282fcea6f3dSAnirudh Venkataramanan { 283fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 284fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 285fcea6f3dSAnirudh Venkataramanan char *p = (char *)data; 286fcea6f3dSAnirudh Venkataramanan unsigned int i; 287fcea6f3dSAnirudh Venkataramanan 288fcea6f3dSAnirudh Venkataramanan switch (stringset) { 289fcea6f3dSAnirudh Venkataramanan case ETH_SS_STATS: 290fcea6f3dSAnirudh Venkataramanan for (i = 0; i < ICE_VSI_STATS_LEN; i++) { 291fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, "%s", 292fcea6f3dSAnirudh Venkataramanan ice_gstrings_vsi_stats[i].stat_string); 293fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 294fcea6f3dSAnirudh Venkataramanan } 295fcea6f3dSAnirudh Venkataramanan 296f8ba7db8SJacob Keller ice_for_each_alloc_txq(vsi, i) { 297fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 298fcea6f3dSAnirudh Venkataramanan "tx-queue-%u.tx_packets", i); 299fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 300fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, "tx-queue-%u.tx_bytes", i); 301fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 302fcea6f3dSAnirudh Venkataramanan } 303fcea6f3dSAnirudh Venkataramanan 304f8ba7db8SJacob Keller ice_for_each_alloc_rxq(vsi, i) { 305fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 306fcea6f3dSAnirudh Venkataramanan "rx-queue-%u.rx_packets", i); 307fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 308fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, "rx-queue-%u.rx_bytes", i); 309fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 310fcea6f3dSAnirudh Venkataramanan } 311fcea6f3dSAnirudh Venkataramanan 312fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 313fcea6f3dSAnirudh Venkataramanan return; 314fcea6f3dSAnirudh Venkataramanan 315fcea6f3dSAnirudh Venkataramanan for (i = 0; i < ICE_PF_STATS_LEN; i++) { 3161fa6e138SJesse Brandeburg snprintf(p, ETH_GSTRING_LEN, "%s", 317fcea6f3dSAnirudh Venkataramanan ice_gstrings_pf_stats[i].stat_string); 318fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 319fcea6f3dSAnirudh Venkataramanan } 320fcea6f3dSAnirudh Venkataramanan 3214b0fdcebSAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 3224b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 3234b0fdcebSAnirudh Venkataramanan "port.tx-priority-%u-xon", i); 3244b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 3254b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 3264b0fdcebSAnirudh Venkataramanan "port.tx-priority-%u-xoff", i); 3274b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 3284b0fdcebSAnirudh Venkataramanan } 3294b0fdcebSAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 3304b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 3314b0fdcebSAnirudh Venkataramanan "port.rx-priority-%u-xon", i); 3324b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 3334b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 3344b0fdcebSAnirudh Venkataramanan "port.rx-priority-%u-xoff", i); 3354b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 3364b0fdcebSAnirudh Venkataramanan } 337fcea6f3dSAnirudh Venkataramanan break; 338ab4ab73fSBruce Allan case ETH_SS_PRIV_FLAGS: 339ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 340ab4ab73fSBruce Allan snprintf(p, ETH_GSTRING_LEN, "%s", 341ab4ab73fSBruce Allan ice_gstrings_priv_flags[i].name); 342ab4ab73fSBruce Allan p += ETH_GSTRING_LEN; 343ab4ab73fSBruce Allan } 344ab4ab73fSBruce Allan break; 345fcea6f3dSAnirudh Venkataramanan default: 346fcea6f3dSAnirudh Venkataramanan break; 347fcea6f3dSAnirudh Venkataramanan } 348fcea6f3dSAnirudh Venkataramanan } 349fcea6f3dSAnirudh Venkataramanan 3508e151d50SAnirudh Venkataramanan static int 3518e151d50SAnirudh Venkataramanan ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) 3528e151d50SAnirudh Venkataramanan { 3538e151d50SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3548e151d50SAnirudh Venkataramanan bool led_active; 3558e151d50SAnirudh Venkataramanan 3568e151d50SAnirudh Venkataramanan switch (state) { 3578e151d50SAnirudh Venkataramanan case ETHTOOL_ID_ACTIVE: 3588e151d50SAnirudh Venkataramanan led_active = true; 3598e151d50SAnirudh Venkataramanan break; 3608e151d50SAnirudh Venkataramanan case ETHTOOL_ID_INACTIVE: 3618e151d50SAnirudh Venkataramanan led_active = false; 3628e151d50SAnirudh Venkataramanan break; 3638e151d50SAnirudh Venkataramanan default: 3648e151d50SAnirudh Venkataramanan return -EINVAL; 3658e151d50SAnirudh Venkataramanan } 3668e151d50SAnirudh Venkataramanan 3678e151d50SAnirudh Venkataramanan if (ice_aq_set_port_id_led(np->vsi->port_info, !led_active, NULL)) 3688e151d50SAnirudh Venkataramanan return -EIO; 3698e151d50SAnirudh Venkataramanan 3708e151d50SAnirudh Venkataramanan return 0; 3718e151d50SAnirudh Venkataramanan } 3728e151d50SAnirudh Venkataramanan 373ab4ab73fSBruce Allan /** 374ab4ab73fSBruce Allan * ice_get_priv_flags - report device private flags 375ab4ab73fSBruce Allan * @netdev: network interface device structure 376ab4ab73fSBruce Allan * 377ab4ab73fSBruce Allan * The get string set count and the string set should be matched for each 378ab4ab73fSBruce Allan * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags 379ab4ab73fSBruce Allan * array. 380ab4ab73fSBruce Allan * 381ab4ab73fSBruce Allan * Returns a u32 bitmap of flags. 382ab4ab73fSBruce Allan */ 383ab4ab73fSBruce Allan static u32 ice_get_priv_flags(struct net_device *netdev) 384ab4ab73fSBruce Allan { 385ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 386ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 387ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 388ab4ab73fSBruce Allan u32 i, ret_flags = 0; 389ab4ab73fSBruce Allan 390ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 391ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 392ab4ab73fSBruce Allan 393ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 394ab4ab73fSBruce Allan 395ab4ab73fSBruce Allan if (test_bit(priv_flag->bitno, pf->flags)) 396ab4ab73fSBruce Allan ret_flags |= BIT(i); 397ab4ab73fSBruce Allan } 398ab4ab73fSBruce Allan 399ab4ab73fSBruce Allan return ret_flags; 400ab4ab73fSBruce Allan } 401ab4ab73fSBruce Allan 402ab4ab73fSBruce Allan /** 403ab4ab73fSBruce Allan * ice_set_priv_flags - set private flags 404ab4ab73fSBruce Allan * @netdev: network interface device structure 405ab4ab73fSBruce Allan * @flags: bit flags to be set 406ab4ab73fSBruce Allan */ 407ab4ab73fSBruce Allan static int ice_set_priv_flags(struct net_device *netdev, u32 flags) 408ab4ab73fSBruce Allan { 409ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 4103a257a14SAnirudh Venkataramanan DECLARE_BITMAP(change_flags, ICE_PF_FLAGS_NBITS); 4113a257a14SAnirudh Venkataramanan DECLARE_BITMAP(orig_flags, ICE_PF_FLAGS_NBITS); 412ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 413ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 4143a257a14SAnirudh Venkataramanan int ret = 0; 415ab4ab73fSBruce Allan u32 i; 416ab4ab73fSBruce Allan 417ab4ab73fSBruce Allan if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE)) 418ab4ab73fSBruce Allan return -EINVAL; 419ab4ab73fSBruce Allan 4203a257a14SAnirudh Venkataramanan set_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 4213a257a14SAnirudh Venkataramanan 4223a257a14SAnirudh Venkataramanan bitmap_copy(orig_flags, pf->flags, ICE_PF_FLAGS_NBITS); 423ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 424ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 425ab4ab73fSBruce Allan 426ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 427ab4ab73fSBruce Allan 428ab4ab73fSBruce Allan if (flags & BIT(i)) 429ab4ab73fSBruce Allan set_bit(priv_flag->bitno, pf->flags); 430ab4ab73fSBruce Allan else 431ab4ab73fSBruce Allan clear_bit(priv_flag->bitno, pf->flags); 432ab4ab73fSBruce Allan } 433ab4ab73fSBruce Allan 4343a257a14SAnirudh Venkataramanan bitmap_xor(change_flags, pf->flags, orig_flags, ICE_PF_FLAGS_NBITS); 4353a257a14SAnirudh Venkataramanan 43631eafa40SAnirudh Venkataramanan if (test_bit(ICE_FLAG_ENABLE_FW_LLDP, change_flags)) { 43731eafa40SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags)) { 4383a257a14SAnirudh Venkataramanan enum ice_status status; 4393a257a14SAnirudh Venkataramanan 4403a257a14SAnirudh Venkataramanan status = ice_aq_cfg_lldp_mib_change(&pf->hw, false, 4413a257a14SAnirudh Venkataramanan NULL); 4423a257a14SAnirudh Venkataramanan /* If unregistering for LLDP events fails, this is 4433a257a14SAnirudh Venkataramanan * not an error state, as there shouldn't be any 4443a257a14SAnirudh Venkataramanan * events to respond to. 4453a257a14SAnirudh Venkataramanan */ 4463a257a14SAnirudh Venkataramanan if (status) 4473a257a14SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 4483a257a14SAnirudh Venkataramanan "Failed to unreg for LLDP events\n"); 4493a257a14SAnirudh Venkataramanan 4503a257a14SAnirudh Venkataramanan /* The AQ call to stop the FW LLDP agent will generate 4513a257a14SAnirudh Venkataramanan * an error if the agent is already stopped. 4523a257a14SAnirudh Venkataramanan */ 45331eafa40SAnirudh Venkataramanan status = ice_aq_stop_lldp(&pf->hw, true, true, NULL); 4543a257a14SAnirudh Venkataramanan if (status) 4553a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 4563a257a14SAnirudh Venkataramanan "Fail to stop LLDP agent\n"); 4573a257a14SAnirudh Venkataramanan /* Use case for having the FW LLDP agent stopped 4583a257a14SAnirudh Venkataramanan * will likely not need DCB, so failure to init is 4593a257a14SAnirudh Venkataramanan * not a concern of ethtool 4603a257a14SAnirudh Venkataramanan */ 461e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 4623a257a14SAnirudh Venkataramanan if (status) 4633a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Fail to init DCB\n"); 4643a257a14SAnirudh Venkataramanan } else { 4653a257a14SAnirudh Venkataramanan enum ice_status status; 4663a257a14SAnirudh Venkataramanan bool dcbx_agent_status; 4673a257a14SAnirudh Venkataramanan 4683a257a14SAnirudh Venkataramanan /* AQ command to start FW LLDP agent will return an 4693a257a14SAnirudh Venkataramanan * error if the agent is already started 4703a257a14SAnirudh Venkataramanan */ 47131eafa40SAnirudh Venkataramanan status = ice_aq_start_lldp(&pf->hw, true, NULL); 4723a257a14SAnirudh Venkataramanan if (status) 4733a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 4743a257a14SAnirudh Venkataramanan "Fail to start LLDP Agent\n"); 4753a257a14SAnirudh Venkataramanan 4763a257a14SAnirudh Venkataramanan /* AQ command to start FW DCBx agent will fail if 4773a257a14SAnirudh Venkataramanan * the agent is already started 4783a257a14SAnirudh Venkataramanan */ 4793a257a14SAnirudh Venkataramanan status = ice_aq_start_stop_dcbx(&pf->hw, true, 4803a257a14SAnirudh Venkataramanan &dcbx_agent_status, 4813a257a14SAnirudh Venkataramanan NULL); 4823a257a14SAnirudh Venkataramanan if (status) 4833a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 4843a257a14SAnirudh Venkataramanan "Failed to start FW DCBX\n"); 4853a257a14SAnirudh Venkataramanan 4863a257a14SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "FW DCBX agent is %s\n", 4873a257a14SAnirudh Venkataramanan dcbx_agent_status ? "ACTIVE" : "DISABLED"); 4883a257a14SAnirudh Venkataramanan 4893a257a14SAnirudh Venkataramanan /* Failure to configure MIB change or init DCB is not 4903a257a14SAnirudh Venkataramanan * relevant to ethtool. Print notification that 4913a257a14SAnirudh Venkataramanan * registration/init failed but do not return error 4923a257a14SAnirudh Venkataramanan * state to ethtool 4933a257a14SAnirudh Venkataramanan */ 4943a257a14SAnirudh Venkataramanan status = ice_aq_cfg_lldp_mib_change(&pf->hw, false, 4953a257a14SAnirudh Venkataramanan NULL); 4963a257a14SAnirudh Venkataramanan if (status) 4973a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 4983a257a14SAnirudh Venkataramanan "Fail to reg for MIB change\n"); 4993a257a14SAnirudh Venkataramanan 500e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 5013a257a14SAnirudh Venkataramanan if (status) 5023a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "Fail to init DCB\n"); 5033a257a14SAnirudh Venkataramanan } 5043a257a14SAnirudh Venkataramanan } 5053a257a14SAnirudh Venkataramanan clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 5063a257a14SAnirudh Venkataramanan return ret; 507ab4ab73fSBruce Allan } 508ab4ab73fSBruce Allan 509fcea6f3dSAnirudh Venkataramanan static int ice_get_sset_count(struct net_device *netdev, int sset) 510fcea6f3dSAnirudh Venkataramanan { 511fcea6f3dSAnirudh Venkataramanan switch (sset) { 512fcea6f3dSAnirudh Venkataramanan case ETH_SS_STATS: 513f8ba7db8SJacob Keller /* The number (and order) of strings reported *must* remain 514f8ba7db8SJacob Keller * constant for a given netdevice. This function must not 515f8ba7db8SJacob Keller * report a different number based on run time parameters 516f8ba7db8SJacob Keller * (such as the number of queues in use, or the setting of 517f8ba7db8SJacob Keller * a private ethtool flag). This is due to the nature of the 518f8ba7db8SJacob Keller * ethtool stats API. 519f8ba7db8SJacob Keller * 520f8ba7db8SJacob Keller * Userspace programs such as ethtool must make 3 separate 521f8ba7db8SJacob Keller * ioctl requests, one for size, one for the strings, and 522f8ba7db8SJacob Keller * finally one for the stats. Since these cross into 523f8ba7db8SJacob Keller * userspace, changes to the number or size could result in 524f8ba7db8SJacob Keller * undefined memory access or incorrect string<->value 525f8ba7db8SJacob Keller * correlations for statistics. 526f8ba7db8SJacob Keller * 527f8ba7db8SJacob Keller * Even if it appears to be safe, changes to the size or 528f8ba7db8SJacob Keller * order of strings will suffer from race conditions and are 529f8ba7db8SJacob Keller * not safe. 530f8ba7db8SJacob Keller */ 531fcea6f3dSAnirudh Venkataramanan return ICE_ALL_STATS_LEN(netdev); 532ab4ab73fSBruce Allan case ETH_SS_PRIV_FLAGS: 533ab4ab73fSBruce Allan return ICE_PRIV_FLAG_ARRAY_SIZE; 534fcea6f3dSAnirudh Venkataramanan default: 535fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 536fcea6f3dSAnirudh Venkataramanan } 537fcea6f3dSAnirudh Venkataramanan } 538fcea6f3dSAnirudh Venkataramanan 539fcea6f3dSAnirudh Venkataramanan static void 540fcea6f3dSAnirudh Venkataramanan ice_get_ethtool_stats(struct net_device *netdev, 541fcea6f3dSAnirudh Venkataramanan struct ethtool_stats __always_unused *stats, u64 *data) 542fcea6f3dSAnirudh Venkataramanan { 543fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 544fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 545fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 546fcea6f3dSAnirudh Venkataramanan struct ice_ring *ring; 547fcea6f3dSAnirudh Venkataramanan unsigned int j = 0; 548fcea6f3dSAnirudh Venkataramanan int i = 0; 549fcea6f3dSAnirudh Venkataramanan char *p; 550fcea6f3dSAnirudh Venkataramanan 551fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_VSI_STATS_LEN; j++) { 552fcea6f3dSAnirudh Venkataramanan p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; 553fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == 554fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 555fcea6f3dSAnirudh Venkataramanan } 556fcea6f3dSAnirudh Venkataramanan 557fcea6f3dSAnirudh Venkataramanan /* populate per queue stats */ 558fcea6f3dSAnirudh Venkataramanan rcu_read_lock(); 559fcea6f3dSAnirudh Venkataramanan 560f8ba7db8SJacob Keller ice_for_each_alloc_txq(vsi, j) { 561fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->tx_rings[j]); 562f8ba7db8SJacob Keller if (ring) { 563fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 564fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 565f8ba7db8SJacob Keller } else { 566f8ba7db8SJacob Keller data[i++] = 0; 567f8ba7db8SJacob Keller data[i++] = 0; 568f8ba7db8SJacob Keller } 569fcea6f3dSAnirudh Venkataramanan } 570fcea6f3dSAnirudh Venkataramanan 571f8ba7db8SJacob Keller ice_for_each_alloc_rxq(vsi, j) { 572fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->rx_rings[j]); 573f8ba7db8SJacob Keller if (ring) { 574fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 575fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 576f8ba7db8SJacob Keller } else { 577f8ba7db8SJacob Keller data[i++] = 0; 578f8ba7db8SJacob Keller data[i++] = 0; 579f8ba7db8SJacob Keller } 580fcea6f3dSAnirudh Venkataramanan } 581fcea6f3dSAnirudh Venkataramanan 582fcea6f3dSAnirudh Venkataramanan rcu_read_unlock(); 583fcea6f3dSAnirudh Venkataramanan 584fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 585fcea6f3dSAnirudh Venkataramanan return; 586fcea6f3dSAnirudh Venkataramanan 587fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_PF_STATS_LEN; j++) { 588fcea6f3dSAnirudh Venkataramanan p = (char *)pf + ice_gstrings_pf_stats[j].stat_offset; 589fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_pf_stats[j].sizeof_stat == 590fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 591fcea6f3dSAnirudh Venkataramanan } 5924b0fdcebSAnirudh Venkataramanan 5934b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 5944b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_tx[j]; 5954b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_tx[j]; 5964b0fdcebSAnirudh Venkataramanan } 5974b0fdcebSAnirudh Venkataramanan 5984b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 5994b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_rx[j]; 6004b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_rx[j]; 6014b0fdcebSAnirudh Venkataramanan } 602fcea6f3dSAnirudh Venkataramanan } 603fcea6f3dSAnirudh Venkataramanan 60448cb27f2SChinh Cao /** 60548cb27f2SChinh Cao * ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes 60648cb27f2SChinh Cao * @netdev: network interface device structure 60748cb27f2SChinh Cao * @ks: ethtool link ksettings struct to fill out 60848cb27f2SChinh Cao */ 609aef74145SAnirudh Venkataramanan static void 610aef74145SAnirudh Venkataramanan ice_phy_type_to_ethtool(struct net_device *netdev, 611fcea6f3dSAnirudh Venkataramanan struct ethtool_link_ksettings *ks) 612fcea6f3dSAnirudh Venkataramanan { 613fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 614fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 615aef74145SAnirudh Venkataramanan bool need_add_adv_mode = false; 616fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 617aef74145SAnirudh Venkataramanan u64 phy_types_high; 61848cb27f2SChinh Cao u64 phy_types_low; 619fcea6f3dSAnirudh Venkataramanan 620fcea6f3dSAnirudh Venkataramanan hw_link_info = &vsi->port_info->phy.link_info; 62148cb27f2SChinh Cao phy_types_low = vsi->port_info->phy.phy_type_low; 622aef74145SAnirudh Venkataramanan phy_types_high = vsi->port_info->phy.phy_type_high; 623fcea6f3dSAnirudh Venkataramanan 62448cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 62548cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 62648cb27f2SChinh Cao 62748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 62848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_100M_SGMII) { 62948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 63048cb27f2SChinh Cao 100baseT_Full); 6319ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6329ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100MB) 63348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 63448cb27f2SChinh Cao 100baseT_Full); 63548cb27f2SChinh Cao } 63648cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 63748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1G_SGMII) { 63848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 63948cb27f2SChinh Cao 1000baseT_Full); 6409ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6419ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 64248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 64348cb27f2SChinh Cao 1000baseT_Full); 64448cb27f2SChinh Cao } 64548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX) { 64648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 64748cb27f2SChinh Cao 1000baseKX_Full); 6489ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6499ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 65048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 65148cb27f2SChinh Cao 1000baseKX_Full); 65248cb27f2SChinh Cao } 65348cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_SX || 65448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_LX) { 65548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 65648cb27f2SChinh Cao 1000baseX_Full); 6579ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6589ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 65948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 66048cb27f2SChinh Cao 1000baseX_Full); 66148cb27f2SChinh Cao } 66248cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T) { 66348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 66448cb27f2SChinh Cao 2500baseT_Full); 6659ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6669ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 66748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 66848cb27f2SChinh Cao 2500baseT_Full); 66948cb27f2SChinh Cao } 67048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_X || 67148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX) { 67248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 67348cb27f2SChinh Cao 2500baseX_Full); 6749ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6759ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 67648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 67748cb27f2SChinh Cao 2500baseX_Full); 67848cb27f2SChinh Cao } 67948cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 68048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR) { 68148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 68248cb27f2SChinh Cao 5000baseT_Full); 6839ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6849ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_5GB) 68548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 68648cb27f2SChinh Cao 5000baseT_Full); 68748cb27f2SChinh Cao } 68848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 68948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_DA || 69048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC || 69148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_C2C) { 692fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 693fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 6949ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 6959ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 696fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 697fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 69848cb27f2SChinh Cao } 69948cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1) { 70048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 70148cb27f2SChinh Cao 10000baseKR_Full); 7029ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7039ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 70448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 70548cb27f2SChinh Cao 10000baseKR_Full); 70648cb27f2SChinh Cao } 70748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_SR) { 70848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 70948cb27f2SChinh Cao 10000baseSR_Full); 7109ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7119ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 71248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 71348cb27f2SChinh Cao 10000baseSR_Full); 71448cb27f2SChinh Cao } 71548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_LR) { 71648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 71748cb27f2SChinh Cao 10000baseLR_Full); 7189ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7199ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 72048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 72148cb27f2SChinh Cao 10000baseLR_Full); 72248cb27f2SChinh Cao } 72348cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 72448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 72548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 72648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 72748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC || 72848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_C2C) { 72948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 73048cb27f2SChinh Cao 25000baseCR_Full); 7319ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7329ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 73348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 73448cb27f2SChinh Cao 25000baseCR_Full); 73548cb27f2SChinh Cao } 73648cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_SR || 73748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_LR) { 73848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 73948cb27f2SChinh Cao 25000baseSR_Full); 7409ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7419ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 74248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 74348cb27f2SChinh Cao 25000baseSR_Full); 74448cb27f2SChinh Cao } 74548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 74648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 74748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1) { 74848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 74948cb27f2SChinh Cao 25000baseKR_Full); 7509ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7519ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 75248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 75348cb27f2SChinh Cao 25000baseKR_Full); 75448cb27f2SChinh Cao } 75548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 75648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 75748cb27f2SChinh Cao 40000baseKR4_Full); 7589ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7599ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 76048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 76148cb27f2SChinh Cao 40000baseKR4_Full); 76248cb27f2SChinh Cao } 76348cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 76448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC || 76548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI) { 76648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 76748cb27f2SChinh Cao 40000baseCR4_Full); 7689ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7699ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 77048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 77148cb27f2SChinh Cao 40000baseCR4_Full); 77248cb27f2SChinh Cao } 77348cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_SR4) { 77448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 77548cb27f2SChinh Cao 40000baseSR4_Full); 7769ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7779ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 77848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 77948cb27f2SChinh Cao 40000baseSR4_Full); 78048cb27f2SChinh Cao } 78148cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_LR4) { 78248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 78348cb27f2SChinh Cao 40000baseLR4_Full); 7849ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 7859ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 78648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 78748cb27f2SChinh Cao 40000baseLR4_Full); 78848cb27f2SChinh Cao } 789aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 790aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC || 791aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2 || 792aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC || 793aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2 || 794aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 795aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR || 796aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC || 797aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1) { 798aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 799aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 8009ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 8019ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 802aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 803aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 804aef74145SAnirudh Venkataramanan } 805aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 806aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 807aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 808aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 8099ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 8109ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 811aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 812aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 813aef74145SAnirudh Venkataramanan } 814aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR2 || 815aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR2 || 816aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_FR || 817aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR) { 818aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 819aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 8209ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 8219ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 822aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 823aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 824aef74145SAnirudh Venkataramanan } 825aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 826aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC || 827aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4 || 828aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC || 829aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4 || 830aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 || 831aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2 || 832aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC || 833aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2 || 834aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC || 835aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2) { 836aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 837aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 8389ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 8399ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 840aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 841aef74145SAnirudh Venkataramanan } 842aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 843aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 844aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 845aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 846aef74145SAnirudh Venkataramanan } 847aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4 || 848aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) { 849aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 850aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 8519ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 8529ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 853aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 854aef74145SAnirudh Venkataramanan } 855aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 856aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 857aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 858aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 859aef74145SAnirudh Venkataramanan } 860aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_LR4 || 861aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_DR) { 862aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 863aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 8649ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 8659ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 866aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 867aef74145SAnirudh Venkataramanan } 868aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 869aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 870aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 871aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 872aef74145SAnirudh Venkataramanan } 873aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || 874aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || 875aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) { 876aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 877aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 8789ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 8799ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 880aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 881aef74145SAnirudh Venkataramanan } 882aef74145SAnirudh Venkataramanan if (need_add_adv_mode) 883aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 884aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 885fcea6f3dSAnirudh Venkataramanan 88648cb27f2SChinh Cao /* Autoneg PHY types */ 88748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 88848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 88948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX || 89048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T || 89148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX || 89248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 89348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR || 89448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 89548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 || 89648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 89748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 89848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 89948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 90048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 90148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 90248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1 || 90348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 90448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 90548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 90648cb27f2SChinh Cao Autoneg); 90748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 90848cb27f2SChinh Cao Autoneg); 90948cb27f2SChinh Cao } 910aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 911aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 912aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 913aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 914aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 915aef74145SAnirudh Venkataramanan Autoneg); 916aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 917aef74145SAnirudh Venkataramanan Autoneg); 918aef74145SAnirudh Venkataramanan } 919aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 920aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || 921aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || 922aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) { 923aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 924aef74145SAnirudh Venkataramanan Autoneg); 925aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 926aef74145SAnirudh Venkataramanan Autoneg); 927aef74145SAnirudh Venkataramanan } 92848cb27f2SChinh Cao } 92948cb27f2SChinh Cao 93048cb27f2SChinh Cao #define TEST_SET_BITS_TIMEOUT 50 93148cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MAX 2000 93248cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MIN 1000 93348cb27f2SChinh Cao 93448cb27f2SChinh Cao /** 93548cb27f2SChinh Cao * ice_get_settings_link_up - Get Link settings for when link is up 93648cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 93748cb27f2SChinh Cao * @netdev: network interface device structure 93848cb27f2SChinh Cao */ 939aef74145SAnirudh Venkataramanan static void 940aef74145SAnirudh Venkataramanan ice_get_settings_link_up(struct ethtool_link_ksettings *ks, 94148cb27f2SChinh Cao struct net_device *netdev) 94248cb27f2SChinh Cao { 94348cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 94448cb27f2SChinh Cao struct ethtool_link_ksettings cap_ksettings; 94548cb27f2SChinh Cao struct ice_link_status *link_info; 94648cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 947aef74145SAnirudh Venkataramanan bool unrecog_phy_high = false; 94848cb27f2SChinh Cao bool unrecog_phy_low = false; 94948cb27f2SChinh Cao 95048cb27f2SChinh Cao link_info = &vsi->port_info->phy.link_info; 95148cb27f2SChinh Cao 952f9867df6SAnirudh Venkataramanan /* Initialize supported and advertised settings based on PHY settings */ 95348cb27f2SChinh Cao switch (link_info->phy_type_low) { 95448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_100BASE_TX: 95548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 95648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 95748cb27f2SChinh Cao 100baseT_Full); 95848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 95948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 96048cb27f2SChinh Cao 100baseT_Full); 961fcea6f3dSAnirudh Venkataramanan break; 96248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_100M_SGMII: 96348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 96448cb27f2SChinh Cao 100baseT_Full); 965fcea6f3dSAnirudh Venkataramanan break; 96648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_T: 96748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 96848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 96948cb27f2SChinh Cao 1000baseT_Full); 97048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 97148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 97248cb27f2SChinh Cao 1000baseT_Full); 973fcea6f3dSAnirudh Venkataramanan break; 97448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1G_SGMII: 97548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 97648cb27f2SChinh Cao 1000baseT_Full); 97748cb27f2SChinh Cao break; 97848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_SX: 97948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_LX: 98048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 98148cb27f2SChinh Cao 1000baseX_Full); 98248cb27f2SChinh Cao break; 98348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_KX: 98448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 98548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 98648cb27f2SChinh Cao 1000baseKX_Full); 98748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 98848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 98948cb27f2SChinh Cao 1000baseKX_Full); 99048cb27f2SChinh Cao break; 99148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_T: 99248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 99348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 99448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 99548cb27f2SChinh Cao 2500baseT_Full); 99648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 99748cb27f2SChinh Cao 2500baseT_Full); 99848cb27f2SChinh Cao break; 99948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_X: 100048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 100148cb27f2SChinh Cao 2500baseX_Full); 100248cb27f2SChinh Cao break; 100348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_KX: 100448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 100548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 100648cb27f2SChinh Cao 2500baseX_Full); 100748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 100848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 100948cb27f2SChinh Cao 2500baseX_Full); 101048cb27f2SChinh Cao break; 101148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_5GBASE_T: 101248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_5GBASE_KR: 101348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 101448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 101548cb27f2SChinh Cao 5000baseT_Full); 101648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 101748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 101848cb27f2SChinh Cao 5000baseT_Full); 101948cb27f2SChinh Cao break; 102048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_T: 102148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 102248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 102348cb27f2SChinh Cao 10000baseT_Full); 102448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 102548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 102648cb27f2SChinh Cao 10000baseT_Full); 102748cb27f2SChinh Cao break; 102848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_DA: 102948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC: 103048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 103148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 103248cb27f2SChinh Cao 10000baseT_Full); 103348cb27f2SChinh Cao break; 103448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_SR: 103548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 103648cb27f2SChinh Cao 10000baseSR_Full); 103748cb27f2SChinh Cao break; 103848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_LR: 103948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 104048cb27f2SChinh Cao 10000baseLR_Full); 104148cb27f2SChinh Cao break; 104248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 104348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 104448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 104548cb27f2SChinh Cao 10000baseKR_Full); 104648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 104748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 104848cb27f2SChinh Cao 10000baseKR_Full); 104948cb27f2SChinh Cao break; 105048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_T: 105148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR: 105248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 105348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR1: 105448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 105548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 105648cb27f2SChinh Cao 25000baseCR_Full); 105748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 105848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 105948cb27f2SChinh Cao 25000baseCR_Full); 106048cb27f2SChinh Cao break; 106148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC: 106249a6a5d7STony Nguyen case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 106348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 106448cb27f2SChinh Cao 25000baseCR_Full); 106548cb27f2SChinh Cao break; 106648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_SR: 106748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_LR: 106848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 106948cb27f2SChinh Cao 25000baseSR_Full); 107048cb27f2SChinh Cao break; 107148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR: 107248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR1: 107348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 107448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 107548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 107648cb27f2SChinh Cao 25000baseKR_Full); 107748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 107848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 107948cb27f2SChinh Cao 25000baseKR_Full); 108048cb27f2SChinh Cao break; 108148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_CR4: 108248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 108348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 108448cb27f2SChinh Cao 40000baseCR4_Full); 108548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 108648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 108748cb27f2SChinh Cao 40000baseCR4_Full); 108848cb27f2SChinh Cao break; 108948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC: 109048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40G_XLAUI: 109148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 109248cb27f2SChinh Cao 40000baseCR4_Full); 109348cb27f2SChinh Cao break; 109448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_SR4: 109548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 109648cb27f2SChinh Cao 40000baseSR4_Full); 109748cb27f2SChinh Cao break; 109848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_LR4: 109948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 110048cb27f2SChinh Cao 40000baseLR4_Full); 110148cb27f2SChinh Cao break; 110248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_KR4: 110348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 110448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 110548cb27f2SChinh Cao 40000baseKR4_Full); 110648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 110748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 110848cb27f2SChinh Cao 40000baseKR4_Full); 110948cb27f2SChinh Cao break; 1110aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_CR2: 1111aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_CP: 1112aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1113aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1114aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1115aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1116aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1117aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1118aef74145SAnirudh Venkataramanan break; 1119aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: 1120aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_LAUI2: 1121aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: 1122aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI2: 1123aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_SR: 1124aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: 1125aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI1: 1126aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1127aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1128aef74145SAnirudh Venkataramanan break; 1129aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_KR2: 1130aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: 1131aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1132aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1133aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1134aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1135aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1136aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1137aef74145SAnirudh Venkataramanan break; 1138aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_SR2: 1139aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_LR2: 1140aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_FR: 1141aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_LR: 1142aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1143aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 1144aef74145SAnirudh Venkataramanan break; 1145aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CR4: 1146aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1147aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1148aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1149aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1150aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1151aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1152aef74145SAnirudh Venkataramanan break; 1153aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: 1154aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_CAUI4: 1155aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: 1156aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_AUI4: 1157aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: 1158aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1159aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1160aef74145SAnirudh Venkataramanan break; 1161aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CP2: 1162aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1163aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1164aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1165aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1166aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1167aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1168aef74145SAnirudh Venkataramanan break; 1169aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_SR4: 1170aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_SR2: 1171aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1172aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 1173aef74145SAnirudh Venkataramanan break; 1174aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_LR4: 1175aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_DR: 1176aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1177aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 1178aef74145SAnirudh Venkataramanan break; 1179aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_KR4: 1180aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: 1181aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1182aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1183aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1184aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1185aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1186aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1187aef74145SAnirudh Venkataramanan break; 118848cb27f2SChinh Cao default: 118948cb27f2SChinh Cao unrecog_phy_low = true; 119048cb27f2SChinh Cao } 119148cb27f2SChinh Cao 1192aef74145SAnirudh Venkataramanan switch (link_info->phy_type_high) { 1193aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: 1194aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1195aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1196aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1197aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1198aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1199aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1200aef74145SAnirudh Venkataramanan break; 1201aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: 1202aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_CAUI2: 1203aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: 1204aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_AUI2: 1205aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1206aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1207aef74145SAnirudh Venkataramanan break; 1208aef74145SAnirudh Venkataramanan default: 1209aef74145SAnirudh Venkataramanan unrecog_phy_high = true; 1210aef74145SAnirudh Venkataramanan } 1211aef74145SAnirudh Venkataramanan 1212aef74145SAnirudh Venkataramanan if (unrecog_phy_low && unrecog_phy_high) { 121348cb27f2SChinh Cao /* if we got here and link is up something bad is afoot */ 1214aef74145SAnirudh Venkataramanan netdev_info(netdev, 1215aef74145SAnirudh Venkataramanan "WARNING: Unrecognized PHY_Low (0x%llx).\n", 121648cb27f2SChinh Cao (u64)link_info->phy_type_low); 1217aef74145SAnirudh Venkataramanan netdev_info(netdev, 1218aef74145SAnirudh Venkataramanan "WARNING: Unrecognized PHY_High (0x%llx).\n", 1219aef74145SAnirudh Venkataramanan (u64)link_info->phy_type_high); 122048cb27f2SChinh Cao } 122148cb27f2SChinh Cao 122248cb27f2SChinh Cao /* Now that we've worked out everything that could be supported by the 122348cb27f2SChinh Cao * current PHY type, get what is supported by the NVM and intersect 122448cb27f2SChinh Cao * them to get what is truly supported 122548cb27f2SChinh Cao */ 1226c6dfd690SBruce Allan memset(&cap_ksettings, 0, sizeof(cap_ksettings)); 122748cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, &cap_ksettings); 122848cb27f2SChinh Cao ethtool_intersect_link_masks(ks, &cap_ksettings); 122948cb27f2SChinh Cao 123048cb27f2SChinh Cao switch (link_info->link_speed) { 1231aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_100GB: 1232aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_100000; 1233aef74145SAnirudh Venkataramanan break; 1234aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_50GB: 1235aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_50000; 1236aef74145SAnirudh Venkataramanan break; 123748cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_40GB: 123848cb27f2SChinh Cao ks->base.speed = SPEED_40000; 1239fcea6f3dSAnirudh Venkataramanan break; 1240fcea6f3dSAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_25GB: 1241fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_25000; 1242fcea6f3dSAnirudh Venkataramanan break; 124348cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_20GB: 124448cb27f2SChinh Cao ks->base.speed = SPEED_20000; 124548cb27f2SChinh Cao break; 124648cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_10GB: 124748cb27f2SChinh Cao ks->base.speed = SPEED_10000; 124848cb27f2SChinh Cao break; 124948cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_5GB: 125048cb27f2SChinh Cao ks->base.speed = SPEED_5000; 125148cb27f2SChinh Cao break; 125248cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_2500MB: 125348cb27f2SChinh Cao ks->base.speed = SPEED_2500; 125448cb27f2SChinh Cao break; 125548cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_1000MB: 125648cb27f2SChinh Cao ks->base.speed = SPEED_1000; 125748cb27f2SChinh Cao break; 125848cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_100MB: 125948cb27f2SChinh Cao ks->base.speed = SPEED_100; 1260fcea6f3dSAnirudh Venkataramanan break; 1261fcea6f3dSAnirudh Venkataramanan default: 126248cb27f2SChinh Cao netdev_info(netdev, 126348cb27f2SChinh Cao "WARNING: Unrecognized link_speed (0x%x).\n", 126448cb27f2SChinh Cao link_info->link_speed); 1265fcea6f3dSAnirudh Venkataramanan break; 1266fcea6f3dSAnirudh Venkataramanan } 1267fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_FULL; 126848cb27f2SChinh Cao } 126948cb27f2SChinh Cao 127048cb27f2SChinh Cao /** 127148cb27f2SChinh Cao * ice_get_settings_link_down - Get the Link settings when link is down 127248cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 127348cb27f2SChinh Cao * @netdev: network interface device structure 127448cb27f2SChinh Cao * 127548cb27f2SChinh Cao * Reports link settings that can be determined when link is down 127648cb27f2SChinh Cao */ 127748cb27f2SChinh Cao static void 127848cb27f2SChinh Cao ice_get_settings_link_down(struct ethtool_link_ksettings *ks, 1279a03499d6STony Nguyen struct net_device *netdev) 128048cb27f2SChinh Cao { 128148cb27f2SChinh Cao /* link is down and the driver needs to fall back on 1282f9867df6SAnirudh Venkataramanan * supported PHY types to figure out what info to display 128348cb27f2SChinh Cao */ 128448cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, ks); 128548cb27f2SChinh Cao 128648cb27f2SChinh Cao /* With no link, speed and duplex are unknown */ 1287fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_UNKNOWN; 1288fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_UNKNOWN; 1289fcea6f3dSAnirudh Venkataramanan } 1290fcea6f3dSAnirudh Venkataramanan 129148cb27f2SChinh Cao /** 129248cb27f2SChinh Cao * ice_get_link_ksettings - Get Link Speed and Duplex settings 129348cb27f2SChinh Cao * @netdev: network interface device structure 129448cb27f2SChinh Cao * @ks: ethtool ksettings 129548cb27f2SChinh Cao * 129648cb27f2SChinh Cao * Reports speed/duplex settings based on media_type 129748cb27f2SChinh Cao */ 1298c8b7abddSBruce Allan static int 1299c8b7abddSBruce Allan ice_get_link_ksettings(struct net_device *netdev, 130048cb27f2SChinh Cao struct ethtool_link_ksettings *ks) 130148cb27f2SChinh Cao { 130248cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 130348cb27f2SChinh Cao struct ice_link_status *hw_link_info; 130448cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 130548cb27f2SChinh Cao 130648cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 130748cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 130848cb27f2SChinh Cao hw_link_info = &vsi->port_info->phy.link_info; 130948cb27f2SChinh Cao 131048cb27f2SChinh Cao /* set speed and duplex */ 131148cb27f2SChinh Cao if (hw_link_info->link_info & ICE_AQ_LINK_UP) 131248cb27f2SChinh Cao ice_get_settings_link_up(ks, netdev); 131348cb27f2SChinh Cao else 131448cb27f2SChinh Cao ice_get_settings_link_down(ks, netdev); 131548cb27f2SChinh Cao 1316fcea6f3dSAnirudh Venkataramanan /* set autoneg settings */ 131748cb27f2SChinh Cao ks->base.autoneg = (hw_link_info->an_info & ICE_AQ_AN_COMPLETED) ? 131848cb27f2SChinh Cao AUTONEG_ENABLE : AUTONEG_DISABLE; 1319fcea6f3dSAnirudh Venkataramanan 1320fcea6f3dSAnirudh Venkataramanan /* set media type settings */ 1321fcea6f3dSAnirudh Venkataramanan switch (vsi->port_info->phy.media_type) { 1322fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_FIBER: 1323fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 1324fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_FIBRE; 1325fcea6f3dSAnirudh Venkataramanan break; 1326fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BASET: 1327fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, TP); 1328fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, TP); 1329fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_TP; 1330fcea6f3dSAnirudh Venkataramanan break; 1331fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BACKPLANE: 1332fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1333fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Backplane); 1334fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1335fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1336fcea6f3dSAnirudh Venkataramanan Backplane); 1337fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_NONE; 1338fcea6f3dSAnirudh Venkataramanan break; 1339fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_DA: 1340fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 1341fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE); 1342fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_DA; 1343fcea6f3dSAnirudh Venkataramanan break; 1344fcea6f3dSAnirudh Venkataramanan default: 1345fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_OTHER; 1346fcea6f3dSAnirudh Venkataramanan break; 1347fcea6f3dSAnirudh Venkataramanan } 1348fcea6f3dSAnirudh Venkataramanan 1349fcea6f3dSAnirudh Venkataramanan /* flow control is symmetric and always supported */ 1350fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Pause); 1351fcea6f3dSAnirudh Venkataramanan 1352fcea6f3dSAnirudh Venkataramanan switch (vsi->port_info->fc.req_mode) { 1353fcea6f3dSAnirudh Venkataramanan case ICE_FC_FULL: 1354fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 1355fcea6f3dSAnirudh Venkataramanan break; 1356fcea6f3dSAnirudh Venkataramanan case ICE_FC_TX_PAUSE: 1357fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1358fcea6f3dSAnirudh Venkataramanan Asym_Pause); 1359fcea6f3dSAnirudh Venkataramanan break; 1360fcea6f3dSAnirudh Venkataramanan case ICE_FC_RX_PAUSE: 1361fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 1362fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1363fcea6f3dSAnirudh Venkataramanan Asym_Pause); 1364fcea6f3dSAnirudh Venkataramanan break; 1365fcea6f3dSAnirudh Venkataramanan case ICE_FC_PFC: 1366fcea6f3dSAnirudh Venkataramanan default: 1367fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, Pause); 1368fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, 1369fcea6f3dSAnirudh Venkataramanan Asym_Pause); 1370fcea6f3dSAnirudh Venkataramanan break; 1371fcea6f3dSAnirudh Venkataramanan } 1372fcea6f3dSAnirudh Venkataramanan 1373fcea6f3dSAnirudh Venkataramanan return 0; 1374fcea6f3dSAnirudh Venkataramanan } 1375fcea6f3dSAnirudh Venkataramanan 1376fcea6f3dSAnirudh Venkataramanan /** 137748cb27f2SChinh Cao * ice_ksettings_find_adv_link_speed - Find advertising link speed 137848cb27f2SChinh Cao * @ks: ethtool ksettings 137948cb27f2SChinh Cao */ 138048cb27f2SChinh Cao static u16 138148cb27f2SChinh Cao ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks) 138248cb27f2SChinh Cao { 138348cb27f2SChinh Cao u16 adv_link_speed = 0; 138448cb27f2SChinh Cao 138548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 138648cb27f2SChinh Cao 100baseT_Full)) 138748cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_100MB; 138848cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 138948cb27f2SChinh Cao 1000baseX_Full)) 139048cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 139148cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 139248cb27f2SChinh Cao 1000baseT_Full) || 139348cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 139448cb27f2SChinh Cao 1000baseKX_Full)) 139548cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 139648cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 139748cb27f2SChinh Cao 2500baseT_Full)) 139848cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 139948cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 140048cb27f2SChinh Cao 2500baseX_Full)) 140148cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 140248cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 140348cb27f2SChinh Cao 5000baseT_Full)) 140448cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_5GB; 140548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 140648cb27f2SChinh Cao 10000baseT_Full) || 140748cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 140848cb27f2SChinh Cao 10000baseKR_Full)) 140948cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 141048cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 141148cb27f2SChinh Cao 10000baseSR_Full) || 141248cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 141348cb27f2SChinh Cao 10000baseLR_Full)) 141448cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 141548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 141648cb27f2SChinh Cao 25000baseCR_Full) || 141748cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 141848cb27f2SChinh Cao 25000baseSR_Full) || 141948cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 142048cb27f2SChinh Cao 25000baseKR_Full)) 142148cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_25GB; 142248cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 142348cb27f2SChinh Cao 40000baseCR4_Full) || 142448cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 142548cb27f2SChinh Cao 40000baseSR4_Full) || 142648cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 142748cb27f2SChinh Cao 40000baseLR4_Full) || 142848cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 142948cb27f2SChinh Cao 40000baseKR4_Full)) 143048cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_40GB; 1431aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 1432aef74145SAnirudh Venkataramanan 50000baseCR2_Full) || 1433aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 1434aef74145SAnirudh Venkataramanan 50000baseKR2_Full)) 1435aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 1436aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 1437aef74145SAnirudh Venkataramanan 50000baseSR2_Full)) 1438aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 1439aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 1440aef74145SAnirudh Venkataramanan 100000baseCR4_Full) || 1441aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 1442aef74145SAnirudh Venkataramanan 100000baseSR4_Full) || 1443aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 1444aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full) || 1445aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 1446aef74145SAnirudh Venkataramanan 100000baseKR4_Full)) 1447aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_100GB; 144848cb27f2SChinh Cao 144948cb27f2SChinh Cao return adv_link_speed; 145048cb27f2SChinh Cao } 145148cb27f2SChinh Cao 145248cb27f2SChinh Cao /** 145348cb27f2SChinh Cao * ice_setup_autoneg 145448cb27f2SChinh Cao * @p: port info 145548cb27f2SChinh Cao * @ks: ethtool_link_ksettings 145648cb27f2SChinh Cao * @config: configuration that will be sent down to FW 145748cb27f2SChinh Cao * @autoneg_enabled: autonegotiation is enabled or not 145848cb27f2SChinh Cao * @autoneg_changed: will there a change in autonegotiation 145948cb27f2SChinh Cao * @netdev: network interface device structure 146048cb27f2SChinh Cao * 146148cb27f2SChinh Cao * Setup PHY autonegotiation feature 146248cb27f2SChinh Cao */ 146348cb27f2SChinh Cao static int 146448cb27f2SChinh Cao ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks, 146548cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data *config, 146648cb27f2SChinh Cao u8 autoneg_enabled, u8 *autoneg_changed, 146748cb27f2SChinh Cao struct net_device *netdev) 146848cb27f2SChinh Cao { 146948cb27f2SChinh Cao int err = 0; 147048cb27f2SChinh Cao 147148cb27f2SChinh Cao *autoneg_changed = 0; 147248cb27f2SChinh Cao 147348cb27f2SChinh Cao /* Check autoneg */ 147448cb27f2SChinh Cao if (autoneg_enabled == AUTONEG_ENABLE) { 147548cb27f2SChinh Cao /* If autoneg was not already enabled */ 147648cb27f2SChinh Cao if (!(p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED)) { 147748cb27f2SChinh Cao /* If autoneg is not supported, return error */ 147848cb27f2SChinh Cao if (!ethtool_link_ksettings_test_link_mode(ks, 147948cb27f2SChinh Cao supported, 148048cb27f2SChinh Cao Autoneg)) { 148148cb27f2SChinh Cao netdev_info(netdev, "Autoneg not supported on this phy.\n"); 148248cb27f2SChinh Cao err = -EINVAL; 148348cb27f2SChinh Cao } else { 148448cb27f2SChinh Cao /* Autoneg is allowed to change */ 148548cb27f2SChinh Cao config->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 148648cb27f2SChinh Cao *autoneg_changed = 1; 148748cb27f2SChinh Cao } 148848cb27f2SChinh Cao } 148948cb27f2SChinh Cao } else { 149048cb27f2SChinh Cao /* If autoneg is currently enabled */ 149148cb27f2SChinh Cao if (p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED) { 1492f9867df6SAnirudh Venkataramanan /* If autoneg is supported 10GBASE_T is the only PHY 149348cb27f2SChinh Cao * that can disable it, so otherwise return error 149448cb27f2SChinh Cao */ 149548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, 149648cb27f2SChinh Cao supported, 149748cb27f2SChinh Cao Autoneg)) { 149848cb27f2SChinh Cao netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); 149948cb27f2SChinh Cao err = -EINVAL; 150048cb27f2SChinh Cao } else { 150148cb27f2SChinh Cao /* Autoneg is allowed to change */ 150248cb27f2SChinh Cao config->caps &= ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 150348cb27f2SChinh Cao *autoneg_changed = 1; 150448cb27f2SChinh Cao } 150548cb27f2SChinh Cao } 150648cb27f2SChinh Cao } 150748cb27f2SChinh Cao 150848cb27f2SChinh Cao return err; 150948cb27f2SChinh Cao } 151048cb27f2SChinh Cao 151148cb27f2SChinh Cao /** 151248cb27f2SChinh Cao * ice_set_link_ksettings - Set Speed and Duplex 151348cb27f2SChinh Cao * @netdev: network interface device structure 151448cb27f2SChinh Cao * @ks: ethtool ksettings 151548cb27f2SChinh Cao * 151648cb27f2SChinh Cao * Set speed/duplex per media_types advertised/forced 151748cb27f2SChinh Cao */ 1518aef74145SAnirudh Venkataramanan static int 1519aef74145SAnirudh Venkataramanan ice_set_link_ksettings(struct net_device *netdev, 152048cb27f2SChinh Cao const struct ethtool_link_ksettings *ks) 152148cb27f2SChinh Cao { 152248cb27f2SChinh Cao u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0; 152348cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 152448cb27f2SChinh Cao struct ethtool_link_ksettings safe_ks, copy_ks; 152548cb27f2SChinh Cao struct ice_aqc_get_phy_caps_data *abilities; 152648cb27f2SChinh Cao u16 adv_link_speed, curr_link_speed, idx; 152748cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data config; 152848cb27f2SChinh Cao struct ice_pf *pf = np->vsi->back; 152948cb27f2SChinh Cao struct ice_port_info *p; 153048cb27f2SChinh Cao u8 autoneg_changed = 0; 153148cb27f2SChinh Cao enum ice_status status; 1532aef74145SAnirudh Venkataramanan u64 phy_type_high; 153348cb27f2SChinh Cao u64 phy_type_low; 153448cb27f2SChinh Cao int err = 0; 153548cb27f2SChinh Cao bool linkup; 153648cb27f2SChinh Cao 153748cb27f2SChinh Cao p = np->vsi->port_info; 153848cb27f2SChinh Cao 153948cb27f2SChinh Cao if (!p) 154048cb27f2SChinh Cao return -EOPNOTSUPP; 154148cb27f2SChinh Cao 1542f9867df6SAnirudh Venkataramanan /* Check if this is LAN VSI */ 154380ed404aSBrett Creeley ice_for_each_vsi(pf, idx) 154448cb27f2SChinh Cao if (pf->vsi[idx]->type == ICE_VSI_PF) { 154548cb27f2SChinh Cao if (np->vsi != pf->vsi[idx]) 154648cb27f2SChinh Cao return -EOPNOTSUPP; 154748cb27f2SChinh Cao break; 154848cb27f2SChinh Cao } 154948cb27f2SChinh Cao 155048cb27f2SChinh Cao if (p->phy.media_type != ICE_MEDIA_BASET && 155148cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_FIBER && 155248cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_BACKPLANE && 155348cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_DA && 155448cb27f2SChinh Cao p->phy.link_info.link_info & ICE_AQ_LINK_UP) 155548cb27f2SChinh Cao return -EOPNOTSUPP; 155648cb27f2SChinh Cao 155748cb27f2SChinh Cao /* copy the ksettings to copy_ks to avoid modifying the original */ 1558c6dfd690SBruce Allan memcpy(©_ks, ks, sizeof(copy_ks)); 155948cb27f2SChinh Cao 156048cb27f2SChinh Cao /* save autoneg out of ksettings */ 156148cb27f2SChinh Cao autoneg = copy_ks.base.autoneg; 156248cb27f2SChinh Cao 156348cb27f2SChinh Cao memset(&safe_ks, 0, sizeof(safe_ks)); 156448cb27f2SChinh Cao 156548cb27f2SChinh Cao /* Get link modes supported by hardware.*/ 156648cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, &safe_ks); 156748cb27f2SChinh Cao 156848cb27f2SChinh Cao /* and check against modes requested by user. 156948cb27f2SChinh Cao * Return an error if unsupported mode was set. 157048cb27f2SChinh Cao */ 157148cb27f2SChinh Cao if (!bitmap_subset(copy_ks.link_modes.advertising, 157248cb27f2SChinh Cao safe_ks.link_modes.supported, 157348cb27f2SChinh Cao __ETHTOOL_LINK_MODE_MASK_NBITS)) 157448cb27f2SChinh Cao return -EINVAL; 157548cb27f2SChinh Cao 157648cb27f2SChinh Cao /* get our own copy of the bits to check against */ 1577c6dfd690SBruce Allan memset(&safe_ks, 0, sizeof(safe_ks)); 157848cb27f2SChinh Cao safe_ks.base.cmd = copy_ks.base.cmd; 157948cb27f2SChinh Cao safe_ks.base.link_mode_masks_nwords = 158048cb27f2SChinh Cao copy_ks.base.link_mode_masks_nwords; 158148cb27f2SChinh Cao ice_get_link_ksettings(netdev, &safe_ks); 158248cb27f2SChinh Cao 158348cb27f2SChinh Cao /* set autoneg back to what it currently is */ 158448cb27f2SChinh Cao copy_ks.base.autoneg = safe_ks.base.autoneg; 158548cb27f2SChinh Cao /* we don't compare the speed */ 158648cb27f2SChinh Cao copy_ks.base.speed = safe_ks.base.speed; 158748cb27f2SChinh Cao 158848cb27f2SChinh Cao /* If copy_ks.base and safe_ks.base are not the same now, then they are 158948cb27f2SChinh Cao * trying to set something that we do not support. 159048cb27f2SChinh Cao */ 1591c6dfd690SBruce Allan if (memcmp(©_ks.base, &safe_ks.base, sizeof(copy_ks.base))) 159248cb27f2SChinh Cao return -EOPNOTSUPP; 159348cb27f2SChinh Cao 159448cb27f2SChinh Cao while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 159548cb27f2SChinh Cao timeout--; 159648cb27f2SChinh Cao if (!timeout) 159748cb27f2SChinh Cao return -EBUSY; 159848cb27f2SChinh Cao usleep_range(TEST_SET_BITS_SLEEP_MIN, TEST_SET_BITS_SLEEP_MAX); 159948cb27f2SChinh Cao } 160048cb27f2SChinh Cao 160148cb27f2SChinh Cao abilities = devm_kzalloc(&pf->pdev->dev, sizeof(*abilities), 160248cb27f2SChinh Cao GFP_KERNEL); 160348cb27f2SChinh Cao if (!abilities) 160448cb27f2SChinh Cao return -ENOMEM; 160548cb27f2SChinh Cao 1606f9867df6SAnirudh Venkataramanan /* Get the current PHY config */ 160748cb27f2SChinh Cao status = ice_aq_get_phy_caps(p, false, ICE_AQC_REPORT_SW_CFG, abilities, 160848cb27f2SChinh Cao NULL); 160948cb27f2SChinh Cao if (status) { 161048cb27f2SChinh Cao err = -EAGAIN; 161148cb27f2SChinh Cao goto done; 161248cb27f2SChinh Cao } 161348cb27f2SChinh Cao 161448cb27f2SChinh Cao /* Copy abilities to config in case autoneg is not set below */ 1615c6dfd690SBruce Allan memset(&config, 0, sizeof(config)); 161648cb27f2SChinh Cao config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE; 161748cb27f2SChinh Cao if (abilities->caps & ICE_AQC_PHY_AN_MODE) 161848cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 161948cb27f2SChinh Cao 162048cb27f2SChinh Cao /* Check autoneg */ 162148cb27f2SChinh Cao err = ice_setup_autoneg(p, &safe_ks, &config, autoneg, &autoneg_changed, 162248cb27f2SChinh Cao netdev); 162348cb27f2SChinh Cao 162448cb27f2SChinh Cao if (err) 162548cb27f2SChinh Cao goto done; 162648cb27f2SChinh Cao 162748cb27f2SChinh Cao /* Call to get the current link speed */ 162848cb27f2SChinh Cao p->phy.get_link_info = true; 162948cb27f2SChinh Cao status = ice_get_link_status(p, &linkup); 163048cb27f2SChinh Cao if (status) { 163148cb27f2SChinh Cao err = -EAGAIN; 163248cb27f2SChinh Cao goto done; 163348cb27f2SChinh Cao } 163448cb27f2SChinh Cao 163548cb27f2SChinh Cao curr_link_speed = p->phy.link_info.link_speed; 163648cb27f2SChinh Cao adv_link_speed = ice_ksettings_find_adv_link_speed(ks); 163748cb27f2SChinh Cao 163848cb27f2SChinh Cao /* If speed didn't get set, set it to what it currently is. 163948cb27f2SChinh Cao * This is needed because if advertise is 0 (as it is when autoneg 164048cb27f2SChinh Cao * is disabled) then speed won't get set. 164148cb27f2SChinh Cao */ 164248cb27f2SChinh Cao if (!adv_link_speed) 164348cb27f2SChinh Cao adv_link_speed = curr_link_speed; 164448cb27f2SChinh Cao 164548cb27f2SChinh Cao /* Convert the advertise link speeds to their corresponded PHY_TYPE */ 1646aef74145SAnirudh Venkataramanan ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed); 164748cb27f2SChinh Cao 164848cb27f2SChinh Cao if (!autoneg_changed && adv_link_speed == curr_link_speed) { 164948cb27f2SChinh Cao netdev_info(netdev, "Nothing changed, exiting without setting anything.\n"); 165048cb27f2SChinh Cao goto done; 165148cb27f2SChinh Cao } 165248cb27f2SChinh Cao 165348cb27f2SChinh Cao /* copy over the rest of the abilities */ 165448cb27f2SChinh Cao config.low_power_ctrl = abilities->low_power_ctrl; 165548cb27f2SChinh Cao config.eee_cap = abilities->eee_cap; 165648cb27f2SChinh Cao config.eeer_value = abilities->eeer_value; 165748cb27f2SChinh Cao config.link_fec_opt = abilities->link_fec_options; 165848cb27f2SChinh Cao 165948cb27f2SChinh Cao /* save the requested speeds */ 166048cb27f2SChinh Cao p->phy.link_info.req_speeds = adv_link_speed; 166148cb27f2SChinh Cao 166248cb27f2SChinh Cao /* set link and auto negotiation so changes take effect */ 166348cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_LINK; 166448cb27f2SChinh Cao 1665aef74145SAnirudh Venkataramanan if (phy_type_low || phy_type_high) { 1666aef74145SAnirudh Venkataramanan config.phy_type_high = cpu_to_le64(phy_type_high) & 1667aef74145SAnirudh Venkataramanan abilities->phy_type_high; 166848cb27f2SChinh Cao config.phy_type_low = cpu_to_le64(phy_type_low) & 166948cb27f2SChinh Cao abilities->phy_type_low; 167048cb27f2SChinh Cao } else { 167148cb27f2SChinh Cao err = -EAGAIN; 167248cb27f2SChinh Cao netdev_info(netdev, "Nothing changed. No PHY_TYPE is corresponded to advertised link speed.\n"); 167348cb27f2SChinh Cao goto done; 167448cb27f2SChinh Cao } 167548cb27f2SChinh Cao 167648cb27f2SChinh Cao /* If link is up put link down */ 167748cb27f2SChinh Cao if (p->phy.link_info.link_info & ICE_AQ_LINK_UP) { 167848cb27f2SChinh Cao /* Tell the OS link is going down, the link will go 167948cb27f2SChinh Cao * back up when fw says it is ready asynchronously 168048cb27f2SChinh Cao */ 168148cb27f2SChinh Cao ice_print_link_msg(np->vsi, false); 168248cb27f2SChinh Cao netif_carrier_off(netdev); 168348cb27f2SChinh Cao netif_tx_stop_all_queues(netdev); 168448cb27f2SChinh Cao } 168548cb27f2SChinh Cao 168648cb27f2SChinh Cao /* make the aq call */ 168748cb27f2SChinh Cao status = ice_aq_set_phy_cfg(&pf->hw, lport, &config, NULL); 168848cb27f2SChinh Cao if (status) { 168948cb27f2SChinh Cao netdev_info(netdev, "Set phy config failed,\n"); 169048cb27f2SChinh Cao err = -EAGAIN; 169148cb27f2SChinh Cao } 169248cb27f2SChinh Cao 169348cb27f2SChinh Cao done: 169448cb27f2SChinh Cao devm_kfree(&pf->pdev->dev, abilities); 169548cb27f2SChinh Cao clear_bit(__ICE_CFG_BUSY, pf->state); 169648cb27f2SChinh Cao 169748cb27f2SChinh Cao return err; 169848cb27f2SChinh Cao } 169948cb27f2SChinh Cao 170048cb27f2SChinh Cao /** 1701f9867df6SAnirudh Venkataramanan * ice_get_rxnfc - command to get Rx flow classification rules 1702fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 1703fcea6f3dSAnirudh Venkataramanan * @cmd: ethtool rxnfc command 1704fcea6f3dSAnirudh Venkataramanan * @rule_locs: buffer to rturn Rx flow classification rules 1705fcea6f3dSAnirudh Venkataramanan * 1706fcea6f3dSAnirudh Venkataramanan * Returns Success if the command is supported. 1707fcea6f3dSAnirudh Venkataramanan */ 1708c8b7abddSBruce Allan static int 1709c8b7abddSBruce Allan ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, 1710fcea6f3dSAnirudh Venkataramanan u32 __always_unused *rule_locs) 1711fcea6f3dSAnirudh Venkataramanan { 1712fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1713fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1714fcea6f3dSAnirudh Venkataramanan int ret = -EOPNOTSUPP; 1715fcea6f3dSAnirudh Venkataramanan 1716fcea6f3dSAnirudh Venkataramanan switch (cmd->cmd) { 1717fcea6f3dSAnirudh Venkataramanan case ETHTOOL_GRXRINGS: 1718fcea6f3dSAnirudh Venkataramanan cmd->data = vsi->rss_size; 1719fcea6f3dSAnirudh Venkataramanan ret = 0; 1720fcea6f3dSAnirudh Venkataramanan break; 1721fcea6f3dSAnirudh Venkataramanan default: 1722fcea6f3dSAnirudh Venkataramanan break; 1723fcea6f3dSAnirudh Venkataramanan } 1724fcea6f3dSAnirudh Venkataramanan 1725fcea6f3dSAnirudh Venkataramanan return ret; 1726fcea6f3dSAnirudh Venkataramanan } 1727fcea6f3dSAnirudh Venkataramanan 1728fcea6f3dSAnirudh Venkataramanan static void 1729fcea6f3dSAnirudh Venkataramanan ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 1730fcea6f3dSAnirudh Venkataramanan { 1731fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1732fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1733fcea6f3dSAnirudh Venkataramanan 1734fcea6f3dSAnirudh Venkataramanan ring->rx_max_pending = ICE_MAX_NUM_DESC; 1735fcea6f3dSAnirudh Venkataramanan ring->tx_max_pending = ICE_MAX_NUM_DESC; 1736fcea6f3dSAnirudh Venkataramanan ring->rx_pending = vsi->rx_rings[0]->count; 1737fcea6f3dSAnirudh Venkataramanan ring->tx_pending = vsi->tx_rings[0]->count; 1738f934bb9bSBruce Allan 1739f934bb9bSBruce Allan /* Rx mini and jumbo rings are not supported */ 1740fcea6f3dSAnirudh Venkataramanan ring->rx_mini_max_pending = 0; 1741fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_max_pending = 0; 1742f934bb9bSBruce Allan ring->rx_mini_pending = 0; 1743fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_pending = 0; 1744fcea6f3dSAnirudh Venkataramanan } 1745fcea6f3dSAnirudh Venkataramanan 1746fcea6f3dSAnirudh Venkataramanan static int 1747fcea6f3dSAnirudh Venkataramanan ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 1748fcea6f3dSAnirudh Venkataramanan { 1749fcea6f3dSAnirudh Venkataramanan struct ice_ring *tx_rings = NULL, *rx_rings = NULL; 1750fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1751fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1752fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1753fcea6f3dSAnirudh Venkataramanan int i, timeout = 50, err = 0; 1754fcea6f3dSAnirudh Venkataramanan u32 new_rx_cnt, new_tx_cnt; 1755fcea6f3dSAnirudh Venkataramanan 1756fcea6f3dSAnirudh Venkataramanan if (ring->tx_pending > ICE_MAX_NUM_DESC || 1757fcea6f3dSAnirudh Venkataramanan ring->tx_pending < ICE_MIN_NUM_DESC || 1758fcea6f3dSAnirudh Venkataramanan ring->rx_pending > ICE_MAX_NUM_DESC || 1759fcea6f3dSAnirudh Venkataramanan ring->rx_pending < ICE_MIN_NUM_DESC) { 1760f934bb9bSBruce Allan netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", 1761fcea6f3dSAnirudh Venkataramanan ring->tx_pending, ring->rx_pending, 1762f934bb9bSBruce Allan ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC, 1763f934bb9bSBruce Allan ICE_REQ_DESC_MULTIPLE); 1764fcea6f3dSAnirudh Venkataramanan return -EINVAL; 1765fcea6f3dSAnirudh Venkataramanan } 1766fcea6f3dSAnirudh Venkataramanan 1767fcea6f3dSAnirudh Venkataramanan new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE); 1768f934bb9bSBruce Allan if (new_tx_cnt != ring->tx_pending) 1769f934bb9bSBruce Allan netdev_info(netdev, 1770f934bb9bSBruce Allan "Requested Tx descriptor count rounded up to %d\n", 1771f934bb9bSBruce Allan new_tx_cnt); 1772fcea6f3dSAnirudh Venkataramanan new_rx_cnt = ALIGN(ring->rx_pending, ICE_REQ_DESC_MULTIPLE); 1773f934bb9bSBruce Allan if (new_rx_cnt != ring->rx_pending) 1774f934bb9bSBruce Allan netdev_info(netdev, 1775f934bb9bSBruce Allan "Requested Rx descriptor count rounded up to %d\n", 1776f934bb9bSBruce Allan new_rx_cnt); 1777fcea6f3dSAnirudh Venkataramanan 1778fcea6f3dSAnirudh Venkataramanan /* if nothing to do return success */ 1779fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count && 1780fcea6f3dSAnirudh Venkataramanan new_rx_cnt == vsi->rx_rings[0]->count) { 1781fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); 1782fcea6f3dSAnirudh Venkataramanan return 0; 1783fcea6f3dSAnirudh Venkataramanan } 1784fcea6f3dSAnirudh Venkataramanan 1785fcea6f3dSAnirudh Venkataramanan while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 1786fcea6f3dSAnirudh Venkataramanan timeout--; 1787fcea6f3dSAnirudh Venkataramanan if (!timeout) 1788fcea6f3dSAnirudh Venkataramanan return -EBUSY; 1789fcea6f3dSAnirudh Venkataramanan usleep_range(1000, 2000); 1790fcea6f3dSAnirudh Venkataramanan } 1791fcea6f3dSAnirudh Venkataramanan 1792fcea6f3dSAnirudh Venkataramanan /* set for the next time the netdev is started */ 1793fcea6f3dSAnirudh Venkataramanan if (!netif_running(vsi->netdev)) { 1794fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) 1795fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[i]->count = new_tx_cnt; 1796fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) 1797fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[i]->count = new_rx_cnt; 1798fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Link is down, descriptor count change happens when link is brought up\n"); 1799fcea6f3dSAnirudh Venkataramanan goto done; 1800fcea6f3dSAnirudh Venkataramanan } 1801fcea6f3dSAnirudh Venkataramanan 1802fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count) 1803fcea6f3dSAnirudh Venkataramanan goto process_rx; 1804fcea6f3dSAnirudh Venkataramanan 1805fcea6f3dSAnirudh Venkataramanan /* alloc updated Tx resources */ 1806fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Tx descriptor count from %d to %d\n", 1807fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[0]->count, new_tx_cnt); 1808fcea6f3dSAnirudh Venkataramanan 1809fcea6f3dSAnirudh Venkataramanan tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 1810c6dfd690SBruce Allan sizeof(*tx_rings), GFP_KERNEL); 1811fcea6f3dSAnirudh Venkataramanan if (!tx_rings) { 1812fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 1813fcea6f3dSAnirudh Venkataramanan goto done; 1814fcea6f3dSAnirudh Venkataramanan } 1815fcea6f3dSAnirudh Venkataramanan 1816f8ba7db8SJacob Keller for (i = 0; i < vsi->alloc_txq; i++) { 1817fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 1818fcea6f3dSAnirudh Venkataramanan tx_rings[i] = *vsi->tx_rings[i]; 1819fcea6f3dSAnirudh Venkataramanan tx_rings[i].count = new_tx_cnt; 1820fcea6f3dSAnirudh Venkataramanan tx_rings[i].desc = NULL; 1821fcea6f3dSAnirudh Venkataramanan tx_rings[i].tx_buf = NULL; 1822fcea6f3dSAnirudh Venkataramanan err = ice_setup_tx_ring(&tx_rings[i]); 1823fcea6f3dSAnirudh Venkataramanan if (err) { 1824fcea6f3dSAnirudh Venkataramanan while (i) { 1825fcea6f3dSAnirudh Venkataramanan i--; 1826fcea6f3dSAnirudh Venkataramanan ice_clean_tx_ring(&tx_rings[i]); 1827fcea6f3dSAnirudh Venkataramanan } 1828fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 1829fcea6f3dSAnirudh Venkataramanan goto done; 1830fcea6f3dSAnirudh Venkataramanan } 1831fcea6f3dSAnirudh Venkataramanan } 1832fcea6f3dSAnirudh Venkataramanan 1833fcea6f3dSAnirudh Venkataramanan process_rx: 1834fcea6f3dSAnirudh Venkataramanan if (new_rx_cnt == vsi->rx_rings[0]->count) 1835fcea6f3dSAnirudh Venkataramanan goto process_link; 1836fcea6f3dSAnirudh Venkataramanan 1837fcea6f3dSAnirudh Venkataramanan /* alloc updated Rx resources */ 1838fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Rx descriptor count from %d to %d\n", 1839fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[0]->count, new_rx_cnt); 1840fcea6f3dSAnirudh Venkataramanan 1841fcea6f3dSAnirudh Venkataramanan rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 1842c6dfd690SBruce Allan sizeof(*rx_rings), GFP_KERNEL); 1843fcea6f3dSAnirudh Venkataramanan if (!rx_rings) { 1844fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 1845fcea6f3dSAnirudh Venkataramanan goto done; 1846fcea6f3dSAnirudh Venkataramanan } 1847fcea6f3dSAnirudh Venkataramanan 1848f8ba7db8SJacob Keller for (i = 0; i < vsi->alloc_rxq; i++) { 1849fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 1850fcea6f3dSAnirudh Venkataramanan rx_rings[i] = *vsi->rx_rings[i]; 1851fcea6f3dSAnirudh Venkataramanan rx_rings[i].count = new_rx_cnt; 1852fcea6f3dSAnirudh Venkataramanan rx_rings[i].desc = NULL; 1853fcea6f3dSAnirudh Venkataramanan rx_rings[i].rx_buf = NULL; 1854fcea6f3dSAnirudh Venkataramanan /* this is to allow wr32 to have something to write to 1855fcea6f3dSAnirudh Venkataramanan * during early allocation of Rx buffers 1856fcea6f3dSAnirudh Venkataramanan */ 1857fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->back->hw.hw_addr + PRTGEN_STATUS; 1858fcea6f3dSAnirudh Venkataramanan 1859fcea6f3dSAnirudh Venkataramanan err = ice_setup_rx_ring(&rx_rings[i]); 1860fcea6f3dSAnirudh Venkataramanan if (err) 1861fcea6f3dSAnirudh Venkataramanan goto rx_unwind; 1862fcea6f3dSAnirudh Venkataramanan 1863fcea6f3dSAnirudh Venkataramanan /* allocate Rx buffers */ 1864fcea6f3dSAnirudh Venkataramanan err = ice_alloc_rx_bufs(&rx_rings[i], 1865fcea6f3dSAnirudh Venkataramanan ICE_DESC_UNUSED(&rx_rings[i])); 1866fcea6f3dSAnirudh Venkataramanan rx_unwind: 1867fcea6f3dSAnirudh Venkataramanan if (err) { 1868fcea6f3dSAnirudh Venkataramanan while (i) { 1869fcea6f3dSAnirudh Venkataramanan i--; 1870fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(&rx_rings[i]); 1871fcea6f3dSAnirudh Venkataramanan } 1872fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, rx_rings); 1873fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 1874fcea6f3dSAnirudh Venkataramanan goto free_tx; 1875fcea6f3dSAnirudh Venkataramanan } 1876fcea6f3dSAnirudh Venkataramanan } 1877fcea6f3dSAnirudh Venkataramanan 1878fcea6f3dSAnirudh Venkataramanan process_link: 1879fcea6f3dSAnirudh Venkataramanan /* Bring interface down, copy in the new ring info, then restore the 1880fcea6f3dSAnirudh Venkataramanan * interface. if VSI is up, bring it down and then back up 1881fcea6f3dSAnirudh Venkataramanan */ 1882fcea6f3dSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) { 1883fcea6f3dSAnirudh Venkataramanan ice_down(vsi); 1884fcea6f3dSAnirudh Venkataramanan 1885fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 1886fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 1887fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 1888fcea6f3dSAnirudh Venkataramanan *vsi->tx_rings[i] = tx_rings[i]; 1889fcea6f3dSAnirudh Venkataramanan } 1890fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 1891fcea6f3dSAnirudh Venkataramanan } 1892fcea6f3dSAnirudh Venkataramanan 1893fcea6f3dSAnirudh Venkataramanan if (rx_rings) { 1894fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 1895fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 1896fcea6f3dSAnirudh Venkataramanan /* copy the real tail offset */ 1897fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->rx_rings[i]->tail; 1898fcea6f3dSAnirudh Venkataramanan /* this is to fake out the allocation routine 1899fcea6f3dSAnirudh Venkataramanan * into thinking it has to realloc everything 1900fcea6f3dSAnirudh Venkataramanan * but the recycling logic will let us re-use 1901fcea6f3dSAnirudh Venkataramanan * the buffers allocated above 1902fcea6f3dSAnirudh Venkataramanan */ 1903fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_use = 0; 1904fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_clean = 0; 1905fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_alloc = 0; 1906fcea6f3dSAnirudh Venkataramanan *vsi->rx_rings[i] = rx_rings[i]; 1907fcea6f3dSAnirudh Venkataramanan } 1908fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, rx_rings); 1909fcea6f3dSAnirudh Venkataramanan } 1910fcea6f3dSAnirudh Venkataramanan 1911fcea6f3dSAnirudh Venkataramanan ice_up(vsi); 1912fcea6f3dSAnirudh Venkataramanan } 1913fcea6f3dSAnirudh Venkataramanan goto done; 1914fcea6f3dSAnirudh Venkataramanan 1915fcea6f3dSAnirudh Venkataramanan free_tx: 1916fcea6f3dSAnirudh Venkataramanan /* error cleanup if the Rx allocations failed after getting Tx */ 1917fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 1918fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) 1919fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(&tx_rings[i]); 1920fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 1921fcea6f3dSAnirudh Venkataramanan } 1922fcea6f3dSAnirudh Venkataramanan 1923fcea6f3dSAnirudh Venkataramanan done: 1924fcea6f3dSAnirudh Venkataramanan clear_bit(__ICE_CFG_BUSY, pf->state); 1925fcea6f3dSAnirudh Venkataramanan return err; 1926fcea6f3dSAnirudh Venkataramanan } 1927fcea6f3dSAnirudh Venkataramanan 1928fcea6f3dSAnirudh Venkataramanan static int ice_nway_reset(struct net_device *netdev) 1929fcea6f3dSAnirudh Venkataramanan { 1930fcea6f3dSAnirudh Venkataramanan /* restart autonegotiation */ 1931fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1932fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1933fcea6f3dSAnirudh Venkataramanan struct ice_port_info *pi; 1934fcea6f3dSAnirudh Venkataramanan enum ice_status status; 1935fcea6f3dSAnirudh Venkataramanan 1936fcea6f3dSAnirudh Venkataramanan pi = vsi->port_info; 1937d38b0883SAkeem G Abodunrin /* If VSI state is up, then restart autoneg with link up */ 1938d38b0883SAkeem G Abodunrin if (!test_bit(__ICE_DOWN, vsi->back->state)) 1939d38b0883SAkeem G Abodunrin status = ice_aq_set_link_restart_an(pi, true, NULL); 1940d38b0883SAkeem G Abodunrin else 1941d38b0883SAkeem G Abodunrin status = ice_aq_set_link_restart_an(pi, false, NULL); 1942fcea6f3dSAnirudh Venkataramanan 1943fcea6f3dSAnirudh Venkataramanan if (status) { 1944fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "link restart failed, err %d aq_err %d\n", 1945fcea6f3dSAnirudh Venkataramanan status, pi->hw->adminq.sq_last_status); 1946fcea6f3dSAnirudh Venkataramanan return -EIO; 1947fcea6f3dSAnirudh Venkataramanan } 1948fcea6f3dSAnirudh Venkataramanan 1949fcea6f3dSAnirudh Venkataramanan return 0; 1950fcea6f3dSAnirudh Venkataramanan } 1951fcea6f3dSAnirudh Venkataramanan 1952fcea6f3dSAnirudh Venkataramanan /** 1953fcea6f3dSAnirudh Venkataramanan * ice_get_pauseparam - Get Flow Control status 1954fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 1955fcea6f3dSAnirudh Venkataramanan * @pause: ethernet pause (flow control) parameters 1956fcea6f3dSAnirudh Venkataramanan */ 1957fcea6f3dSAnirudh Venkataramanan static void 1958fcea6f3dSAnirudh Venkataramanan ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 1959fcea6f3dSAnirudh Venkataramanan { 1960fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 196140c3c546SLukasz Czapnik struct ice_port_info *pi = np->vsi->port_info; 196240c3c546SLukasz Czapnik struct ice_aqc_get_phy_caps_data *pcaps; 196340c3c546SLukasz Czapnik struct ice_vsi *vsi = np->vsi; 19643a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 196540c3c546SLukasz Czapnik enum ice_status status; 1966fcea6f3dSAnirudh Venkataramanan 196740c3c546SLukasz Czapnik /* Initialize pause params */ 196840c3c546SLukasz Czapnik pause->rx_pause = 0; 196940c3c546SLukasz Czapnik pause->tx_pause = 0; 197040c3c546SLukasz Czapnik 19713a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 19723a257a14SAnirudh Venkataramanan 197340c3c546SLukasz Czapnik pcaps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*pcaps), 197440c3c546SLukasz Czapnik GFP_KERNEL); 197540c3c546SLukasz Czapnik if (!pcaps) 197640c3c546SLukasz Czapnik return; 197740c3c546SLukasz Czapnik 1978f9867df6SAnirudh Venkataramanan /* Get current PHY config */ 197940c3c546SLukasz Czapnik status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, 198040c3c546SLukasz Czapnik NULL); 198140c3c546SLukasz Czapnik if (status) 198240c3c546SLukasz Czapnik goto out; 198340c3c546SLukasz Czapnik 198440c3c546SLukasz Czapnik pause->autoneg = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ? 1985fcea6f3dSAnirudh Venkataramanan AUTONEG_ENABLE : AUTONEG_DISABLE); 1986fcea6f3dSAnirudh Venkataramanan 19873a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) 19883a257a14SAnirudh Venkataramanan /* PFC enabled so report LFC as off */ 19893a257a14SAnirudh Venkataramanan goto out; 19903a257a14SAnirudh Venkataramanan 199140c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) 1992fcea6f3dSAnirudh Venkataramanan pause->tx_pause = 1; 199340c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 1994fcea6f3dSAnirudh Venkataramanan pause->rx_pause = 1; 199540c3c546SLukasz Czapnik 199640c3c546SLukasz Czapnik out: 199740c3c546SLukasz Czapnik devm_kfree(&vsi->back->pdev->dev, pcaps); 1998fcea6f3dSAnirudh Venkataramanan } 1999fcea6f3dSAnirudh Venkataramanan 2000fcea6f3dSAnirudh Venkataramanan /** 2001fcea6f3dSAnirudh Venkataramanan * ice_set_pauseparam - Set Flow Control parameter 2002fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2003d337f2afSAnirudh Venkataramanan * @pause: return Tx/Rx flow control status 2004fcea6f3dSAnirudh Venkataramanan */ 2005fcea6f3dSAnirudh Venkataramanan static int 2006fcea6f3dSAnirudh Venkataramanan ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 2007fcea6f3dSAnirudh Venkataramanan { 2008fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2009fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 2010fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 20113a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 2012fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2013fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2014fcea6f3dSAnirudh Venkataramanan struct ice_port_info *pi; 2015fcea6f3dSAnirudh Venkataramanan enum ice_status status; 2016fcea6f3dSAnirudh Venkataramanan u8 aq_failures; 2017fcea6f3dSAnirudh Venkataramanan bool link_up; 2018fcea6f3dSAnirudh Venkataramanan int err = 0; 2019fcea6f3dSAnirudh Venkataramanan 2020fcea6f3dSAnirudh Venkataramanan pi = vsi->port_info; 2021fcea6f3dSAnirudh Venkataramanan hw_link_info = &pi->phy.link_info; 20223a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 2023fcea6f3dSAnirudh Venkataramanan link_up = hw_link_info->link_info & ICE_AQ_LINK_UP; 2024fcea6f3dSAnirudh Venkataramanan 2025fcea6f3dSAnirudh Venkataramanan /* Changing the port's flow control is not supported if this isn't the 2026fcea6f3dSAnirudh Venkataramanan * PF VSI 2027fcea6f3dSAnirudh Venkataramanan */ 2028fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) { 2029fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing flow control parameters only supported for PF VSI\n"); 2030fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2031fcea6f3dSAnirudh Venkataramanan } 2032fcea6f3dSAnirudh Venkataramanan 2033fcea6f3dSAnirudh Venkataramanan if (pause->autoneg != (hw_link_info->an_info & ICE_AQ_AN_COMPLETED)) { 2034fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n"); 2035fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2036fcea6f3dSAnirudh Venkataramanan } 2037fcea6f3dSAnirudh Venkataramanan 2038fcea6f3dSAnirudh Venkataramanan /* If we have link and don't have autoneg */ 2039fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state) && 2040fcea6f3dSAnirudh Venkataramanan !(hw_link_info->an_info & ICE_AQ_AN_COMPLETED)) { 2041fcea6f3dSAnirudh Venkataramanan /* Send message that it might not necessarily work*/ 2042fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n"); 2043fcea6f3dSAnirudh Venkataramanan } 2044fcea6f3dSAnirudh Venkataramanan 20453a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) { 20463a257a14SAnirudh Venkataramanan netdev_info(netdev, "Priority flow control enabled. Cannot set link flow control.\n"); 20473a257a14SAnirudh Venkataramanan return -EOPNOTSUPP; 20483a257a14SAnirudh Venkataramanan } 2049fcea6f3dSAnirudh Venkataramanan if (pause->rx_pause && pause->tx_pause) 2050fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_FULL; 2051fcea6f3dSAnirudh Venkataramanan else if (pause->rx_pause && !pause->tx_pause) 2052fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_RX_PAUSE; 2053fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && pause->tx_pause) 2054fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_TX_PAUSE; 2055fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && !pause->tx_pause) 2056fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_NONE; 2057fcea6f3dSAnirudh Venkataramanan else 2058fcea6f3dSAnirudh Venkataramanan return -EINVAL; 2059fcea6f3dSAnirudh Venkataramanan 2060fcea6f3dSAnirudh Venkataramanan /* Tell the OS link is going down, the link will go back up when fw 2061fcea6f3dSAnirudh Venkataramanan * says it is ready asynchronously 2062fcea6f3dSAnirudh Venkataramanan */ 2063fcea6f3dSAnirudh Venkataramanan ice_print_link_msg(vsi, false); 2064fcea6f3dSAnirudh Venkataramanan netif_carrier_off(netdev); 2065fcea6f3dSAnirudh Venkataramanan netif_tx_stop_all_queues(netdev); 2066fcea6f3dSAnirudh Venkataramanan 2067fcea6f3dSAnirudh Venkataramanan /* Set the FC mode and only restart AN if link is up */ 2068fcea6f3dSAnirudh Venkataramanan status = ice_set_fc(pi, &aq_failures, link_up); 2069fcea6f3dSAnirudh Venkataramanan 2070fcea6f3dSAnirudh Venkataramanan if (aq_failures & ICE_SET_FC_AQ_FAIL_GET) { 2071fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the get_phy_capabilities call with err %d aq_err %d\n", 2072fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2073fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2074fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_SET) { 2075fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the set_phy_config call with err %d aq_err %d\n", 2076fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2077fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2078fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_UPDATE) { 2079fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the get_link_info call with err %d aq_err %d\n", 2080fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2081fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2082fcea6f3dSAnirudh Venkataramanan } 2083fcea6f3dSAnirudh Venkataramanan 2084fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) { 20850f5d4c21SAkeem G Abodunrin /* Give it a little more time to try to come back. If still 20860f5d4c21SAkeem G Abodunrin * down, restart autoneg link or reinitialize the interface. 20870f5d4c21SAkeem G Abodunrin */ 2088fcea6f3dSAnirudh Venkataramanan msleep(75); 2089fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) 2090fcea6f3dSAnirudh Venkataramanan return ice_nway_reset(netdev); 20910f5d4c21SAkeem G Abodunrin 20920f5d4c21SAkeem G Abodunrin ice_down(vsi); 20930f5d4c21SAkeem G Abodunrin ice_up(vsi); 2094fcea6f3dSAnirudh Venkataramanan } 2095fcea6f3dSAnirudh Venkataramanan 2096fcea6f3dSAnirudh Venkataramanan return err; 2097fcea6f3dSAnirudh Venkataramanan } 2098fcea6f3dSAnirudh Venkataramanan 2099fcea6f3dSAnirudh Venkataramanan /** 2100fcea6f3dSAnirudh Venkataramanan * ice_get_rxfh_key_size - get the RSS hash key size 2101fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2102fcea6f3dSAnirudh Venkataramanan * 2103fcea6f3dSAnirudh Venkataramanan * Returns the table size. 2104fcea6f3dSAnirudh Venkataramanan */ 2105fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_key_size(struct net_device __always_unused *netdev) 2106fcea6f3dSAnirudh Venkataramanan { 2107fcea6f3dSAnirudh Venkataramanan return ICE_VSIQF_HKEY_ARRAY_SIZE; 2108fcea6f3dSAnirudh Venkataramanan } 2109fcea6f3dSAnirudh Venkataramanan 2110fcea6f3dSAnirudh Venkataramanan /** 2111d337f2afSAnirudh Venkataramanan * ice_get_rxfh_indir_size - get the Rx flow hash indirection table size 2112fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2113fcea6f3dSAnirudh Venkataramanan * 2114fcea6f3dSAnirudh Venkataramanan * Returns the table size. 2115fcea6f3dSAnirudh Venkataramanan */ 2116fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_indir_size(struct net_device *netdev) 2117fcea6f3dSAnirudh Venkataramanan { 2118fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2119fcea6f3dSAnirudh Venkataramanan 2120fcea6f3dSAnirudh Venkataramanan return np->vsi->rss_table_size; 2121fcea6f3dSAnirudh Venkataramanan } 2122fcea6f3dSAnirudh Venkataramanan 2123fcea6f3dSAnirudh Venkataramanan /** 2124d337f2afSAnirudh Venkataramanan * ice_get_rxfh - get the Rx flow hash indirection table 2125fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2126fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 2127fcea6f3dSAnirudh Venkataramanan * @key: hash key 2128fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 2129fcea6f3dSAnirudh Venkataramanan * 2130fcea6f3dSAnirudh Venkataramanan * Reads the indirection table directly from the hardware. 2131fcea6f3dSAnirudh Venkataramanan */ 2132fcea6f3dSAnirudh Venkataramanan static int 2133fcea6f3dSAnirudh Venkataramanan ice_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) 2134fcea6f3dSAnirudh Venkataramanan { 2135fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2136fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2137fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2138fcea6f3dSAnirudh Venkataramanan int ret = 0, i; 2139fcea6f3dSAnirudh Venkataramanan u8 *lut; 2140fcea6f3dSAnirudh Venkataramanan 2141fcea6f3dSAnirudh Venkataramanan if (hfunc) 2142fcea6f3dSAnirudh Venkataramanan *hfunc = ETH_RSS_HASH_TOP; 2143fcea6f3dSAnirudh Venkataramanan 2144fcea6f3dSAnirudh Venkataramanan if (!indir) 2145fcea6f3dSAnirudh Venkataramanan return 0; 2146fcea6f3dSAnirudh Venkataramanan 2147fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 2148fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 2149fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 2150fcea6f3dSAnirudh Venkataramanan return -EIO; 2151fcea6f3dSAnirudh Venkataramanan } 2152fcea6f3dSAnirudh Venkataramanan 2153fcea6f3dSAnirudh Venkataramanan lut = devm_kzalloc(&pf->pdev->dev, vsi->rss_table_size, GFP_KERNEL); 2154fcea6f3dSAnirudh Venkataramanan if (!lut) 2155fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 2156fcea6f3dSAnirudh Venkataramanan 2157fcea6f3dSAnirudh Venkataramanan if (ice_get_rss(vsi, key, lut, vsi->rss_table_size)) { 2158fcea6f3dSAnirudh Venkataramanan ret = -EIO; 2159fcea6f3dSAnirudh Venkataramanan goto out; 2160fcea6f3dSAnirudh Venkataramanan } 2161fcea6f3dSAnirudh Venkataramanan 2162fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 2163fcea6f3dSAnirudh Venkataramanan indir[i] = (u32)(lut[i]); 2164fcea6f3dSAnirudh Venkataramanan 2165fcea6f3dSAnirudh Venkataramanan out: 2166fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, lut); 2167fcea6f3dSAnirudh Venkataramanan return ret; 2168fcea6f3dSAnirudh Venkataramanan } 2169fcea6f3dSAnirudh Venkataramanan 2170fcea6f3dSAnirudh Venkataramanan /** 2171d337f2afSAnirudh Venkataramanan * ice_set_rxfh - set the Rx flow hash indirection table 2172fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2173fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 2174fcea6f3dSAnirudh Venkataramanan * @key: hash key 2175fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 2176fcea6f3dSAnirudh Venkataramanan * 2177f9867df6SAnirudh Venkataramanan * Returns -EINVAL if the table specifies an invalid queue ID, otherwise 2178fcea6f3dSAnirudh Venkataramanan * returns 0 after programming the table. 2179fcea6f3dSAnirudh Venkataramanan */ 2180c8b7abddSBruce Allan static int 2181c8b7abddSBruce Allan ice_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, 2182c8b7abddSBruce Allan const u8 hfunc) 2183fcea6f3dSAnirudh Venkataramanan { 2184fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2185fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2186fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2187fcea6f3dSAnirudh Venkataramanan u8 *seed = NULL; 2188fcea6f3dSAnirudh Venkataramanan 2189fcea6f3dSAnirudh Venkataramanan if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 2190fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2191fcea6f3dSAnirudh Venkataramanan 2192fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 2193fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 2194fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 2195fcea6f3dSAnirudh Venkataramanan return -EIO; 2196fcea6f3dSAnirudh Venkataramanan } 2197fcea6f3dSAnirudh Venkataramanan 2198fcea6f3dSAnirudh Venkataramanan if (key) { 2199fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) { 2200fcea6f3dSAnirudh Venkataramanan vsi->rss_hkey_user = 2201fcea6f3dSAnirudh Venkataramanan devm_kzalloc(&pf->pdev->dev, 2202fcea6f3dSAnirudh Venkataramanan ICE_VSIQF_HKEY_ARRAY_SIZE, 2203fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 2204fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) 2205fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 2206fcea6f3dSAnirudh Venkataramanan } 2207fcea6f3dSAnirudh Venkataramanan memcpy(vsi->rss_hkey_user, key, ICE_VSIQF_HKEY_ARRAY_SIZE); 2208fcea6f3dSAnirudh Venkataramanan seed = vsi->rss_hkey_user; 2209fcea6f3dSAnirudh Venkataramanan } 2210fcea6f3dSAnirudh Venkataramanan 2211fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) { 2212fcea6f3dSAnirudh Venkataramanan vsi->rss_lut_user = devm_kzalloc(&pf->pdev->dev, 2213fcea6f3dSAnirudh Venkataramanan vsi->rss_table_size, 2214fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 2215fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) 2216fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 2217fcea6f3dSAnirudh Venkataramanan } 2218fcea6f3dSAnirudh Venkataramanan 2219fcea6f3dSAnirudh Venkataramanan /* Each 32 bits pointed by 'indir' is stored with a lut entry */ 2220fcea6f3dSAnirudh Venkataramanan if (indir) { 2221fcea6f3dSAnirudh Venkataramanan int i; 2222fcea6f3dSAnirudh Venkataramanan 2223fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 2224fcea6f3dSAnirudh Venkataramanan vsi->rss_lut_user[i] = (u8)(indir[i]); 2225fcea6f3dSAnirudh Venkataramanan } else { 2226fcea6f3dSAnirudh Venkataramanan ice_fill_rss_lut(vsi->rss_lut_user, vsi->rss_table_size, 2227fcea6f3dSAnirudh Venkataramanan vsi->rss_size); 2228fcea6f3dSAnirudh Venkataramanan } 2229fcea6f3dSAnirudh Venkataramanan 2230fcea6f3dSAnirudh Venkataramanan if (ice_set_rss(vsi, seed, vsi->rss_lut_user, vsi->rss_table_size)) 2231fcea6f3dSAnirudh Venkataramanan return -EIO; 2232fcea6f3dSAnirudh Venkataramanan 2233fcea6f3dSAnirudh Venkataramanan return 0; 2234fcea6f3dSAnirudh Venkataramanan } 2235fcea6f3dSAnirudh Venkataramanan 223667fe64d7SBrett Creeley enum ice_container_type { 223767fe64d7SBrett Creeley ICE_RX_CONTAINER, 223867fe64d7SBrett Creeley ICE_TX_CONTAINER, 223967fe64d7SBrett Creeley }; 224067fe64d7SBrett Creeley 224167fe64d7SBrett Creeley /** 224267fe64d7SBrett Creeley * ice_get_rc_coalesce - get ITR values for specific ring container 224367fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 2244f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 224567fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 224667fe64d7SBrett Creeley * 224767fe64d7SBrett Creeley * Query the device for ice_ring_container specific ITR values. This is 224867fe64d7SBrett Creeley * done per ice_ring_container because each q_vector can have 1 or more rings 224967fe64d7SBrett Creeley * and all of said ring(s) will have the same ITR values. 225067fe64d7SBrett Creeley * 225167fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 225267fe64d7SBrett Creeley */ 225367fe64d7SBrett Creeley static int 225467fe64d7SBrett Creeley ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, 225567fe64d7SBrett Creeley struct ice_ring_container *rc) 225667fe64d7SBrett Creeley { 2257b9c8bb06SBrett Creeley struct ice_pf *pf; 2258b9c8bb06SBrett Creeley 2259b9c8bb06SBrett Creeley if (!rc->ring) 2260b9c8bb06SBrett Creeley return -EINVAL; 2261b9c8bb06SBrett Creeley 2262b9c8bb06SBrett Creeley pf = rc->ring->vsi->back; 226367fe64d7SBrett Creeley 226467fe64d7SBrett Creeley switch (c_type) { 226567fe64d7SBrett Creeley case ICE_RX_CONTAINER: 226667fe64d7SBrett Creeley ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 226767fe64d7SBrett Creeley ec->rx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 2268b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high = rc->ring->q_vector->intrl; 226967fe64d7SBrett Creeley break; 227067fe64d7SBrett Creeley case ICE_TX_CONTAINER: 227167fe64d7SBrett Creeley ec->use_adaptive_tx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 227267fe64d7SBrett Creeley ec->tx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 227367fe64d7SBrett Creeley break; 227467fe64d7SBrett Creeley default: 227567fe64d7SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid c_type %d\n", c_type); 227667fe64d7SBrett Creeley return -EINVAL; 227767fe64d7SBrett Creeley } 227867fe64d7SBrett Creeley 227967fe64d7SBrett Creeley return 0; 228067fe64d7SBrett Creeley } 228167fe64d7SBrett Creeley 228267fe64d7SBrett Creeley /** 2283e40c899aSBrett Creeley * ice_get_q_coalesce - get a queue's ITR/INTRL (coalesce) settings 2284e40c899aSBrett Creeley * @vsi: VSI associated to the queue for getting ITR/INTRL (coalesce) settings 2285e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 2286e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 2287e40c899aSBrett Creeley * 2288e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 2289e40c899aSBrett Creeley * 1. Getting Tx or Rx ITR/INTRL (coalesce) settings failed. 2290e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 2291e40c899aSBrett Creeley */ 2292e40c899aSBrett Creeley static int 2293e40c899aSBrett Creeley ice_get_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 2294e40c899aSBrett Creeley { 2295e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 2296e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2297e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 2298e40c899aSBrett Creeley return -EINVAL; 2299e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2300e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 2301e40c899aSBrett Creeley return -EINVAL; 2302e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 2303e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2304e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 2305e40c899aSBrett Creeley return -EINVAL; 2306e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 2307e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2308e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 2309e40c899aSBrett Creeley return -EINVAL; 2310e40c899aSBrett Creeley } else { 2311e40c899aSBrett Creeley return -EINVAL; 2312e40c899aSBrett Creeley } 2313e40c899aSBrett Creeley 2314e40c899aSBrett Creeley return 0; 2315e40c899aSBrett Creeley } 2316e40c899aSBrett Creeley 2317e40c899aSBrett Creeley /** 231867fe64d7SBrett Creeley * __ice_get_coalesce - get ITR/INTRL values for the device 231967fe64d7SBrett Creeley * @netdev: pointer to the netdev associated with this query 232067fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 232167fe64d7SBrett Creeley * @q_num: queue number to get the coalesce settings for 2322e40c899aSBrett Creeley * 2323e40c899aSBrett Creeley * If the caller passes in a negative q_num then we return coalesce settings 2324e40c899aSBrett Creeley * based on queue number 0, else use the actual q_num passed in. 232567fe64d7SBrett Creeley */ 232667fe64d7SBrett Creeley static int 232767fe64d7SBrett Creeley __ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 232867fe64d7SBrett Creeley int q_num) 232967fe64d7SBrett Creeley { 233067fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 233167fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 233267fe64d7SBrett Creeley 2333e40c899aSBrett Creeley if (q_num < 0) 2334e40c899aSBrett Creeley q_num = 0; 233567fe64d7SBrett Creeley 2336e40c899aSBrett Creeley if (ice_get_q_coalesce(vsi, ec, q_num)) 233767fe64d7SBrett Creeley return -EINVAL; 233867fe64d7SBrett Creeley 233967fe64d7SBrett Creeley if (q_num < vsi->num_txq) 234067fe64d7SBrett Creeley ec->tx_max_coalesced_frames_irq = vsi->work_lmt; 234167fe64d7SBrett Creeley 234267fe64d7SBrett Creeley if (q_num < vsi->num_rxq) 234367fe64d7SBrett Creeley ec->rx_max_coalesced_frames_irq = vsi->work_lmt; 234467fe64d7SBrett Creeley 234567fe64d7SBrett Creeley return 0; 234667fe64d7SBrett Creeley } 234767fe64d7SBrett Creeley 234867fe64d7SBrett Creeley static int 234967fe64d7SBrett Creeley ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 235067fe64d7SBrett Creeley { 235167fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, -1); 235267fe64d7SBrett Creeley } 235367fe64d7SBrett Creeley 2354c8b7abddSBruce Allan static int 2355c8b7abddSBruce Allan ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num, 235667fe64d7SBrett Creeley struct ethtool_coalesce *ec) 235767fe64d7SBrett Creeley { 235867fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, q_num); 235967fe64d7SBrett Creeley } 236067fe64d7SBrett Creeley 236167fe64d7SBrett Creeley /** 236267fe64d7SBrett Creeley * ice_set_rc_coalesce - set ITR values for specific ring container 2363f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 236467fe64d7SBrett Creeley * @ec: ethtool structure from user to update ITR settings 236567fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 236667fe64d7SBrett Creeley * @vsi: VSI associated to the ring container 236767fe64d7SBrett Creeley * 236867fe64d7SBrett Creeley * Set specific ITR values. This is done per ice_ring_container because each 236967fe64d7SBrett Creeley * q_vector can have 1 or more rings and all of said ring(s) will have the same 237067fe64d7SBrett Creeley * ITR values. 237167fe64d7SBrett Creeley * 237267fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 237367fe64d7SBrett Creeley */ 237467fe64d7SBrett Creeley static int 237567fe64d7SBrett Creeley ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec, 237667fe64d7SBrett Creeley struct ice_ring_container *rc, struct ice_vsi *vsi) 237767fe64d7SBrett Creeley { 237867fe64d7SBrett Creeley struct ice_pf *pf = vsi->back; 237967fe64d7SBrett Creeley u16 itr_setting; 238067fe64d7SBrett Creeley 238167fe64d7SBrett Creeley if (!rc->ring) 238267fe64d7SBrett Creeley return -EINVAL; 238367fe64d7SBrett Creeley 238467fe64d7SBrett Creeley itr_setting = rc->itr_setting & ~ICE_ITR_DYNAMIC; 238567fe64d7SBrett Creeley 238667fe64d7SBrett Creeley switch (c_type) { 238767fe64d7SBrett Creeley case ICE_RX_CONTAINER: 2388b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high > ICE_MAX_INTRL || 2389b9c8bb06SBrett Creeley (ec->rx_coalesce_usecs_high && 2390b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high < pf->hw.intrl_gran)) { 2391b9c8bb06SBrett Creeley netdev_info(vsi->netdev, 2392b9c8bb06SBrett Creeley "Invalid value, rx-usecs-high valid values are 0 (disabled), %d-%d\n", 2393b9c8bb06SBrett Creeley pf->hw.intrl_gran, ICE_MAX_INTRL); 2394b9c8bb06SBrett Creeley return -EINVAL; 2395b9c8bb06SBrett Creeley } 2396b9c8bb06SBrett Creeley 2397b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high != rc->ring->q_vector->intrl) { 2398b9c8bb06SBrett Creeley rc->ring->q_vector->intrl = ec->rx_coalesce_usecs_high; 2399b9c8bb06SBrett Creeley wr32(&pf->hw, GLINT_RATE(vsi->hw_base_vector + 2400b9c8bb06SBrett Creeley rc->ring->q_vector->v_idx), 2401b9c8bb06SBrett Creeley ice_intrl_usec_to_reg(ec->rx_coalesce_usecs_high, 2402b9c8bb06SBrett Creeley pf->hw.intrl_gran)); 2403b9c8bb06SBrett Creeley } 2404b9c8bb06SBrett Creeley 240567fe64d7SBrett Creeley if (ec->rx_coalesce_usecs != itr_setting && 240667fe64d7SBrett Creeley ec->use_adaptive_rx_coalesce) { 240767fe64d7SBrett Creeley netdev_info(vsi->netdev, 240867fe64d7SBrett Creeley "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n"); 240967fe64d7SBrett Creeley return -EINVAL; 241067fe64d7SBrett Creeley } 241167fe64d7SBrett Creeley 241267fe64d7SBrett Creeley if (ec->rx_coalesce_usecs > ICE_ITR_MAX) { 241367fe64d7SBrett Creeley netdev_info(vsi->netdev, 241467fe64d7SBrett Creeley "Invalid value, rx-usecs range is 0-%d\n", 241567fe64d7SBrett Creeley ICE_ITR_MAX); 241667fe64d7SBrett Creeley return -EINVAL; 241767fe64d7SBrett Creeley } 241867fe64d7SBrett Creeley 241967fe64d7SBrett Creeley if (ec->use_adaptive_rx_coalesce) { 242067fe64d7SBrett Creeley rc->itr_setting |= ICE_ITR_DYNAMIC; 242167fe64d7SBrett Creeley } else { 242267fe64d7SBrett Creeley rc->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs); 242367fe64d7SBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 242467fe64d7SBrett Creeley } 242567fe64d7SBrett Creeley break; 242667fe64d7SBrett Creeley case ICE_TX_CONTAINER: 2427b9c8bb06SBrett Creeley if (ec->tx_coalesce_usecs_high) { 2428b9c8bb06SBrett Creeley netdev_info(vsi->netdev, 2429b9c8bb06SBrett Creeley "setting tx-usecs-high is not supported\n"); 2430b9c8bb06SBrett Creeley return -EINVAL; 2431b9c8bb06SBrett Creeley } 2432b9c8bb06SBrett Creeley 243367fe64d7SBrett Creeley if (ec->tx_coalesce_usecs != itr_setting && 243467fe64d7SBrett Creeley ec->use_adaptive_tx_coalesce) { 243567fe64d7SBrett Creeley netdev_info(vsi->netdev, 243667fe64d7SBrett Creeley "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n"); 243767fe64d7SBrett Creeley return -EINVAL; 243867fe64d7SBrett Creeley } 243967fe64d7SBrett Creeley 244067fe64d7SBrett Creeley if (ec->tx_coalesce_usecs > ICE_ITR_MAX) { 244167fe64d7SBrett Creeley netdev_info(vsi->netdev, 244267fe64d7SBrett Creeley "Invalid value, tx-usecs range is 0-%d\n", 244367fe64d7SBrett Creeley ICE_ITR_MAX); 244467fe64d7SBrett Creeley return -EINVAL; 244567fe64d7SBrett Creeley } 244667fe64d7SBrett Creeley 244767fe64d7SBrett Creeley if (ec->use_adaptive_tx_coalesce) { 244867fe64d7SBrett Creeley rc->itr_setting |= ICE_ITR_DYNAMIC; 244967fe64d7SBrett Creeley } else { 245067fe64d7SBrett Creeley rc->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs); 245167fe64d7SBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 245267fe64d7SBrett Creeley } 245367fe64d7SBrett Creeley break; 245467fe64d7SBrett Creeley default: 245567fe64d7SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid container type %d\n", c_type); 245667fe64d7SBrett Creeley return -EINVAL; 245767fe64d7SBrett Creeley } 245867fe64d7SBrett Creeley 245967fe64d7SBrett Creeley return 0; 246067fe64d7SBrett Creeley } 246167fe64d7SBrett Creeley 2462e40c899aSBrett Creeley /** 2463e40c899aSBrett Creeley * ice_set_q_coalesce - set a queue's ITR/INTRL (coalesce) settings 2464e40c899aSBrett Creeley * @vsi: VSI associated to the queue that need updating 2465e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 2466e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 2467e40c899aSBrett Creeley * 2468e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 2469e40c899aSBrett Creeley * 1. Setting Tx or Rx ITR/INTRL (coalesce) settings failed. 2470e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 2471e40c899aSBrett Creeley */ 2472e40c899aSBrett Creeley static int 2473e40c899aSBrett Creeley ice_set_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 2474e40c899aSBrett Creeley { 2475e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 2476e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 2477e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 2478e40c899aSBrett Creeley vsi)) 2479e40c899aSBrett Creeley return -EINVAL; 2480e40c899aSBrett Creeley 2481e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 2482e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 2483e40c899aSBrett Creeley vsi)) 2484e40c899aSBrett Creeley return -EINVAL; 2485e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 2486e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 2487e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 2488e40c899aSBrett Creeley vsi)) 2489e40c899aSBrett Creeley return -EINVAL; 2490e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 2491e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 2492e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 2493e40c899aSBrett Creeley vsi)) 2494e40c899aSBrett Creeley return -EINVAL; 2495e40c899aSBrett Creeley } else { 2496e40c899aSBrett Creeley return -EINVAL; 2497e40c899aSBrett Creeley } 2498e40c899aSBrett Creeley 2499e40c899aSBrett Creeley return 0; 2500e40c899aSBrett Creeley } 2501e40c899aSBrett Creeley 2502e40c899aSBrett Creeley /** 2503e40c899aSBrett Creeley * __ice_set_coalesce - set ITR/INTRL values for the device 2504e40c899aSBrett Creeley * @netdev: pointer to the netdev associated with this query 2505e40c899aSBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 2506e40c899aSBrett Creeley * @q_num: queue number to get the coalesce settings for 2507e40c899aSBrett Creeley * 2508e40c899aSBrett Creeley * If the caller passes in a negative q_num then we set the coalesce settings 2509e40c899aSBrett Creeley * for all Tx/Rx queues, else use the actual q_num passed in. 2510e40c899aSBrett Creeley */ 251167fe64d7SBrett Creeley static int 251267fe64d7SBrett Creeley __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 251367fe64d7SBrett Creeley int q_num) 251467fe64d7SBrett Creeley { 251567fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 251667fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 251767fe64d7SBrett Creeley 251867fe64d7SBrett Creeley if (q_num < 0) { 251967fe64d7SBrett Creeley int i; 252067fe64d7SBrett Creeley 252167fe64d7SBrett Creeley ice_for_each_q_vector(vsi, i) { 2522e40c899aSBrett Creeley if (ice_set_q_coalesce(vsi, ec, i)) 252367fe64d7SBrett Creeley return -EINVAL; 252467fe64d7SBrett Creeley } 252567fe64d7SBrett Creeley goto set_work_lmt; 252667fe64d7SBrett Creeley } 252767fe64d7SBrett Creeley 2528e40c899aSBrett Creeley if (ice_set_q_coalesce(vsi, ec, q_num)) 252967fe64d7SBrett Creeley return -EINVAL; 253067fe64d7SBrett Creeley 253167fe64d7SBrett Creeley set_work_lmt: 2532e40c899aSBrett Creeley 253367fe64d7SBrett Creeley if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) 253467fe64d7SBrett Creeley vsi->work_lmt = max(ec->tx_max_coalesced_frames_irq, 253567fe64d7SBrett Creeley ec->rx_max_coalesced_frames_irq); 253667fe64d7SBrett Creeley 253767fe64d7SBrett Creeley return 0; 253867fe64d7SBrett Creeley } 253967fe64d7SBrett Creeley 254067fe64d7SBrett Creeley static int 254167fe64d7SBrett Creeley ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 254267fe64d7SBrett Creeley { 254367fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, -1); 254467fe64d7SBrett Creeley } 254567fe64d7SBrett Creeley 2546c8b7abddSBruce Allan static int 2547c8b7abddSBruce Allan ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num, 254867fe64d7SBrett Creeley struct ethtool_coalesce *ec) 254967fe64d7SBrett Creeley { 255067fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, q_num); 255167fe64d7SBrett Creeley } 255267fe64d7SBrett Creeley 2553fcea6f3dSAnirudh Venkataramanan static const struct ethtool_ops ice_ethtool_ops = { 2554fcea6f3dSAnirudh Venkataramanan .get_link_ksettings = ice_get_link_ksettings, 255548cb27f2SChinh Cao .set_link_ksettings = ice_set_link_ksettings, 2556fcea6f3dSAnirudh Venkataramanan .get_drvinfo = ice_get_drvinfo, 2557fcea6f3dSAnirudh Venkataramanan .get_regs_len = ice_get_regs_len, 2558fcea6f3dSAnirudh Venkataramanan .get_regs = ice_get_regs, 2559fcea6f3dSAnirudh Venkataramanan .get_msglevel = ice_get_msglevel, 2560fcea6f3dSAnirudh Venkataramanan .set_msglevel = ice_set_msglevel, 2561fcea6f3dSAnirudh Venkataramanan .get_link = ethtool_op_get_link, 25624c98ab55SBruce Allan .get_eeprom_len = ice_get_eeprom_len, 25634c98ab55SBruce Allan .get_eeprom = ice_get_eeprom, 256467fe64d7SBrett Creeley .get_coalesce = ice_get_coalesce, 256567fe64d7SBrett Creeley .set_coalesce = ice_set_coalesce, 2566fcea6f3dSAnirudh Venkataramanan .get_strings = ice_get_strings, 25678e151d50SAnirudh Venkataramanan .set_phys_id = ice_set_phys_id, 2568fcea6f3dSAnirudh Venkataramanan .get_ethtool_stats = ice_get_ethtool_stats, 2569ab4ab73fSBruce Allan .get_priv_flags = ice_get_priv_flags, 2570ab4ab73fSBruce Allan .set_priv_flags = ice_set_priv_flags, 2571fcea6f3dSAnirudh Venkataramanan .get_sset_count = ice_get_sset_count, 2572fcea6f3dSAnirudh Venkataramanan .get_rxnfc = ice_get_rxnfc, 2573fcea6f3dSAnirudh Venkataramanan .get_ringparam = ice_get_ringparam, 2574fcea6f3dSAnirudh Venkataramanan .set_ringparam = ice_set_ringparam, 2575fcea6f3dSAnirudh Venkataramanan .nway_reset = ice_nway_reset, 2576fcea6f3dSAnirudh Venkataramanan .get_pauseparam = ice_get_pauseparam, 2577fcea6f3dSAnirudh Venkataramanan .set_pauseparam = ice_set_pauseparam, 2578fcea6f3dSAnirudh Venkataramanan .get_rxfh_key_size = ice_get_rxfh_key_size, 2579fcea6f3dSAnirudh Venkataramanan .get_rxfh_indir_size = ice_get_rxfh_indir_size, 2580fcea6f3dSAnirudh Venkataramanan .get_rxfh = ice_get_rxfh, 2581fcea6f3dSAnirudh Venkataramanan .set_rxfh = ice_set_rxfh, 2582a8939784STony Nguyen .get_ts_info = ethtool_op_get_ts_info, 258367fe64d7SBrett Creeley .get_per_queue_coalesce = ice_get_per_q_coalesce, 258467fe64d7SBrett Creeley .set_per_queue_coalesce = ice_set_per_q_coalesce, 2585fcea6f3dSAnirudh Venkataramanan }; 2586fcea6f3dSAnirudh Venkataramanan 2587fcea6f3dSAnirudh Venkataramanan /** 2588fcea6f3dSAnirudh Venkataramanan * ice_set_ethtool_ops - setup netdev ethtool ops 2589fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2590fcea6f3dSAnirudh Venkataramanan * 2591fcea6f3dSAnirudh Venkataramanan * setup netdev ethtool ops with ice specific ops 2592fcea6f3dSAnirudh Venkataramanan */ 2593fcea6f3dSAnirudh Venkataramanan void ice_set_ethtool_ops(struct net_device *netdev) 2594fcea6f3dSAnirudh Venkataramanan { 2595fcea6f3dSAnirudh Venkataramanan netdev->ethtool_ops = &ice_ethtool_ops; 2596fcea6f3dSAnirudh Venkataramanan } 2597