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("rx_unicast", eth_stats.rx_unicast), 4955e062baSRichard Rodriguez ICE_VSI_STAT("tx_unicast", eth_stats.tx_unicast), 50fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_multicast", eth_stats.rx_multicast), 5155e062baSRichard Rodriguez ICE_VSI_STAT("tx_multicast", eth_stats.tx_multicast), 52fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_broadcast", eth_stats.rx_broadcast), 5355e062baSRichard Rodriguez ICE_VSI_STAT("tx_broadcast", eth_stats.tx_broadcast), 54fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_bytes", eth_stats.rx_bytes), 5555e062baSRichard Rodriguez ICE_VSI_STAT("tx_bytes", eth_stats.tx_bytes), 5655e062baSRichard Rodriguez ICE_VSI_STAT("rx_dropped", eth_stats.rx_discards), 57fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol), 58fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_alloc_fail", rx_buf_failed), 59fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_pg_alloc_fail", rx_page_failed), 6055e062baSRichard Rodriguez ICE_VSI_STAT("tx_errors", eth_stats.tx_errors), 6155e062baSRichard Rodriguez ICE_VSI_STAT("tx_linearize", tx_linearize), 62fcea6f3dSAnirudh Venkataramanan }; 63fcea6f3dSAnirudh Venkataramanan 640e674aebSAnirudh Venkataramanan enum ice_ethtool_test_id { 650e674aebSAnirudh Venkataramanan ICE_ETH_TEST_REG = 0, 660e674aebSAnirudh Venkataramanan ICE_ETH_TEST_EEPROM, 670e674aebSAnirudh Venkataramanan ICE_ETH_TEST_INTR, 680e674aebSAnirudh Venkataramanan ICE_ETH_TEST_LOOP, 690e674aebSAnirudh Venkataramanan ICE_ETH_TEST_LINK, 700e674aebSAnirudh Venkataramanan }; 710e674aebSAnirudh Venkataramanan 720e674aebSAnirudh Venkataramanan static const char ice_gstrings_test[][ETH_GSTRING_LEN] = { 730e674aebSAnirudh Venkataramanan "Register test (offline)", 740e674aebSAnirudh Venkataramanan "EEPROM test (offline)", 750e674aebSAnirudh Venkataramanan "Interrupt test (offline)", 760e674aebSAnirudh Venkataramanan "Loopback test (offline)", 770e674aebSAnirudh Venkataramanan "Link test (on/offline)", 780e674aebSAnirudh Venkataramanan }; 790e674aebSAnirudh Venkataramanan 800e674aebSAnirudh Venkataramanan #define ICE_TEST_LEN (sizeof(ice_gstrings_test) / ETH_GSTRING_LEN) 810e674aebSAnirudh Venkataramanan 82fcea6f3dSAnirudh Venkataramanan /* These PF_STATs might look like duplicates of some NETDEV_STATs, 83fcea6f3dSAnirudh Venkataramanan * but they aren't. This device is capable of supporting multiple 84fcea6f3dSAnirudh Venkataramanan * VSIs/netdevs on a single PF. The NETDEV_STATs are for individual 85fcea6f3dSAnirudh Venkataramanan * netdevs whereas the PF_STATs are for the physical function that's 86fcea6f3dSAnirudh Venkataramanan * hosting these netdevs. 87fcea6f3dSAnirudh Venkataramanan * 88fcea6f3dSAnirudh Venkataramanan * The PF_STATs are appended to the netdev stats only when ethtool -S 89fcea6f3dSAnirudh Venkataramanan * is queried on the base PF netdev. 90fcea6f3dSAnirudh Venkataramanan */ 9155aa141eSBruce Allan static const struct ice_stats ice_gstrings_pf_stats[] = { 9255e062baSRichard Rodriguez ICE_PF_STAT("rx_bytes.nic", stats.eth.rx_bytes), 9355e062baSRichard Rodriguez ICE_PF_STAT("tx_bytes.nic", stats.eth.tx_bytes), 9455e062baSRichard Rodriguez ICE_PF_STAT("rx_unicast.nic", stats.eth.rx_unicast), 9555e062baSRichard Rodriguez ICE_PF_STAT("tx_unicast.nic", stats.eth.tx_unicast), 9655e062baSRichard Rodriguez ICE_PF_STAT("rx_multicast.nic", stats.eth.rx_multicast), 9755e062baSRichard Rodriguez ICE_PF_STAT("tx_multicast.nic", stats.eth.tx_multicast), 9855e062baSRichard Rodriguez ICE_PF_STAT("rx_broadcast.nic", stats.eth.rx_broadcast), 9955e062baSRichard Rodriguez ICE_PF_STAT("tx_broadcast.nic", stats.eth.tx_broadcast), 10055e062baSRichard Rodriguez ICE_PF_STAT("tx_errors.nic", stats.eth.tx_errors), 10155e062baSRichard Rodriguez ICE_PF_STAT("rx_size_64.nic", stats.rx_size_64), 10255e062baSRichard Rodriguez ICE_PF_STAT("tx_size_64.nic", stats.tx_size_64), 10355e062baSRichard Rodriguez ICE_PF_STAT("rx_size_127.nic", stats.rx_size_127), 10455e062baSRichard Rodriguez ICE_PF_STAT("tx_size_127.nic", stats.tx_size_127), 10555e062baSRichard Rodriguez ICE_PF_STAT("rx_size_255.nic", stats.rx_size_255), 10655e062baSRichard Rodriguez ICE_PF_STAT("tx_size_255.nic", stats.tx_size_255), 10755e062baSRichard Rodriguez ICE_PF_STAT("rx_size_511.nic", stats.rx_size_511), 10855e062baSRichard Rodriguez ICE_PF_STAT("tx_size_511.nic", stats.tx_size_511), 10955e062baSRichard Rodriguez ICE_PF_STAT("rx_size_1023.nic", stats.rx_size_1023), 11055e062baSRichard Rodriguez ICE_PF_STAT("tx_size_1023.nic", stats.tx_size_1023), 11155e062baSRichard Rodriguez ICE_PF_STAT("rx_size_1522.nic", stats.rx_size_1522), 11255e062baSRichard Rodriguez ICE_PF_STAT("tx_size_1522.nic", stats.tx_size_1522), 11355e062baSRichard Rodriguez ICE_PF_STAT("rx_size_big.nic", stats.rx_size_big), 11455e062baSRichard Rodriguez ICE_PF_STAT("tx_size_big.nic", stats.tx_size_big), 11555e062baSRichard Rodriguez ICE_PF_STAT("link_xon_rx.nic", stats.link_xon_rx), 11655e062baSRichard Rodriguez ICE_PF_STAT("link_xon_tx.nic", stats.link_xon_tx), 11755e062baSRichard Rodriguez ICE_PF_STAT("link_xoff_rx.nic", stats.link_xoff_rx), 11855e062baSRichard Rodriguez ICE_PF_STAT("link_xoff_tx.nic", stats.link_xoff_tx), 11955e062baSRichard Rodriguez ICE_PF_STAT("tx_dropped_link_down.nic", stats.tx_dropped_link_down), 12055e062baSRichard Rodriguez ICE_PF_STAT("rx_undersize.nic", stats.rx_undersize), 12155e062baSRichard Rodriguez ICE_PF_STAT("rx_fragments.nic", stats.rx_fragments), 12255e062baSRichard Rodriguez ICE_PF_STAT("rx_oversize.nic", stats.rx_oversize), 12355e062baSRichard Rodriguez ICE_PF_STAT("rx_jabber.nic", stats.rx_jabber), 12455e062baSRichard Rodriguez ICE_PF_STAT("rx_csum_bad.nic", hw_csum_rx_error), 12555e062baSRichard Rodriguez ICE_PF_STAT("rx_length_errors.nic", stats.rx_len_errors), 12655e062baSRichard Rodriguez ICE_PF_STAT("rx_dropped.nic", stats.eth.rx_discards), 12755e062baSRichard Rodriguez ICE_PF_STAT("rx_crc_errors.nic", stats.crc_errors), 12855e062baSRichard Rodriguez ICE_PF_STAT("illegal_bytes.nic", stats.illegal_bytes), 12955e062baSRichard Rodriguez ICE_PF_STAT("mac_local_faults.nic", stats.mac_local_faults), 13055e062baSRichard Rodriguez ICE_PF_STAT("mac_remote_faults.nic", stats.mac_remote_faults), 131fcea6f3dSAnirudh Venkataramanan }; 132fcea6f3dSAnirudh Venkataramanan 13355aa141eSBruce Allan static const u32 ice_regs_dump_list[] = { 134fcea6f3dSAnirudh Venkataramanan PFGEN_STATE, 135fcea6f3dSAnirudh Venkataramanan PRTGEN_STATUS, 136fcea6f3dSAnirudh Venkataramanan QRX_CTRL(0), 137fcea6f3dSAnirudh Venkataramanan QINT_TQCTL(0), 138fcea6f3dSAnirudh Venkataramanan QINT_RQCTL(0), 139fcea6f3dSAnirudh Venkataramanan PFINT_OICR_ENA, 140fcea6f3dSAnirudh Venkataramanan QRX_ITR(0), 1410e674aebSAnirudh Venkataramanan PF0INT_ITR_0(0), 1420e674aebSAnirudh Venkataramanan PF0INT_ITR_1(0), 1430e674aebSAnirudh Venkataramanan PF0INT_ITR_2(0), 144fcea6f3dSAnirudh Venkataramanan }; 145fcea6f3dSAnirudh Venkataramanan 146ab4ab73fSBruce Allan struct ice_priv_flag { 147ab4ab73fSBruce Allan char name[ETH_GSTRING_LEN]; 148ab4ab73fSBruce Allan u32 bitno; /* bit position in pf->flags */ 149ab4ab73fSBruce Allan }; 150ab4ab73fSBruce Allan 151ab4ab73fSBruce Allan #define ICE_PRIV_FLAG(_name, _bitno) { \ 152ab4ab73fSBruce Allan .name = _name, \ 153ab4ab73fSBruce Allan .bitno = _bitno, \ 154ab4ab73fSBruce Allan } 155ab4ab73fSBruce Allan 156ab4ab73fSBruce Allan static const struct ice_priv_flag ice_gstrings_priv_flags[] = { 157ab4ab73fSBruce Allan ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA), 15831eafa40SAnirudh Venkataramanan ICE_PRIV_FLAG("enable-fw-lldp", ICE_FLAG_ENABLE_FW_LLDP), 159ab4ab73fSBruce Allan }; 160ab4ab73fSBruce Allan 161ab4ab73fSBruce Allan #define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags) 162ab4ab73fSBruce Allan 163fcea6f3dSAnirudh Venkataramanan /** 164fcea6f3dSAnirudh Venkataramanan * ice_nvm_version_str - format the NVM version strings 165fcea6f3dSAnirudh Venkataramanan * @hw: ptr to the hardware info 166fcea6f3dSAnirudh Venkataramanan */ 167fcea6f3dSAnirudh Venkataramanan static char *ice_nvm_version_str(struct ice_hw *hw) 168fcea6f3dSAnirudh Venkataramanan { 169fcea6f3dSAnirudh Venkataramanan static char buf[ICE_ETHTOOL_FWVER_LEN]; 170fcea6f3dSAnirudh Venkataramanan u8 ver, patch; 171fcea6f3dSAnirudh Venkataramanan u32 full_ver; 172fcea6f3dSAnirudh Venkataramanan u16 build; 173fcea6f3dSAnirudh Venkataramanan 174fcea6f3dSAnirudh Venkataramanan full_ver = hw->nvm.oem_ver; 175fcea6f3dSAnirudh Venkataramanan ver = (u8)((full_ver & ICE_OEM_VER_MASK) >> ICE_OEM_VER_SHIFT); 176fcea6f3dSAnirudh Venkataramanan build = (u16)((full_ver & ICE_OEM_VER_BUILD_MASK) >> 177fcea6f3dSAnirudh Venkataramanan ICE_OEM_VER_BUILD_SHIFT); 178fcea6f3dSAnirudh Venkataramanan patch = (u8)(full_ver & ICE_OEM_VER_PATCH_MASK); 179fcea6f3dSAnirudh Venkataramanan 180fcea6f3dSAnirudh Venkataramanan snprintf(buf, sizeof(buf), "%x.%02x 0x%x %d.%d.%d", 181fcea6f3dSAnirudh Venkataramanan (hw->nvm.ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT, 182fcea6f3dSAnirudh Venkataramanan (hw->nvm.ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT, 183fcea6f3dSAnirudh Venkataramanan hw->nvm.eetrack, ver, build, patch); 184fcea6f3dSAnirudh Venkataramanan 185fcea6f3dSAnirudh Venkataramanan return buf; 186fcea6f3dSAnirudh Venkataramanan } 187fcea6f3dSAnirudh Venkataramanan 188fcea6f3dSAnirudh Venkataramanan static void 189fcea6f3dSAnirudh Venkataramanan ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) 190fcea6f3dSAnirudh Venkataramanan { 191fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 192fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 193fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 194fcea6f3dSAnirudh Venkataramanan 195fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); 196fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->version, ice_drv_ver, sizeof(drvinfo->version)); 197fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->fw_version, ice_nvm_version_str(&pf->hw), 198fcea6f3dSAnirudh Venkataramanan sizeof(drvinfo->fw_version)); 199fcea6f3dSAnirudh Venkataramanan strlcpy(drvinfo->bus_info, pci_name(pf->pdev), 200fcea6f3dSAnirudh Venkataramanan sizeof(drvinfo->bus_info)); 201ab4ab73fSBruce Allan drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE; 202fcea6f3dSAnirudh Venkataramanan } 203fcea6f3dSAnirudh Venkataramanan 204fcea6f3dSAnirudh Venkataramanan static int ice_get_regs_len(struct net_device __always_unused *netdev) 205fcea6f3dSAnirudh Venkataramanan { 206cba5957dSAnirudh Venkataramanan return sizeof(ice_regs_dump_list); 207fcea6f3dSAnirudh Venkataramanan } 208fcea6f3dSAnirudh Venkataramanan 209fcea6f3dSAnirudh Venkataramanan static void 210fcea6f3dSAnirudh Venkataramanan ice_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) 211fcea6f3dSAnirudh Venkataramanan { 212fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 213fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 214fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 215fcea6f3dSAnirudh Venkataramanan u32 *regs_buf = (u32 *)p; 216fcea6f3dSAnirudh Venkataramanan int i; 217fcea6f3dSAnirudh Venkataramanan 218fcea6f3dSAnirudh Venkataramanan regs->version = 1; 219fcea6f3dSAnirudh Venkataramanan 220cba5957dSAnirudh Venkataramanan for (i = 0; i < ARRAY_SIZE(ice_regs_dump_list); ++i) 221fcea6f3dSAnirudh Venkataramanan regs_buf[i] = rd32(hw, ice_regs_dump_list[i]); 222fcea6f3dSAnirudh Venkataramanan } 223fcea6f3dSAnirudh Venkataramanan 224fcea6f3dSAnirudh Venkataramanan static u32 ice_get_msglevel(struct net_device *netdev) 225fcea6f3dSAnirudh Venkataramanan { 226fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 227fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 228fcea6f3dSAnirudh Venkataramanan 229fcea6f3dSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 230fcea6f3dSAnirudh Venkataramanan if (pf->hw.debug_mask) 231fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "hw debug_mask: 0x%llX\n", 232fcea6f3dSAnirudh Venkataramanan pf->hw.debug_mask); 233fcea6f3dSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 234fcea6f3dSAnirudh Venkataramanan 235fcea6f3dSAnirudh Venkataramanan return pf->msg_enable; 236fcea6f3dSAnirudh Venkataramanan } 237fcea6f3dSAnirudh Venkataramanan 238fcea6f3dSAnirudh Venkataramanan static void ice_set_msglevel(struct net_device *netdev, u32 data) 239fcea6f3dSAnirudh Venkataramanan { 240fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 241fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 242fcea6f3dSAnirudh Venkataramanan 243fcea6f3dSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 244fcea6f3dSAnirudh Venkataramanan if (ICE_DBG_USER & data) 245fcea6f3dSAnirudh Venkataramanan pf->hw.debug_mask = data; 246fcea6f3dSAnirudh Venkataramanan else 247fcea6f3dSAnirudh Venkataramanan pf->msg_enable = data; 248fcea6f3dSAnirudh Venkataramanan #else 249fcea6f3dSAnirudh Venkataramanan pf->msg_enable = data; 250fcea6f3dSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 251fcea6f3dSAnirudh Venkataramanan } 252fcea6f3dSAnirudh Venkataramanan 2534c98ab55SBruce Allan static int ice_get_eeprom_len(struct net_device *netdev) 2544c98ab55SBruce Allan { 2554c98ab55SBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 2564c98ab55SBruce Allan struct ice_pf *pf = np->vsi->back; 2574c98ab55SBruce Allan 2584c98ab55SBruce Allan return (int)(pf->hw.nvm.sr_words * sizeof(u16)); 2594c98ab55SBruce Allan } 2604c98ab55SBruce Allan 2614c98ab55SBruce Allan static int 2624c98ab55SBruce Allan ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, 2634c98ab55SBruce Allan u8 *bytes) 2644c98ab55SBruce Allan { 2654c98ab55SBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 2664c98ab55SBruce Allan u16 first_word, last_word, nwords; 2674c98ab55SBruce Allan struct ice_vsi *vsi = np->vsi; 2684c98ab55SBruce Allan struct ice_pf *pf = vsi->back; 2694c98ab55SBruce Allan struct ice_hw *hw = &pf->hw; 2704c98ab55SBruce Allan enum ice_status status; 2714c98ab55SBruce Allan struct device *dev; 2724c98ab55SBruce Allan int ret = 0; 2734c98ab55SBruce Allan u16 *buf; 2744c98ab55SBruce Allan 2754c98ab55SBruce Allan dev = &pf->pdev->dev; 2764c98ab55SBruce Allan 2774c98ab55SBruce Allan eeprom->magic = hw->vendor_id | (hw->device_id << 16); 2784c98ab55SBruce Allan 2794c98ab55SBruce Allan first_word = eeprom->offset >> 1; 2804c98ab55SBruce Allan last_word = (eeprom->offset + eeprom->len - 1) >> 1; 2814c98ab55SBruce Allan nwords = last_word - first_word + 1; 2824c98ab55SBruce Allan 2834c98ab55SBruce Allan buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL); 2844c98ab55SBruce Allan if (!buf) 2854c98ab55SBruce Allan return -ENOMEM; 2864c98ab55SBruce Allan 2874c98ab55SBruce Allan status = ice_read_sr_buf(hw, first_word, &nwords, buf); 2884c98ab55SBruce Allan if (status) { 2894c98ab55SBruce Allan dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n", 2904c98ab55SBruce Allan status, hw->adminq.sq_last_status); 2914c98ab55SBruce Allan eeprom->len = sizeof(u16) * nwords; 2924c98ab55SBruce Allan ret = -EIO; 2934c98ab55SBruce Allan goto out; 2944c98ab55SBruce Allan } 2954c98ab55SBruce Allan 2964c98ab55SBruce Allan memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len); 2974c98ab55SBruce Allan out: 2984c98ab55SBruce Allan devm_kfree(dev, buf); 2994c98ab55SBruce Allan return ret; 3004c98ab55SBruce Allan } 3014c98ab55SBruce Allan 3020e674aebSAnirudh Venkataramanan /** 3030e674aebSAnirudh Venkataramanan * ice_active_vfs - check if there are any active VFs 3040e674aebSAnirudh Venkataramanan * @pf: board private structure 3050e674aebSAnirudh Venkataramanan * 3060e674aebSAnirudh Venkataramanan * Returns true if an active VF is found, otherwise returns false 3070e674aebSAnirudh Venkataramanan */ 3080e674aebSAnirudh Venkataramanan static bool ice_active_vfs(struct ice_pf *pf) 3090e674aebSAnirudh Venkataramanan { 3100e674aebSAnirudh Venkataramanan struct ice_vf *vf = pf->vf; 3110e674aebSAnirudh Venkataramanan int i; 3120e674aebSAnirudh Venkataramanan 3130e674aebSAnirudh Venkataramanan for (i = 0; i < pf->num_alloc_vfs; i++, vf++) 3140e674aebSAnirudh Venkataramanan if (test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) 3150e674aebSAnirudh Venkataramanan return true; 3160e674aebSAnirudh Venkataramanan return false; 3170e674aebSAnirudh Venkataramanan } 3180e674aebSAnirudh Venkataramanan 3190e674aebSAnirudh Venkataramanan /** 3200e674aebSAnirudh Venkataramanan * ice_link_test - perform a link test on a given net_device 3210e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 3220e674aebSAnirudh Venkataramanan * 3230e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 3240e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 3250e674aebSAnirudh Venkataramanan */ 3260e674aebSAnirudh Venkataramanan static u64 ice_link_test(struct net_device *netdev) 3270e674aebSAnirudh Venkataramanan { 3280e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3290e674aebSAnirudh Venkataramanan enum ice_status status; 3300e674aebSAnirudh Venkataramanan bool link_up = false; 3310e674aebSAnirudh Venkataramanan 3320e674aebSAnirudh Venkataramanan netdev_info(netdev, "link test\n"); 3330e674aebSAnirudh Venkataramanan status = ice_get_link_status(np->vsi->port_info, &link_up); 3340e674aebSAnirudh Venkataramanan if (status) { 3350e674aebSAnirudh Venkataramanan netdev_err(netdev, "link query error, status = %d\n", status); 3360e674aebSAnirudh Venkataramanan return 1; 3370e674aebSAnirudh Venkataramanan } 3380e674aebSAnirudh Venkataramanan 3390e674aebSAnirudh Venkataramanan if (!link_up) 3400e674aebSAnirudh Venkataramanan return 2; 3410e674aebSAnirudh Venkataramanan 3420e674aebSAnirudh Venkataramanan return 0; 3430e674aebSAnirudh Venkataramanan } 3440e674aebSAnirudh Venkataramanan 3450e674aebSAnirudh Venkataramanan /** 3460e674aebSAnirudh Venkataramanan * ice_eeprom_test - perform an EEPROM test on a given net_device 3470e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 3480e674aebSAnirudh Venkataramanan * 3490e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 3500e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 3510e674aebSAnirudh Venkataramanan */ 3520e674aebSAnirudh Venkataramanan static u64 ice_eeprom_test(struct net_device *netdev) 3530e674aebSAnirudh Venkataramanan { 3540e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3550e674aebSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 3560e674aebSAnirudh Venkataramanan 3570e674aebSAnirudh Venkataramanan netdev_info(netdev, "EEPROM test\n"); 3580e674aebSAnirudh Venkataramanan return !!(ice_nvm_validate_checksum(&pf->hw)); 3590e674aebSAnirudh Venkataramanan } 3600e674aebSAnirudh Venkataramanan 3610e674aebSAnirudh Venkataramanan /** 3620e674aebSAnirudh Venkataramanan * ice_reg_pattern_test 3630e674aebSAnirudh Venkataramanan * @hw: pointer to the HW struct 3640e674aebSAnirudh Venkataramanan * @reg: reg to be tested 3650e674aebSAnirudh Venkataramanan * @mask: bits to be touched 3660e674aebSAnirudh Venkataramanan */ 3670e674aebSAnirudh Venkataramanan static int ice_reg_pattern_test(struct ice_hw *hw, u32 reg, u32 mask) 3680e674aebSAnirudh Venkataramanan { 3690e674aebSAnirudh Venkataramanan struct ice_pf *pf = (struct ice_pf *)hw->back; 3700e674aebSAnirudh Venkataramanan static const u32 patterns[] = { 3710e674aebSAnirudh Venkataramanan 0x5A5A5A5A, 0xA5A5A5A5, 3720e674aebSAnirudh Venkataramanan 0x00000000, 0xFFFFFFFF 3730e674aebSAnirudh Venkataramanan }; 3740e674aebSAnirudh Venkataramanan u32 val, orig_val; 3750e674aebSAnirudh Venkataramanan int i; 3760e674aebSAnirudh Venkataramanan 3770e674aebSAnirudh Venkataramanan orig_val = rd32(hw, reg); 3780e674aebSAnirudh Venkataramanan for (i = 0; i < ARRAY_SIZE(patterns); ++i) { 3790e674aebSAnirudh Venkataramanan u32 pattern = patterns[i] & mask; 3800e674aebSAnirudh Venkataramanan 3810e674aebSAnirudh Venkataramanan wr32(hw, reg, pattern); 3820e674aebSAnirudh Venkataramanan val = rd32(hw, reg); 3830e674aebSAnirudh Venkataramanan if (val == pattern) 3840e674aebSAnirudh Venkataramanan continue; 3850e674aebSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3860e674aebSAnirudh Venkataramanan "%s: reg pattern test failed - reg 0x%08x pat 0x%08x val 0x%08x\n" 3870e674aebSAnirudh Venkataramanan , __func__, reg, pattern, val); 3880e674aebSAnirudh Venkataramanan return 1; 3890e674aebSAnirudh Venkataramanan } 3900e674aebSAnirudh Venkataramanan 3910e674aebSAnirudh Venkataramanan wr32(hw, reg, orig_val); 3920e674aebSAnirudh Venkataramanan val = rd32(hw, reg); 3930e674aebSAnirudh Venkataramanan if (val != orig_val) { 3940e674aebSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 3950e674aebSAnirudh Venkataramanan "%s: reg restore test failed - reg 0x%08x orig 0x%08x val 0x%08x\n" 3960e674aebSAnirudh Venkataramanan , __func__, reg, orig_val, val); 3970e674aebSAnirudh Venkataramanan return 1; 3980e674aebSAnirudh Venkataramanan } 3990e674aebSAnirudh Venkataramanan 4000e674aebSAnirudh Venkataramanan return 0; 4010e674aebSAnirudh Venkataramanan } 4020e674aebSAnirudh Venkataramanan 4030e674aebSAnirudh Venkataramanan /** 4040e674aebSAnirudh Venkataramanan * ice_reg_test - perform a register test on a given net_device 4050e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 4060e674aebSAnirudh Venkataramanan * 4070e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 4080e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 4090e674aebSAnirudh Venkataramanan */ 4100e674aebSAnirudh Venkataramanan static u64 ice_reg_test(struct net_device *netdev) 4110e674aebSAnirudh Venkataramanan { 4120e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 4130e674aebSAnirudh Venkataramanan struct ice_hw *hw = np->vsi->port_info->hw; 4140e674aebSAnirudh Venkataramanan u32 int_elements = hw->func_caps.common_cap.num_msix_vectors ? 4150e674aebSAnirudh Venkataramanan hw->func_caps.common_cap.num_msix_vectors - 1 : 1; 4160e674aebSAnirudh Venkataramanan struct ice_diag_reg_test_info { 4170e674aebSAnirudh Venkataramanan u32 address; 4180e674aebSAnirudh Venkataramanan u32 mask; 4190e674aebSAnirudh Venkataramanan u32 elem_num; 4200e674aebSAnirudh Venkataramanan u32 elem_size; 4210e674aebSAnirudh Venkataramanan } ice_reg_list[] = { 4220e674aebSAnirudh Venkataramanan {GLINT_ITR(0, 0), 0x00000fff, int_elements, 4230e674aebSAnirudh Venkataramanan GLINT_ITR(0, 1) - GLINT_ITR(0, 0)}, 4240e674aebSAnirudh Venkataramanan {GLINT_ITR(1, 0), 0x00000fff, int_elements, 4250e674aebSAnirudh Venkataramanan GLINT_ITR(1, 1) - GLINT_ITR(1, 0)}, 4260e674aebSAnirudh Venkataramanan {GLINT_ITR(0, 0), 0x00000fff, int_elements, 4270e674aebSAnirudh Venkataramanan GLINT_ITR(2, 1) - GLINT_ITR(2, 0)}, 4280e674aebSAnirudh Venkataramanan {GLINT_CTL, 0xffff0001, 1, 0} 4290e674aebSAnirudh Venkataramanan }; 4300e674aebSAnirudh Venkataramanan int i; 4310e674aebSAnirudh Venkataramanan 4320e674aebSAnirudh Venkataramanan netdev_dbg(netdev, "Register test\n"); 4330e674aebSAnirudh Venkataramanan for (i = 0; i < ARRAY_SIZE(ice_reg_list); ++i) { 4340e674aebSAnirudh Venkataramanan u32 j; 4350e674aebSAnirudh Venkataramanan 4360e674aebSAnirudh Venkataramanan for (j = 0; j < ice_reg_list[i].elem_num; ++j) { 4370e674aebSAnirudh Venkataramanan u32 mask = ice_reg_list[i].mask; 4380e674aebSAnirudh Venkataramanan u32 reg = ice_reg_list[i].address + 4390e674aebSAnirudh Venkataramanan (j * ice_reg_list[i].elem_size); 4400e674aebSAnirudh Venkataramanan 4410e674aebSAnirudh Venkataramanan /* bail on failure (non-zero return) */ 4420e674aebSAnirudh Venkataramanan if (ice_reg_pattern_test(hw, reg, mask)) 4430e674aebSAnirudh Venkataramanan return 1; 4440e674aebSAnirudh Venkataramanan } 4450e674aebSAnirudh Venkataramanan } 4460e674aebSAnirudh Venkataramanan 4470e674aebSAnirudh Venkataramanan return 0; 4480e674aebSAnirudh Venkataramanan } 4490e674aebSAnirudh Venkataramanan 4500e674aebSAnirudh Venkataramanan /** 4510e674aebSAnirudh Venkataramanan * ice_lbtest_prepare_rings - configure Tx/Rx test rings 4520e674aebSAnirudh Venkataramanan * @vsi: pointer to the VSI structure 4530e674aebSAnirudh Venkataramanan * 4540e674aebSAnirudh Venkataramanan * Function configures rings of a VSI for loopback test without 4550e674aebSAnirudh Venkataramanan * enabling interrupts or informing the kernel about new queues. 4560e674aebSAnirudh Venkataramanan * 4570e674aebSAnirudh Venkataramanan * Returns 0 on success, negative on failure. 4580e674aebSAnirudh Venkataramanan */ 4590e674aebSAnirudh Venkataramanan static int ice_lbtest_prepare_rings(struct ice_vsi *vsi) 4600e674aebSAnirudh Venkataramanan { 4610e674aebSAnirudh Venkataramanan int status; 4620e674aebSAnirudh Venkataramanan 4630e674aebSAnirudh Venkataramanan status = ice_vsi_setup_tx_rings(vsi); 4640e674aebSAnirudh Venkataramanan if (status) 4650e674aebSAnirudh Venkataramanan goto err_setup_tx_ring; 4660e674aebSAnirudh Venkataramanan 4670e674aebSAnirudh Venkataramanan status = ice_vsi_setup_rx_rings(vsi); 4680e674aebSAnirudh Venkataramanan if (status) 4690e674aebSAnirudh Venkataramanan goto err_setup_rx_ring; 4700e674aebSAnirudh Venkataramanan 4710e674aebSAnirudh Venkataramanan status = ice_vsi_cfg(vsi); 4720e674aebSAnirudh Venkataramanan if (status) 4730e674aebSAnirudh Venkataramanan goto err_setup_rx_ring; 4740e674aebSAnirudh Venkataramanan 4750e674aebSAnirudh Venkataramanan status = ice_vsi_start_rx_rings(vsi); 4760e674aebSAnirudh Venkataramanan if (status) 4770e674aebSAnirudh Venkataramanan goto err_start_rx_ring; 4780e674aebSAnirudh Venkataramanan 4790e674aebSAnirudh Venkataramanan return status; 4800e674aebSAnirudh Venkataramanan 4810e674aebSAnirudh Venkataramanan err_start_rx_ring: 4820e674aebSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 4830e674aebSAnirudh Venkataramanan err_setup_rx_ring: 4840e674aebSAnirudh Venkataramanan ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); 4850e674aebSAnirudh Venkataramanan err_setup_tx_ring: 4860e674aebSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 4870e674aebSAnirudh Venkataramanan 4880e674aebSAnirudh Venkataramanan return status; 4890e674aebSAnirudh Venkataramanan } 4900e674aebSAnirudh Venkataramanan 4910e674aebSAnirudh Venkataramanan /** 4920e674aebSAnirudh Venkataramanan * ice_lbtest_disable_rings - disable Tx/Rx test rings after loopback test 4930e674aebSAnirudh Venkataramanan * @vsi: pointer to the VSI structure 4940e674aebSAnirudh Venkataramanan * 4950e674aebSAnirudh Venkataramanan * Function stops and frees VSI rings after a loopback test. 4960e674aebSAnirudh Venkataramanan * Returns 0 on success, negative on failure. 4970e674aebSAnirudh Venkataramanan */ 4980e674aebSAnirudh Venkataramanan static int ice_lbtest_disable_rings(struct ice_vsi *vsi) 4990e674aebSAnirudh Venkataramanan { 5000e674aebSAnirudh Venkataramanan int status; 5010e674aebSAnirudh Venkataramanan 5020e674aebSAnirudh Venkataramanan status = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); 5030e674aebSAnirudh Venkataramanan if (status) 5040e674aebSAnirudh Venkataramanan netdev_err(vsi->netdev, "Failed to stop Tx rings, VSI %d error %d\n", 5050e674aebSAnirudh Venkataramanan vsi->vsi_num, status); 5060e674aebSAnirudh Venkataramanan 5070e674aebSAnirudh Venkataramanan status = ice_vsi_stop_rx_rings(vsi); 5080e674aebSAnirudh Venkataramanan if (status) 5090e674aebSAnirudh Venkataramanan netdev_err(vsi->netdev, "Failed to stop Rx rings, VSI %d error %d\n", 5100e674aebSAnirudh Venkataramanan vsi->vsi_num, status); 5110e674aebSAnirudh Venkataramanan 5120e674aebSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 5130e674aebSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 5140e674aebSAnirudh Venkataramanan 5150e674aebSAnirudh Venkataramanan return status; 5160e674aebSAnirudh Venkataramanan } 5170e674aebSAnirudh Venkataramanan 5180e674aebSAnirudh Venkataramanan /** 5190e674aebSAnirudh Venkataramanan * ice_lbtest_create_frame - create test packet 5200e674aebSAnirudh Venkataramanan * @pf: pointer to the PF structure 5210e674aebSAnirudh Venkataramanan * @ret_data: allocated frame buffer 5220e674aebSAnirudh Venkataramanan * @size: size of the packet data 5230e674aebSAnirudh Venkataramanan * 5240e674aebSAnirudh Venkataramanan * Function allocates a frame with a test pattern on specific offsets. 5250e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 5260e674aebSAnirudh Venkataramanan */ 5270e674aebSAnirudh Venkataramanan static int ice_lbtest_create_frame(struct ice_pf *pf, u8 **ret_data, u16 size) 5280e674aebSAnirudh Venkataramanan { 5290e674aebSAnirudh Venkataramanan u8 *data; 5300e674aebSAnirudh Venkataramanan 5310e674aebSAnirudh Venkataramanan if (!pf) 5320e674aebSAnirudh Venkataramanan return -EINVAL; 5330e674aebSAnirudh Venkataramanan 5340e674aebSAnirudh Venkataramanan data = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL); 5350e674aebSAnirudh Venkataramanan if (!data) 5360e674aebSAnirudh Venkataramanan return -ENOMEM; 5370e674aebSAnirudh Venkataramanan 5380e674aebSAnirudh Venkataramanan /* Since the ethernet test frame should always be at least 5390e674aebSAnirudh Venkataramanan * 64 bytes long, fill some octets in the payload with test data. 5400e674aebSAnirudh Venkataramanan */ 5410e674aebSAnirudh Venkataramanan memset(data, 0xFF, size); 5420e674aebSAnirudh Venkataramanan data[32] = 0xDE; 5430e674aebSAnirudh Venkataramanan data[42] = 0xAD; 5440e674aebSAnirudh Venkataramanan data[44] = 0xBE; 5450e674aebSAnirudh Venkataramanan data[46] = 0xEF; 5460e674aebSAnirudh Venkataramanan 5470e674aebSAnirudh Venkataramanan *ret_data = data; 5480e674aebSAnirudh Venkataramanan 5490e674aebSAnirudh Venkataramanan return 0; 5500e674aebSAnirudh Venkataramanan } 5510e674aebSAnirudh Venkataramanan 5520e674aebSAnirudh Venkataramanan /** 5530e674aebSAnirudh Venkataramanan * ice_lbtest_check_frame - verify received loopback frame 5540e674aebSAnirudh Venkataramanan * @frame: pointer to the raw packet data 5550e674aebSAnirudh Venkataramanan * 5560e674aebSAnirudh Venkataramanan * Function verifies received test frame with a pattern. 5570e674aebSAnirudh Venkataramanan * Returns true if frame matches the pattern, false otherwise. 5580e674aebSAnirudh Venkataramanan */ 5590e674aebSAnirudh Venkataramanan static bool ice_lbtest_check_frame(u8 *frame) 5600e674aebSAnirudh Venkataramanan { 5610e674aebSAnirudh Venkataramanan /* Validate bytes of a frame under offsets chosen earlier */ 5620e674aebSAnirudh Venkataramanan if (frame[32] == 0xDE && 5630e674aebSAnirudh Venkataramanan frame[42] == 0xAD && 5640e674aebSAnirudh Venkataramanan frame[44] == 0xBE && 5650e674aebSAnirudh Venkataramanan frame[46] == 0xEF && 5660e674aebSAnirudh Venkataramanan frame[48] == 0xFF) 5670e674aebSAnirudh Venkataramanan return true; 5680e674aebSAnirudh Venkataramanan 5690e674aebSAnirudh Venkataramanan return false; 5700e674aebSAnirudh Venkataramanan } 5710e674aebSAnirudh Venkataramanan 5720e674aebSAnirudh Venkataramanan /** 5730e674aebSAnirudh Venkataramanan * ice_diag_send - send test frames to the test ring 5740e674aebSAnirudh Venkataramanan * @tx_ring: pointer to the transmit ring 5750e674aebSAnirudh Venkataramanan * @data: pointer to the raw packet data 5760e674aebSAnirudh Venkataramanan * @size: size of the packet to send 5770e674aebSAnirudh Venkataramanan * 5780e674aebSAnirudh Venkataramanan * Function sends loopback packets on a test Tx ring. 5790e674aebSAnirudh Venkataramanan */ 5800e674aebSAnirudh Venkataramanan static int ice_diag_send(struct ice_ring *tx_ring, u8 *data, u16 size) 5810e674aebSAnirudh Venkataramanan { 5820e674aebSAnirudh Venkataramanan struct ice_tx_desc *tx_desc; 5830e674aebSAnirudh Venkataramanan struct ice_tx_buf *tx_buf; 5840e674aebSAnirudh Venkataramanan dma_addr_t dma; 5850e674aebSAnirudh Venkataramanan u64 td_cmd; 5860e674aebSAnirudh Venkataramanan 5870e674aebSAnirudh Venkataramanan tx_desc = ICE_TX_DESC(tx_ring, tx_ring->next_to_use); 5880e674aebSAnirudh Venkataramanan tx_buf = &tx_ring->tx_buf[tx_ring->next_to_use]; 5890e674aebSAnirudh Venkataramanan 5900e674aebSAnirudh Venkataramanan dma = dma_map_single(tx_ring->dev, data, size, DMA_TO_DEVICE); 5910e674aebSAnirudh Venkataramanan if (dma_mapping_error(tx_ring->dev, dma)) 5920e674aebSAnirudh Venkataramanan return -EINVAL; 5930e674aebSAnirudh Venkataramanan 5940e674aebSAnirudh Venkataramanan tx_desc->buf_addr = cpu_to_le64(dma); 5950e674aebSAnirudh Venkataramanan 5960e674aebSAnirudh Venkataramanan /* These flags are required for a descriptor to be pushed out */ 5970e674aebSAnirudh Venkataramanan td_cmd = (u64)(ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS); 5980e674aebSAnirudh Venkataramanan tx_desc->cmd_type_offset_bsz = 5990e674aebSAnirudh Venkataramanan cpu_to_le64(ICE_TX_DESC_DTYPE_DATA | 6000e674aebSAnirudh Venkataramanan (td_cmd << ICE_TXD_QW1_CMD_S) | 6010e674aebSAnirudh Venkataramanan ((u64)0 << ICE_TXD_QW1_OFFSET_S) | 6020e674aebSAnirudh Venkataramanan ((u64)size << ICE_TXD_QW1_TX_BUF_SZ_S) | 6030e674aebSAnirudh Venkataramanan ((u64)0 << ICE_TXD_QW1_L2TAG1_S)); 6040e674aebSAnirudh Venkataramanan 6050e674aebSAnirudh Venkataramanan tx_buf->next_to_watch = tx_desc; 6060e674aebSAnirudh Venkataramanan 6070e674aebSAnirudh Venkataramanan /* Force memory write to complete before letting h/w know 6080e674aebSAnirudh Venkataramanan * there are new descriptors to fetch. 6090e674aebSAnirudh Venkataramanan */ 6100e674aebSAnirudh Venkataramanan wmb(); 6110e674aebSAnirudh Venkataramanan 6120e674aebSAnirudh Venkataramanan tx_ring->next_to_use++; 6130e674aebSAnirudh Venkataramanan if (tx_ring->next_to_use >= tx_ring->count) 6140e674aebSAnirudh Venkataramanan tx_ring->next_to_use = 0; 6150e674aebSAnirudh Venkataramanan 6160e674aebSAnirudh Venkataramanan writel_relaxed(tx_ring->next_to_use, tx_ring->tail); 6170e674aebSAnirudh Venkataramanan 6180e674aebSAnirudh Venkataramanan /* Wait until the packets get transmitted to the receive queue. */ 6190e674aebSAnirudh Venkataramanan usleep_range(1000, 2000); 6200e674aebSAnirudh Venkataramanan dma_unmap_single(tx_ring->dev, dma, size, DMA_TO_DEVICE); 6210e674aebSAnirudh Venkataramanan 6220e674aebSAnirudh Venkataramanan return 0; 6230e674aebSAnirudh Venkataramanan } 6240e674aebSAnirudh Venkataramanan 6250e674aebSAnirudh Venkataramanan #define ICE_LB_FRAME_SIZE 64 6260e674aebSAnirudh Venkataramanan /** 6270e674aebSAnirudh Venkataramanan * ice_lbtest_receive_frames - receive and verify test frames 6280e674aebSAnirudh Venkataramanan * @rx_ring: pointer to the receive ring 6290e674aebSAnirudh Venkataramanan * 6300e674aebSAnirudh Venkataramanan * Function receives loopback packets and verify their correctness. 6310e674aebSAnirudh Venkataramanan * Returns number of received valid frames. 6320e674aebSAnirudh Venkataramanan */ 6330e674aebSAnirudh Venkataramanan static int ice_lbtest_receive_frames(struct ice_ring *rx_ring) 6340e674aebSAnirudh Venkataramanan { 6350e674aebSAnirudh Venkataramanan struct ice_rx_buf *rx_buf; 6360e674aebSAnirudh Venkataramanan int valid_frames, i; 6370e674aebSAnirudh Venkataramanan u8 *received_buf; 6380e674aebSAnirudh Venkataramanan 6390e674aebSAnirudh Venkataramanan valid_frames = 0; 6400e674aebSAnirudh Venkataramanan 6410e674aebSAnirudh Venkataramanan for (i = 0; i < rx_ring->count; i++) { 6420e674aebSAnirudh Venkataramanan union ice_32b_rx_flex_desc *rx_desc; 6430e674aebSAnirudh Venkataramanan 6440e674aebSAnirudh Venkataramanan rx_desc = ICE_RX_DESC(rx_ring, i); 6450e674aebSAnirudh Venkataramanan 6460e674aebSAnirudh Venkataramanan if (!(rx_desc->wb.status_error0 & 6470e674aebSAnirudh Venkataramanan cpu_to_le16(ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS))) 6480e674aebSAnirudh Venkataramanan continue; 6490e674aebSAnirudh Venkataramanan 6500e674aebSAnirudh Venkataramanan rx_buf = &rx_ring->rx_buf[i]; 6510e674aebSAnirudh Venkataramanan received_buf = page_address(rx_buf->page); 6520e674aebSAnirudh Venkataramanan 6530e674aebSAnirudh Venkataramanan if (ice_lbtest_check_frame(received_buf)) 6540e674aebSAnirudh Venkataramanan valid_frames++; 6550e674aebSAnirudh Venkataramanan } 6560e674aebSAnirudh Venkataramanan 6570e674aebSAnirudh Venkataramanan return valid_frames; 6580e674aebSAnirudh Venkataramanan } 6590e674aebSAnirudh Venkataramanan 6600e674aebSAnirudh Venkataramanan /** 6610e674aebSAnirudh Venkataramanan * ice_loopback_test - perform a loopback test on a given net_device 6620e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 6630e674aebSAnirudh Venkataramanan * 6640e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 6650e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 6660e674aebSAnirudh Venkataramanan */ 6670e674aebSAnirudh Venkataramanan static u64 ice_loopback_test(struct net_device *netdev) 6680e674aebSAnirudh Venkataramanan { 6690e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 6700e674aebSAnirudh Venkataramanan struct ice_vsi *orig_vsi = np->vsi, *test_vsi; 6710e674aebSAnirudh Venkataramanan struct ice_pf *pf = orig_vsi->back; 6720e674aebSAnirudh Venkataramanan struct ice_ring *tx_ring, *rx_ring; 6730e674aebSAnirudh Venkataramanan u8 broadcast[ETH_ALEN], ret = 0; 6740e674aebSAnirudh Venkataramanan int num_frames, valid_frames; 6750e674aebSAnirudh Venkataramanan LIST_HEAD(tmp_list); 6760e674aebSAnirudh Venkataramanan u8 *tx_frame; 6770e674aebSAnirudh Venkataramanan int i; 6780e674aebSAnirudh Venkataramanan 6790e674aebSAnirudh Venkataramanan netdev_info(netdev, "loopback test\n"); 6800e674aebSAnirudh Venkataramanan 6810e674aebSAnirudh Venkataramanan test_vsi = ice_lb_vsi_setup(pf, pf->hw.port_info); 6820e674aebSAnirudh Venkataramanan if (!test_vsi) { 6830e674aebSAnirudh Venkataramanan netdev_err(netdev, "Failed to create a VSI for the loopback test"); 6840e674aebSAnirudh Venkataramanan return 1; 6850e674aebSAnirudh Venkataramanan } 6860e674aebSAnirudh Venkataramanan 6870e674aebSAnirudh Venkataramanan test_vsi->netdev = netdev; 6880e674aebSAnirudh Venkataramanan tx_ring = test_vsi->tx_rings[0]; 6890e674aebSAnirudh Venkataramanan rx_ring = test_vsi->rx_rings[0]; 6900e674aebSAnirudh Venkataramanan 6910e674aebSAnirudh Venkataramanan if (ice_lbtest_prepare_rings(test_vsi)) { 6920e674aebSAnirudh Venkataramanan ret = 2; 6930e674aebSAnirudh Venkataramanan goto lbtest_vsi_close; 6940e674aebSAnirudh Venkataramanan } 6950e674aebSAnirudh Venkataramanan 6960e674aebSAnirudh Venkataramanan if (ice_alloc_rx_bufs(rx_ring, rx_ring->count)) { 6970e674aebSAnirudh Venkataramanan ret = 3; 6980e674aebSAnirudh Venkataramanan goto lbtest_rings_dis; 6990e674aebSAnirudh Venkataramanan } 7000e674aebSAnirudh Venkataramanan 7010e674aebSAnirudh Venkataramanan /* Enable MAC loopback in firmware */ 7020e674aebSAnirudh Venkataramanan if (ice_aq_set_mac_loopback(&pf->hw, true, NULL)) { 7030e674aebSAnirudh Venkataramanan ret = 4; 7040e674aebSAnirudh Venkataramanan goto lbtest_mac_dis; 7050e674aebSAnirudh Venkataramanan } 7060e674aebSAnirudh Venkataramanan 7070e674aebSAnirudh Venkataramanan /* Test VSI needs to receive broadcast packets */ 7080e674aebSAnirudh Venkataramanan eth_broadcast_addr(broadcast); 7090e674aebSAnirudh Venkataramanan if (ice_add_mac_to_list(test_vsi, &tmp_list, broadcast)) { 7100e674aebSAnirudh Venkataramanan ret = 5; 7110e674aebSAnirudh Venkataramanan goto lbtest_mac_dis; 7120e674aebSAnirudh Venkataramanan } 7130e674aebSAnirudh Venkataramanan 7140e674aebSAnirudh Venkataramanan if (ice_add_mac(&pf->hw, &tmp_list)) { 7150e674aebSAnirudh Venkataramanan ret = 6; 7160e674aebSAnirudh Venkataramanan goto free_mac_list; 7170e674aebSAnirudh Venkataramanan } 7180e674aebSAnirudh Venkataramanan 7190e674aebSAnirudh Venkataramanan if (ice_lbtest_create_frame(pf, &tx_frame, ICE_LB_FRAME_SIZE)) { 7200e674aebSAnirudh Venkataramanan ret = 7; 7210e674aebSAnirudh Venkataramanan goto remove_mac_filters; 7220e674aebSAnirudh Venkataramanan } 7230e674aebSAnirudh Venkataramanan 7240e674aebSAnirudh Venkataramanan num_frames = min_t(int, tx_ring->count, 32); 7250e674aebSAnirudh Venkataramanan for (i = 0; i < num_frames; i++) { 7260e674aebSAnirudh Venkataramanan if (ice_diag_send(tx_ring, tx_frame, ICE_LB_FRAME_SIZE)) { 7270e674aebSAnirudh Venkataramanan ret = 8; 7280e674aebSAnirudh Venkataramanan goto lbtest_free_frame; 7290e674aebSAnirudh Venkataramanan } 7300e674aebSAnirudh Venkataramanan } 7310e674aebSAnirudh Venkataramanan 7320e674aebSAnirudh Venkataramanan valid_frames = ice_lbtest_receive_frames(rx_ring); 7330e674aebSAnirudh Venkataramanan if (!valid_frames) 7340e674aebSAnirudh Venkataramanan ret = 9; 7350e674aebSAnirudh Venkataramanan else if (valid_frames != num_frames) 7360e674aebSAnirudh Venkataramanan ret = 10; 7370e674aebSAnirudh Venkataramanan 7380e674aebSAnirudh Venkataramanan lbtest_free_frame: 7390e674aebSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_frame); 7400e674aebSAnirudh Venkataramanan remove_mac_filters: 7410e674aebSAnirudh Venkataramanan if (ice_remove_mac(&pf->hw, &tmp_list)) 7420e674aebSAnirudh Venkataramanan netdev_err(netdev, "Could not remove MAC filter for the test VSI"); 7430e674aebSAnirudh Venkataramanan free_mac_list: 7440e674aebSAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_list); 7450e674aebSAnirudh Venkataramanan lbtest_mac_dis: 7460e674aebSAnirudh Venkataramanan /* Disable MAC loopback after the test is completed. */ 7470e674aebSAnirudh Venkataramanan if (ice_aq_set_mac_loopback(&pf->hw, false, NULL)) 7480e674aebSAnirudh Venkataramanan netdev_err(netdev, "Could not disable MAC loopback\n"); 7490e674aebSAnirudh Venkataramanan lbtest_rings_dis: 7500e674aebSAnirudh Venkataramanan if (ice_lbtest_disable_rings(test_vsi)) 7510e674aebSAnirudh Venkataramanan netdev_err(netdev, "Could not disable test rings\n"); 7520e674aebSAnirudh Venkataramanan lbtest_vsi_close: 7530e674aebSAnirudh Venkataramanan test_vsi->netdev = NULL; 7540e674aebSAnirudh Venkataramanan if (ice_vsi_release(test_vsi)) 7550e674aebSAnirudh Venkataramanan netdev_err(netdev, "Failed to remove the test VSI"); 7560e674aebSAnirudh Venkataramanan 7570e674aebSAnirudh Venkataramanan return ret; 7580e674aebSAnirudh Venkataramanan } 7590e674aebSAnirudh Venkataramanan 7600e674aebSAnirudh Venkataramanan /** 7610e674aebSAnirudh Venkataramanan * ice_intr_test - perform an interrupt test on a given net_device 7620e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 7630e674aebSAnirudh Venkataramanan * 7640e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 7650e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 7660e674aebSAnirudh Venkataramanan */ 7670e674aebSAnirudh Venkataramanan static u64 ice_intr_test(struct net_device *netdev) 7680e674aebSAnirudh Venkataramanan { 7690e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 7700e674aebSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 7710e674aebSAnirudh Venkataramanan u16 swic_old = pf->sw_int_count; 7720e674aebSAnirudh Venkataramanan 7730e674aebSAnirudh Venkataramanan netdev_info(netdev, "interrupt test\n"); 7740e674aebSAnirudh Venkataramanan 775cbe66bfeSBrett Creeley wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_idx), 7760e674aebSAnirudh Venkataramanan GLINT_DYN_CTL_SW_ITR_INDX_M | 7770e674aebSAnirudh Venkataramanan GLINT_DYN_CTL_INTENA_MSK_M | 7780e674aebSAnirudh Venkataramanan GLINT_DYN_CTL_SWINT_TRIG_M); 7790e674aebSAnirudh Venkataramanan 7800e674aebSAnirudh Venkataramanan usleep_range(1000, 2000); 7810e674aebSAnirudh Venkataramanan return (swic_old == pf->sw_int_count); 7820e674aebSAnirudh Venkataramanan } 7830e674aebSAnirudh Venkataramanan 7840e674aebSAnirudh Venkataramanan /** 7850e674aebSAnirudh Venkataramanan * ice_self_test - handler function for performing a self-test by ethtool 7860e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 7870e674aebSAnirudh Venkataramanan * @eth_test: ethtool_test structure 7880e674aebSAnirudh Venkataramanan * @data: required by ethtool.self_test 7890e674aebSAnirudh Venkataramanan * 7900e674aebSAnirudh Venkataramanan * This function is called after invoking 'ethtool -t devname' command where 7910e674aebSAnirudh Venkataramanan * devname is the name of the network device on which ethtool should operate. 7920e674aebSAnirudh Venkataramanan * It performs a set of self-tests to check if a device works properly. 7930e674aebSAnirudh Venkataramanan */ 7940e674aebSAnirudh Venkataramanan static void 7950e674aebSAnirudh Venkataramanan ice_self_test(struct net_device *netdev, struct ethtool_test *eth_test, 7960e674aebSAnirudh Venkataramanan u64 *data) 7970e674aebSAnirudh Venkataramanan { 7980e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 7990e674aebSAnirudh Venkataramanan bool if_running = netif_running(netdev); 8000e674aebSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 8010e674aebSAnirudh Venkataramanan 8020e674aebSAnirudh Venkataramanan if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 8030e674aebSAnirudh Venkataramanan netdev_info(netdev, "offline testing starting\n"); 8040e674aebSAnirudh Venkataramanan 8050e674aebSAnirudh Venkataramanan set_bit(__ICE_TESTING, pf->state); 8060e674aebSAnirudh Venkataramanan 8070e674aebSAnirudh Venkataramanan if (ice_active_vfs(pf)) { 8080e674aebSAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 8090e674aebSAnirudh Venkataramanan "Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\n"); 8100e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG] = 1; 8110e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] = 1; 8120e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] = 1; 8130e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] = 1; 8140e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LINK] = 1; 8150e674aebSAnirudh Venkataramanan eth_test->flags |= ETH_TEST_FL_FAILED; 8160e674aebSAnirudh Venkataramanan clear_bit(__ICE_TESTING, pf->state); 8170e674aebSAnirudh Venkataramanan goto skip_ol_tests; 8180e674aebSAnirudh Venkataramanan } 8190e674aebSAnirudh Venkataramanan /* If the device is online then take it offline */ 8200e674aebSAnirudh Venkataramanan if (if_running) 8210e674aebSAnirudh Venkataramanan /* indicate we're in test mode */ 8220e674aebSAnirudh Venkataramanan ice_stop(netdev); 8230e674aebSAnirudh Venkataramanan 8240e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LINK] = ice_link_test(netdev); 8250e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] = ice_eeprom_test(netdev); 8260e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] = ice_intr_test(netdev); 8270e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] = ice_loopback_test(netdev); 8280e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG] = ice_reg_test(netdev); 8290e674aebSAnirudh Venkataramanan 8300e674aebSAnirudh Venkataramanan if (data[ICE_ETH_TEST_LINK] || 8310e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] || 8320e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] || 8330e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] || 8340e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG]) 8350e674aebSAnirudh Venkataramanan eth_test->flags |= ETH_TEST_FL_FAILED; 8360e674aebSAnirudh Venkataramanan 8370e674aebSAnirudh Venkataramanan clear_bit(__ICE_TESTING, pf->state); 8380e674aebSAnirudh Venkataramanan 8390e674aebSAnirudh Venkataramanan if (if_running) { 8400e674aebSAnirudh Venkataramanan int status = ice_open(netdev); 8410e674aebSAnirudh Venkataramanan 8420e674aebSAnirudh Venkataramanan if (status) { 8430e674aebSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 8440e674aebSAnirudh Venkataramanan "Could not open device %s, err %d", 8450e674aebSAnirudh Venkataramanan pf->int_name, status); 8460e674aebSAnirudh Venkataramanan } 8470e674aebSAnirudh Venkataramanan } 8480e674aebSAnirudh Venkataramanan } else { 8490e674aebSAnirudh Venkataramanan /* Online tests */ 8500e674aebSAnirudh Venkataramanan netdev_info(netdev, "online testing starting\n"); 8510e674aebSAnirudh Venkataramanan 8520e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LINK] = ice_link_test(netdev); 8530e674aebSAnirudh Venkataramanan if (data[ICE_ETH_TEST_LINK]) 8540e674aebSAnirudh Venkataramanan eth_test->flags |= ETH_TEST_FL_FAILED; 8550e674aebSAnirudh Venkataramanan 8560e674aebSAnirudh Venkataramanan /* Offline only tests, not run in online; pass by default */ 8570e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG] = 0; 8580e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] = 0; 8590e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] = 0; 8600e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] = 0; 8610e674aebSAnirudh Venkataramanan } 8620e674aebSAnirudh Venkataramanan 8630e674aebSAnirudh Venkataramanan skip_ol_tests: 8640e674aebSAnirudh Venkataramanan netdev_info(netdev, "testing finished\n"); 8650e674aebSAnirudh Venkataramanan } 8660e674aebSAnirudh Venkataramanan 867fcea6f3dSAnirudh Venkataramanan static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) 868fcea6f3dSAnirudh Venkataramanan { 869fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 870fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 871fcea6f3dSAnirudh Venkataramanan char *p = (char *)data; 872fcea6f3dSAnirudh Venkataramanan unsigned int i; 873fcea6f3dSAnirudh Venkataramanan 874fcea6f3dSAnirudh Venkataramanan switch (stringset) { 875fcea6f3dSAnirudh Venkataramanan case ETH_SS_STATS: 876fcea6f3dSAnirudh Venkataramanan for (i = 0; i < ICE_VSI_STATS_LEN; i++) { 877fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, "%s", 878fcea6f3dSAnirudh Venkataramanan ice_gstrings_vsi_stats[i].stat_string); 879fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 880fcea6f3dSAnirudh Venkataramanan } 881fcea6f3dSAnirudh Venkataramanan 882f8ba7db8SJacob Keller ice_for_each_alloc_txq(vsi, i) { 883fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 88455e062baSRichard Rodriguez "tx_queue_%u_packets", i); 885fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 88655e062baSRichard Rodriguez snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i); 887fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 888fcea6f3dSAnirudh Venkataramanan } 889fcea6f3dSAnirudh Venkataramanan 890f8ba7db8SJacob Keller ice_for_each_alloc_rxq(vsi, i) { 891fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 89255e062baSRichard Rodriguez "rx_queue_%u_packets", i); 893fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 89455e062baSRichard Rodriguez snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i); 895fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 896fcea6f3dSAnirudh Venkataramanan } 897fcea6f3dSAnirudh Venkataramanan 898fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 899fcea6f3dSAnirudh Venkataramanan return; 900fcea6f3dSAnirudh Venkataramanan 901fcea6f3dSAnirudh Venkataramanan for (i = 0; i < ICE_PF_STATS_LEN; i++) { 9021fa6e138SJesse Brandeburg snprintf(p, ETH_GSTRING_LEN, "%s", 903fcea6f3dSAnirudh Venkataramanan ice_gstrings_pf_stats[i].stat_string); 904fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 905fcea6f3dSAnirudh Venkataramanan } 906fcea6f3dSAnirudh Venkataramanan 9074b0fdcebSAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 9084b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 90955e062baSRichard Rodriguez "tx_priority_%u_xon.nic", i); 9104b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9114b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 91255e062baSRichard Rodriguez "tx_priority_%u_xoff.nic", i); 9134b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9144b0fdcebSAnirudh Venkataramanan } 9154b0fdcebSAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 9164b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 91755e062baSRichard Rodriguez "rx_priority_%u_xon.nic", i); 9184b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9194b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 92055e062baSRichard Rodriguez "rx_priority_%u_xoff.nic", i); 9214b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9224b0fdcebSAnirudh Venkataramanan } 923fcea6f3dSAnirudh Venkataramanan break; 9240e674aebSAnirudh Venkataramanan case ETH_SS_TEST: 9250e674aebSAnirudh Venkataramanan memcpy(data, ice_gstrings_test, ICE_TEST_LEN * ETH_GSTRING_LEN); 9260e674aebSAnirudh Venkataramanan break; 927ab4ab73fSBruce Allan case ETH_SS_PRIV_FLAGS: 928ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 929ab4ab73fSBruce Allan snprintf(p, ETH_GSTRING_LEN, "%s", 930ab4ab73fSBruce Allan ice_gstrings_priv_flags[i].name); 931ab4ab73fSBruce Allan p += ETH_GSTRING_LEN; 932ab4ab73fSBruce Allan } 933ab4ab73fSBruce Allan break; 934fcea6f3dSAnirudh Venkataramanan default: 935fcea6f3dSAnirudh Venkataramanan break; 936fcea6f3dSAnirudh Venkataramanan } 937fcea6f3dSAnirudh Venkataramanan } 938fcea6f3dSAnirudh Venkataramanan 9398e151d50SAnirudh Venkataramanan static int 9408e151d50SAnirudh Venkataramanan ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) 9418e151d50SAnirudh Venkataramanan { 9428e151d50SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 9438e151d50SAnirudh Venkataramanan bool led_active; 9448e151d50SAnirudh Venkataramanan 9458e151d50SAnirudh Venkataramanan switch (state) { 9468e151d50SAnirudh Venkataramanan case ETHTOOL_ID_ACTIVE: 9478e151d50SAnirudh Venkataramanan led_active = true; 9488e151d50SAnirudh Venkataramanan break; 9498e151d50SAnirudh Venkataramanan case ETHTOOL_ID_INACTIVE: 9508e151d50SAnirudh Venkataramanan led_active = false; 9518e151d50SAnirudh Venkataramanan break; 9528e151d50SAnirudh Venkataramanan default: 9538e151d50SAnirudh Venkataramanan return -EINVAL; 9548e151d50SAnirudh Venkataramanan } 9558e151d50SAnirudh Venkataramanan 9568e151d50SAnirudh Venkataramanan if (ice_aq_set_port_id_led(np->vsi->port_info, !led_active, NULL)) 9578e151d50SAnirudh Venkataramanan return -EIO; 9588e151d50SAnirudh Venkataramanan 9598e151d50SAnirudh Venkataramanan return 0; 9608e151d50SAnirudh Venkataramanan } 9618e151d50SAnirudh Venkataramanan 962ab4ab73fSBruce Allan /** 963ab4ab73fSBruce Allan * ice_get_priv_flags - report device private flags 964ab4ab73fSBruce Allan * @netdev: network interface device structure 965ab4ab73fSBruce Allan * 966ab4ab73fSBruce Allan * The get string set count and the string set should be matched for each 967ab4ab73fSBruce Allan * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags 968ab4ab73fSBruce Allan * array. 969ab4ab73fSBruce Allan * 970ab4ab73fSBruce Allan * Returns a u32 bitmap of flags. 971ab4ab73fSBruce Allan */ 972ab4ab73fSBruce Allan static u32 ice_get_priv_flags(struct net_device *netdev) 973ab4ab73fSBruce Allan { 974ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 975ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 976ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 977ab4ab73fSBruce Allan u32 i, ret_flags = 0; 978ab4ab73fSBruce Allan 979ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 980ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 981ab4ab73fSBruce Allan 982ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 983ab4ab73fSBruce Allan 984ab4ab73fSBruce Allan if (test_bit(priv_flag->bitno, pf->flags)) 985ab4ab73fSBruce Allan ret_flags |= BIT(i); 986ab4ab73fSBruce Allan } 987ab4ab73fSBruce Allan 988ab4ab73fSBruce Allan return ret_flags; 989ab4ab73fSBruce Allan } 990ab4ab73fSBruce Allan 991ab4ab73fSBruce Allan /** 992ab4ab73fSBruce Allan * ice_set_priv_flags - set private flags 993ab4ab73fSBruce Allan * @netdev: network interface device structure 994ab4ab73fSBruce Allan * @flags: bit flags to be set 995ab4ab73fSBruce Allan */ 996ab4ab73fSBruce Allan static int ice_set_priv_flags(struct net_device *netdev, u32 flags) 997ab4ab73fSBruce Allan { 998ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 9993a257a14SAnirudh Venkataramanan DECLARE_BITMAP(change_flags, ICE_PF_FLAGS_NBITS); 10003a257a14SAnirudh Venkataramanan DECLARE_BITMAP(orig_flags, ICE_PF_FLAGS_NBITS); 1001ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 1002ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 10033a257a14SAnirudh Venkataramanan int ret = 0; 1004ab4ab73fSBruce Allan u32 i; 1005ab4ab73fSBruce Allan 1006ab4ab73fSBruce Allan if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE)) 1007ab4ab73fSBruce Allan return -EINVAL; 1008ab4ab73fSBruce Allan 10093a257a14SAnirudh Venkataramanan set_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 10103a257a14SAnirudh Venkataramanan 10113a257a14SAnirudh Venkataramanan bitmap_copy(orig_flags, pf->flags, ICE_PF_FLAGS_NBITS); 1012ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 1013ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 1014ab4ab73fSBruce Allan 1015ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 1016ab4ab73fSBruce Allan 1017ab4ab73fSBruce Allan if (flags & BIT(i)) 1018ab4ab73fSBruce Allan set_bit(priv_flag->bitno, pf->flags); 1019ab4ab73fSBruce Allan else 1020ab4ab73fSBruce Allan clear_bit(priv_flag->bitno, pf->flags); 1021ab4ab73fSBruce Allan } 1022ab4ab73fSBruce Allan 10233a257a14SAnirudh Venkataramanan bitmap_xor(change_flags, pf->flags, orig_flags, ICE_PF_FLAGS_NBITS); 10243a257a14SAnirudh Venkataramanan 102531eafa40SAnirudh Venkataramanan if (test_bit(ICE_FLAG_ENABLE_FW_LLDP, change_flags)) { 102631eafa40SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags)) { 10273a257a14SAnirudh Venkataramanan enum ice_status status; 10283a257a14SAnirudh Venkataramanan 10293a257a14SAnirudh Venkataramanan status = ice_aq_cfg_lldp_mib_change(&pf->hw, false, 10303a257a14SAnirudh Venkataramanan NULL); 10313a257a14SAnirudh Venkataramanan /* If unregistering for LLDP events fails, this is 10323a257a14SAnirudh Venkataramanan * not an error state, as there shouldn't be any 10333a257a14SAnirudh Venkataramanan * events to respond to. 10343a257a14SAnirudh Venkataramanan */ 10353a257a14SAnirudh Venkataramanan if (status) 10363a257a14SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 10373a257a14SAnirudh Venkataramanan "Failed to unreg for LLDP events\n"); 10383a257a14SAnirudh Venkataramanan 10393a257a14SAnirudh Venkataramanan /* The AQ call to stop the FW LLDP agent will generate 10403a257a14SAnirudh Venkataramanan * an error if the agent is already stopped. 10413a257a14SAnirudh Venkataramanan */ 104231eafa40SAnirudh Venkataramanan status = ice_aq_stop_lldp(&pf->hw, true, true, NULL); 10433a257a14SAnirudh Venkataramanan if (status) 10443a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 10453a257a14SAnirudh Venkataramanan "Fail to stop LLDP agent\n"); 10463a257a14SAnirudh Venkataramanan /* Use case for having the FW LLDP agent stopped 10473a257a14SAnirudh Venkataramanan * will likely not need DCB, so failure to init is 10483a257a14SAnirudh Venkataramanan * not a concern of ethtool 10493a257a14SAnirudh Venkataramanan */ 1050e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 10513a257a14SAnirudh Venkataramanan if (status) 10523a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Fail to init DCB\n"); 10533a257a14SAnirudh Venkataramanan } else { 10543a257a14SAnirudh Venkataramanan enum ice_status status; 10553a257a14SAnirudh Venkataramanan bool dcbx_agent_status; 10563a257a14SAnirudh Venkataramanan 10573a257a14SAnirudh Venkataramanan /* AQ command to start FW LLDP agent will return an 10583a257a14SAnirudh Venkataramanan * error if the agent is already started 10593a257a14SAnirudh Venkataramanan */ 106031eafa40SAnirudh Venkataramanan status = ice_aq_start_lldp(&pf->hw, true, NULL); 10613a257a14SAnirudh Venkataramanan if (status) 10623a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 10633a257a14SAnirudh Venkataramanan "Fail to start LLDP Agent\n"); 10643a257a14SAnirudh Venkataramanan 10653a257a14SAnirudh Venkataramanan /* AQ command to start FW DCBx agent will fail if 10663a257a14SAnirudh Venkataramanan * the agent is already started 10673a257a14SAnirudh Venkataramanan */ 10683a257a14SAnirudh Venkataramanan status = ice_aq_start_stop_dcbx(&pf->hw, true, 10693a257a14SAnirudh Venkataramanan &dcbx_agent_status, 10703a257a14SAnirudh Venkataramanan NULL); 10713a257a14SAnirudh Venkataramanan if (status) 10723a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 10733a257a14SAnirudh Venkataramanan "Failed to start FW DCBX\n"); 10743a257a14SAnirudh Venkataramanan 10753a257a14SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "FW DCBX agent is %s\n", 10763a257a14SAnirudh Venkataramanan dcbx_agent_status ? "ACTIVE" : "DISABLED"); 10773a257a14SAnirudh Venkataramanan 10783a257a14SAnirudh Venkataramanan /* Failure to configure MIB change or init DCB is not 10793a257a14SAnirudh Venkataramanan * relevant to ethtool. Print notification that 10803a257a14SAnirudh Venkataramanan * registration/init failed but do not return error 10813a257a14SAnirudh Venkataramanan * state to ethtool 10823a257a14SAnirudh Venkataramanan */ 10833a257a14SAnirudh Venkataramanan status = ice_aq_cfg_lldp_mib_change(&pf->hw, false, 10843a257a14SAnirudh Venkataramanan NULL); 10853a257a14SAnirudh Venkataramanan if (status) 10863a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 10873a257a14SAnirudh Venkataramanan "Fail to reg for MIB change\n"); 10883a257a14SAnirudh Venkataramanan 1089e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 10903a257a14SAnirudh Venkataramanan if (status) 10913a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "Fail to init DCB\n"); 10923a257a14SAnirudh Venkataramanan } 10933a257a14SAnirudh Venkataramanan } 10943a257a14SAnirudh Venkataramanan clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 10953a257a14SAnirudh Venkataramanan return ret; 1096ab4ab73fSBruce Allan } 1097ab4ab73fSBruce Allan 1098fcea6f3dSAnirudh Venkataramanan static int ice_get_sset_count(struct net_device *netdev, int sset) 1099fcea6f3dSAnirudh Venkataramanan { 1100fcea6f3dSAnirudh Venkataramanan switch (sset) { 1101fcea6f3dSAnirudh Venkataramanan case ETH_SS_STATS: 1102f8ba7db8SJacob Keller /* The number (and order) of strings reported *must* remain 1103f8ba7db8SJacob Keller * constant for a given netdevice. This function must not 1104f8ba7db8SJacob Keller * report a different number based on run time parameters 1105f8ba7db8SJacob Keller * (such as the number of queues in use, or the setting of 1106f8ba7db8SJacob Keller * a private ethtool flag). This is due to the nature of the 1107f8ba7db8SJacob Keller * ethtool stats API. 1108f8ba7db8SJacob Keller * 1109f8ba7db8SJacob Keller * Userspace programs such as ethtool must make 3 separate 1110f8ba7db8SJacob Keller * ioctl requests, one for size, one for the strings, and 1111f8ba7db8SJacob Keller * finally one for the stats. Since these cross into 1112f8ba7db8SJacob Keller * userspace, changes to the number or size could result in 1113f8ba7db8SJacob Keller * undefined memory access or incorrect string<->value 1114f8ba7db8SJacob Keller * correlations for statistics. 1115f8ba7db8SJacob Keller * 1116f8ba7db8SJacob Keller * Even if it appears to be safe, changes to the size or 1117f8ba7db8SJacob Keller * order of strings will suffer from race conditions and are 1118f8ba7db8SJacob Keller * not safe. 1119f8ba7db8SJacob Keller */ 1120fcea6f3dSAnirudh Venkataramanan return ICE_ALL_STATS_LEN(netdev); 11210e674aebSAnirudh Venkataramanan case ETH_SS_TEST: 11220e674aebSAnirudh Venkataramanan return ICE_TEST_LEN; 1123ab4ab73fSBruce Allan case ETH_SS_PRIV_FLAGS: 1124ab4ab73fSBruce Allan return ICE_PRIV_FLAG_ARRAY_SIZE; 1125fcea6f3dSAnirudh Venkataramanan default: 1126fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 1127fcea6f3dSAnirudh Venkataramanan } 1128fcea6f3dSAnirudh Venkataramanan } 1129fcea6f3dSAnirudh Venkataramanan 1130fcea6f3dSAnirudh Venkataramanan static void 1131fcea6f3dSAnirudh Venkataramanan ice_get_ethtool_stats(struct net_device *netdev, 1132fcea6f3dSAnirudh Venkataramanan struct ethtool_stats __always_unused *stats, u64 *data) 1133fcea6f3dSAnirudh Venkataramanan { 1134fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1135fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1136fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1137fcea6f3dSAnirudh Venkataramanan struct ice_ring *ring; 1138fcea6f3dSAnirudh Venkataramanan unsigned int j = 0; 1139fcea6f3dSAnirudh Venkataramanan int i = 0; 1140fcea6f3dSAnirudh Venkataramanan char *p; 1141fcea6f3dSAnirudh Venkataramanan 1142fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_VSI_STATS_LEN; j++) { 1143fcea6f3dSAnirudh Venkataramanan p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; 1144fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == 1145fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 1146fcea6f3dSAnirudh Venkataramanan } 1147fcea6f3dSAnirudh Venkataramanan 1148fcea6f3dSAnirudh Venkataramanan /* populate per queue stats */ 1149fcea6f3dSAnirudh Venkataramanan rcu_read_lock(); 1150fcea6f3dSAnirudh Venkataramanan 1151f8ba7db8SJacob Keller ice_for_each_alloc_txq(vsi, j) { 1152fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->tx_rings[j]); 1153f8ba7db8SJacob Keller if (ring) { 1154fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 1155fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 1156f8ba7db8SJacob Keller } else { 1157f8ba7db8SJacob Keller data[i++] = 0; 1158f8ba7db8SJacob Keller data[i++] = 0; 1159f8ba7db8SJacob Keller } 1160fcea6f3dSAnirudh Venkataramanan } 1161fcea6f3dSAnirudh Venkataramanan 1162f8ba7db8SJacob Keller ice_for_each_alloc_rxq(vsi, j) { 1163fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->rx_rings[j]); 1164f8ba7db8SJacob Keller if (ring) { 1165fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 1166fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 1167f8ba7db8SJacob Keller } else { 1168f8ba7db8SJacob Keller data[i++] = 0; 1169f8ba7db8SJacob Keller data[i++] = 0; 1170f8ba7db8SJacob Keller } 1171fcea6f3dSAnirudh Venkataramanan } 1172fcea6f3dSAnirudh Venkataramanan 1173fcea6f3dSAnirudh Venkataramanan rcu_read_unlock(); 1174fcea6f3dSAnirudh Venkataramanan 1175fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 1176fcea6f3dSAnirudh Venkataramanan return; 1177fcea6f3dSAnirudh Venkataramanan 1178fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_PF_STATS_LEN; j++) { 1179fcea6f3dSAnirudh Venkataramanan p = (char *)pf + ice_gstrings_pf_stats[j].stat_offset; 1180fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_pf_stats[j].sizeof_stat == 1181fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 1182fcea6f3dSAnirudh Venkataramanan } 11834b0fdcebSAnirudh Venkataramanan 11844b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 11854b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_tx[j]; 11864b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_tx[j]; 11874b0fdcebSAnirudh Venkataramanan } 11884b0fdcebSAnirudh Venkataramanan 11894b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 11904b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_rx[j]; 11914b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_rx[j]; 11924b0fdcebSAnirudh Venkataramanan } 1193fcea6f3dSAnirudh Venkataramanan } 1194fcea6f3dSAnirudh Venkataramanan 119548cb27f2SChinh Cao /** 119648cb27f2SChinh Cao * ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes 119748cb27f2SChinh Cao * @netdev: network interface device structure 119848cb27f2SChinh Cao * @ks: ethtool link ksettings struct to fill out 119948cb27f2SChinh Cao */ 1200aef74145SAnirudh Venkataramanan static void 1201aef74145SAnirudh Venkataramanan ice_phy_type_to_ethtool(struct net_device *netdev, 1202fcea6f3dSAnirudh Venkataramanan struct ethtool_link_ksettings *ks) 1203fcea6f3dSAnirudh Venkataramanan { 1204fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1205fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 1206aef74145SAnirudh Venkataramanan bool need_add_adv_mode = false; 1207fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1208aef74145SAnirudh Venkataramanan u64 phy_types_high; 120948cb27f2SChinh Cao u64 phy_types_low; 1210fcea6f3dSAnirudh Venkataramanan 1211fcea6f3dSAnirudh Venkataramanan hw_link_info = &vsi->port_info->phy.link_info; 121248cb27f2SChinh Cao phy_types_low = vsi->port_info->phy.phy_type_low; 1213aef74145SAnirudh Venkataramanan phy_types_high = vsi->port_info->phy.phy_type_high; 1214fcea6f3dSAnirudh Venkataramanan 121548cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 121648cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 121748cb27f2SChinh Cao 121848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 121948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_100M_SGMII) { 122048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 122148cb27f2SChinh Cao 100baseT_Full); 12229ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12239ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100MB) 122448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 122548cb27f2SChinh Cao 100baseT_Full); 122648cb27f2SChinh Cao } 122748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 122848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1G_SGMII) { 122948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 123048cb27f2SChinh Cao 1000baseT_Full); 12319ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12329ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 123348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 123448cb27f2SChinh Cao 1000baseT_Full); 123548cb27f2SChinh Cao } 123648cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX) { 123748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 123848cb27f2SChinh Cao 1000baseKX_Full); 12399ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12409ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 124148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 124248cb27f2SChinh Cao 1000baseKX_Full); 124348cb27f2SChinh Cao } 124448cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_SX || 124548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_LX) { 124648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 124748cb27f2SChinh Cao 1000baseX_Full); 12489ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12499ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 125048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 125148cb27f2SChinh Cao 1000baseX_Full); 125248cb27f2SChinh Cao } 125348cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T) { 125448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 125548cb27f2SChinh Cao 2500baseT_Full); 12569ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12579ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 125848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 125948cb27f2SChinh Cao 2500baseT_Full); 126048cb27f2SChinh Cao } 126148cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_X || 126248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX) { 126348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 126448cb27f2SChinh Cao 2500baseX_Full); 12659ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12669ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 126748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 126848cb27f2SChinh Cao 2500baseX_Full); 126948cb27f2SChinh Cao } 127048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 127148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR) { 127248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 127348cb27f2SChinh Cao 5000baseT_Full); 12749ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12759ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_5GB) 127648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 127748cb27f2SChinh Cao 5000baseT_Full); 127848cb27f2SChinh Cao } 127948cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 128048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_DA || 128148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC || 128248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_C2C) { 1283fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1284fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 12859ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12869ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 1287fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1288fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 128948cb27f2SChinh Cao } 129048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1) { 129148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 129248cb27f2SChinh Cao 10000baseKR_Full); 12939ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 12949ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 129548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 129648cb27f2SChinh Cao 10000baseKR_Full); 129748cb27f2SChinh Cao } 129848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_SR) { 129948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 130048cb27f2SChinh Cao 10000baseSR_Full); 13019ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13029ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 130348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 130448cb27f2SChinh Cao 10000baseSR_Full); 130548cb27f2SChinh Cao } 130648cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_LR) { 130748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 130848cb27f2SChinh Cao 10000baseLR_Full); 13099ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13109ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 131148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 131248cb27f2SChinh Cao 10000baseLR_Full); 131348cb27f2SChinh Cao } 131448cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 131548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 131648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 131748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 131848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC || 131948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_C2C) { 132048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 132148cb27f2SChinh Cao 25000baseCR_Full); 13229ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13239ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 132448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 132548cb27f2SChinh Cao 25000baseCR_Full); 132648cb27f2SChinh Cao } 132748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_SR || 132848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_LR) { 132948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 133048cb27f2SChinh Cao 25000baseSR_Full); 13319ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13329ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 133348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 133448cb27f2SChinh Cao 25000baseSR_Full); 133548cb27f2SChinh Cao } 133648cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 133748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 133848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1) { 133948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 134048cb27f2SChinh Cao 25000baseKR_Full); 13419ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13429ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 134348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 134448cb27f2SChinh Cao 25000baseKR_Full); 134548cb27f2SChinh Cao } 134648cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 134748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 134848cb27f2SChinh Cao 40000baseKR4_Full); 13499ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13509ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 135148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 135248cb27f2SChinh Cao 40000baseKR4_Full); 135348cb27f2SChinh Cao } 135448cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 135548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC || 135648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI) { 135748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 135848cb27f2SChinh Cao 40000baseCR4_Full); 13599ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13609ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 136148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 136248cb27f2SChinh Cao 40000baseCR4_Full); 136348cb27f2SChinh Cao } 136448cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_SR4) { 136548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 136648cb27f2SChinh Cao 40000baseSR4_Full); 13679ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13689ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 136948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 137048cb27f2SChinh Cao 40000baseSR4_Full); 137148cb27f2SChinh Cao } 137248cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_LR4) { 137348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 137448cb27f2SChinh Cao 40000baseLR4_Full); 13759ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13769ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 137748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 137848cb27f2SChinh Cao 40000baseLR4_Full); 137948cb27f2SChinh Cao } 1380aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 1381aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC || 1382aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2 || 1383aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC || 1384aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2 || 1385aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 1386aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR || 1387aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC || 1388aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1) { 1389aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1390aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 13919ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 13929ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1393aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1394aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1395aef74145SAnirudh Venkataramanan } 1396aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 1397aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 1398aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1399aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 14009ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14019ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1402aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1403aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1404aef74145SAnirudh Venkataramanan } 1405aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR2 || 1406aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR2 || 1407aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_FR || 1408aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR) { 1409aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1410aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 14119ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14129ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1413aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1414aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 1415aef74145SAnirudh Venkataramanan } 1416aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 1417aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC || 1418aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4 || 1419aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC || 1420aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4 || 1421aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 || 1422aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2 || 1423aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC || 1424aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2 || 1425aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC || 1426aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2) { 1427aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1428aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 14299ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14309ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1431aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1432aef74145SAnirudh Venkataramanan } 1433aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1434aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1435aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1436aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1437aef74145SAnirudh Venkataramanan } 1438aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4 || 1439aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) { 1440aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1441aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 14429ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14439ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1444aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1445aef74145SAnirudh Venkataramanan } 1446aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1447aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1448aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1449aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 1450aef74145SAnirudh Venkataramanan } 1451aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_LR4 || 1452aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_DR) { 1453aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1454aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 14559ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14569ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1457aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1458aef74145SAnirudh Venkataramanan } 1459aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1460aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1461aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1462aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 1463aef74145SAnirudh Venkataramanan } 1464aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || 1465aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || 1466aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) { 1467aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1468aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 14699ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14709ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1471aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1472aef74145SAnirudh Venkataramanan } 1473aef74145SAnirudh Venkataramanan if (need_add_adv_mode) 1474aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1475aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1476fcea6f3dSAnirudh Venkataramanan 147748cb27f2SChinh Cao /* Autoneg PHY types */ 147848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 147948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 148048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX || 148148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T || 148248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX || 148348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 148448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR || 148548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 148648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 || 148748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 148848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 148948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 149048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 149148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 149248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 149348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1 || 149448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 149548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 149648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 149748cb27f2SChinh Cao Autoneg); 149848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 149948cb27f2SChinh Cao Autoneg); 150048cb27f2SChinh Cao } 1501aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 1502aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 1503aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 1504aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 1505aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1506aef74145SAnirudh Venkataramanan Autoneg); 1507aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1508aef74145SAnirudh Venkataramanan Autoneg); 1509aef74145SAnirudh Venkataramanan } 1510aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 1511aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || 1512aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || 1513aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) { 1514aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1515aef74145SAnirudh Venkataramanan Autoneg); 1516aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1517aef74145SAnirudh Venkataramanan Autoneg); 1518aef74145SAnirudh Venkataramanan } 151948cb27f2SChinh Cao } 152048cb27f2SChinh Cao 152148cb27f2SChinh Cao #define TEST_SET_BITS_TIMEOUT 50 152248cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MAX 2000 152348cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MIN 1000 152448cb27f2SChinh Cao 152548cb27f2SChinh Cao /** 152648cb27f2SChinh Cao * ice_get_settings_link_up - Get Link settings for when link is up 152748cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 152848cb27f2SChinh Cao * @netdev: network interface device structure 152948cb27f2SChinh Cao */ 1530aef74145SAnirudh Venkataramanan static void 1531aef74145SAnirudh Venkataramanan ice_get_settings_link_up(struct ethtool_link_ksettings *ks, 153248cb27f2SChinh Cao struct net_device *netdev) 153348cb27f2SChinh Cao { 153448cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 153548cb27f2SChinh Cao struct ethtool_link_ksettings cap_ksettings; 153648cb27f2SChinh Cao struct ice_link_status *link_info; 153748cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 1538aef74145SAnirudh Venkataramanan bool unrecog_phy_high = false; 153948cb27f2SChinh Cao bool unrecog_phy_low = false; 154048cb27f2SChinh Cao 154148cb27f2SChinh Cao link_info = &vsi->port_info->phy.link_info; 154248cb27f2SChinh Cao 1543f9867df6SAnirudh Venkataramanan /* Initialize supported and advertised settings based on PHY settings */ 154448cb27f2SChinh Cao switch (link_info->phy_type_low) { 154548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_100BASE_TX: 154648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 154748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 154848cb27f2SChinh Cao 100baseT_Full); 154948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 155048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 155148cb27f2SChinh Cao 100baseT_Full); 1552fcea6f3dSAnirudh Venkataramanan break; 155348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_100M_SGMII: 155448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 155548cb27f2SChinh Cao 100baseT_Full); 1556fcea6f3dSAnirudh Venkataramanan break; 155748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_T: 155848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 155948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 156048cb27f2SChinh Cao 1000baseT_Full); 156148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 156248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 156348cb27f2SChinh Cao 1000baseT_Full); 1564fcea6f3dSAnirudh Venkataramanan break; 156548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1G_SGMII: 156648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 156748cb27f2SChinh Cao 1000baseT_Full); 156848cb27f2SChinh Cao break; 156948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_SX: 157048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_LX: 157148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 157248cb27f2SChinh Cao 1000baseX_Full); 157348cb27f2SChinh Cao break; 157448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_KX: 157548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 157648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 157748cb27f2SChinh Cao 1000baseKX_Full); 157848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 157948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 158048cb27f2SChinh Cao 1000baseKX_Full); 158148cb27f2SChinh Cao break; 158248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_T: 158348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 158448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 158548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 158648cb27f2SChinh Cao 2500baseT_Full); 158748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 158848cb27f2SChinh Cao 2500baseT_Full); 158948cb27f2SChinh Cao break; 159048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_X: 159148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 159248cb27f2SChinh Cao 2500baseX_Full); 159348cb27f2SChinh Cao break; 159448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_KX: 159548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 159648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 159748cb27f2SChinh Cao 2500baseX_Full); 159848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 159948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 160048cb27f2SChinh Cao 2500baseX_Full); 160148cb27f2SChinh Cao break; 160248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_5GBASE_T: 160348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_5GBASE_KR: 160448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 160548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 160648cb27f2SChinh Cao 5000baseT_Full); 160748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 160848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 160948cb27f2SChinh Cao 5000baseT_Full); 161048cb27f2SChinh Cao break; 161148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_T: 161248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 161348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 161448cb27f2SChinh Cao 10000baseT_Full); 161548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 161648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 161748cb27f2SChinh Cao 10000baseT_Full); 161848cb27f2SChinh Cao break; 161948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_DA: 162048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC: 162148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 162248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 162348cb27f2SChinh Cao 10000baseT_Full); 162448cb27f2SChinh Cao break; 162548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_SR: 162648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 162748cb27f2SChinh Cao 10000baseSR_Full); 162848cb27f2SChinh Cao break; 162948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_LR: 163048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 163148cb27f2SChinh Cao 10000baseLR_Full); 163248cb27f2SChinh Cao break; 163348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 163448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 163548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 163648cb27f2SChinh Cao 10000baseKR_Full); 163748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 163848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 163948cb27f2SChinh Cao 10000baseKR_Full); 164048cb27f2SChinh Cao break; 164148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_T: 164248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR: 164348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 164448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR1: 164548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 164648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 164748cb27f2SChinh Cao 25000baseCR_Full); 164848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 164948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 165048cb27f2SChinh Cao 25000baseCR_Full); 165148cb27f2SChinh Cao break; 165248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC: 165349a6a5d7STony Nguyen case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 165448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 165548cb27f2SChinh Cao 25000baseCR_Full); 165648cb27f2SChinh Cao break; 165748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_SR: 165848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_LR: 165948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 166048cb27f2SChinh Cao 25000baseSR_Full); 166148cb27f2SChinh Cao break; 166248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR: 166348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR1: 166448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 166548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 166648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 166748cb27f2SChinh Cao 25000baseKR_Full); 166848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 166948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 167048cb27f2SChinh Cao 25000baseKR_Full); 167148cb27f2SChinh Cao break; 167248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_CR4: 167348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 167448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 167548cb27f2SChinh Cao 40000baseCR4_Full); 167648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 167748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 167848cb27f2SChinh Cao 40000baseCR4_Full); 167948cb27f2SChinh Cao break; 168048cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC: 168148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40G_XLAUI: 168248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 168348cb27f2SChinh Cao 40000baseCR4_Full); 168448cb27f2SChinh Cao break; 168548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_SR4: 168648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 168748cb27f2SChinh Cao 40000baseSR4_Full); 168848cb27f2SChinh Cao break; 168948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_LR4: 169048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 169148cb27f2SChinh Cao 40000baseLR4_Full); 169248cb27f2SChinh Cao break; 169348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_KR4: 169448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 169548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 169648cb27f2SChinh Cao 40000baseKR4_Full); 169748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 169848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 169948cb27f2SChinh Cao 40000baseKR4_Full); 170048cb27f2SChinh Cao break; 1701aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_CR2: 1702aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_CP: 1703aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1704aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1705aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1706aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1707aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1708aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1709aef74145SAnirudh Venkataramanan break; 1710aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: 1711aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_LAUI2: 1712aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: 1713aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI2: 1714aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_SR: 1715aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: 1716aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI1: 1717aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1718aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1719aef74145SAnirudh Venkataramanan break; 1720aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_KR2: 1721aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: 1722aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1723aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1724aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1725aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1726aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1727aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1728aef74145SAnirudh Venkataramanan break; 1729aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_SR2: 1730aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_LR2: 1731aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_FR: 1732aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_LR: 1733aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1734aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 1735aef74145SAnirudh Venkataramanan break; 1736aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CR4: 1737aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1738aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1739aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1740aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1741aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1742aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1743aef74145SAnirudh Venkataramanan break; 1744aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: 1745aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_CAUI4: 1746aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: 1747aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_AUI4: 1748aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: 1749aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1750aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1751aef74145SAnirudh Venkataramanan break; 1752aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CP2: 1753aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1754aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1755aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1756aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1757aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1758aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1759aef74145SAnirudh Venkataramanan break; 1760aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_SR4: 1761aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_SR2: 1762aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1763aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 1764aef74145SAnirudh Venkataramanan break; 1765aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_LR4: 1766aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_DR: 1767aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1768aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 1769aef74145SAnirudh Venkataramanan break; 1770aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_KR4: 1771aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: 1772aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1773aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1774aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1775aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1776aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1777aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1778aef74145SAnirudh Venkataramanan break; 177948cb27f2SChinh Cao default: 178048cb27f2SChinh Cao unrecog_phy_low = true; 178148cb27f2SChinh Cao } 178248cb27f2SChinh Cao 1783aef74145SAnirudh Venkataramanan switch (link_info->phy_type_high) { 1784aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: 1785aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1786aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1787aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1788aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1789aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1790aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1791aef74145SAnirudh Venkataramanan break; 1792aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: 1793aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_CAUI2: 1794aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: 1795aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_AUI2: 1796aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1797aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1798aef74145SAnirudh Venkataramanan break; 1799aef74145SAnirudh Venkataramanan default: 1800aef74145SAnirudh Venkataramanan unrecog_phy_high = true; 1801aef74145SAnirudh Venkataramanan } 1802aef74145SAnirudh Venkataramanan 1803aef74145SAnirudh Venkataramanan if (unrecog_phy_low && unrecog_phy_high) { 180448cb27f2SChinh Cao /* if we got here and link is up something bad is afoot */ 1805aef74145SAnirudh Venkataramanan netdev_info(netdev, 1806aef74145SAnirudh Venkataramanan "WARNING: Unrecognized PHY_Low (0x%llx).\n", 180748cb27f2SChinh Cao (u64)link_info->phy_type_low); 1808aef74145SAnirudh Venkataramanan netdev_info(netdev, 1809aef74145SAnirudh Venkataramanan "WARNING: Unrecognized PHY_High (0x%llx).\n", 1810aef74145SAnirudh Venkataramanan (u64)link_info->phy_type_high); 181148cb27f2SChinh Cao } 181248cb27f2SChinh Cao 181348cb27f2SChinh Cao /* Now that we've worked out everything that could be supported by the 181448cb27f2SChinh Cao * current PHY type, get what is supported by the NVM and intersect 181548cb27f2SChinh Cao * them to get what is truly supported 181648cb27f2SChinh Cao */ 1817c6dfd690SBruce Allan memset(&cap_ksettings, 0, sizeof(cap_ksettings)); 181848cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, &cap_ksettings); 181948cb27f2SChinh Cao ethtool_intersect_link_masks(ks, &cap_ksettings); 182048cb27f2SChinh Cao 182148cb27f2SChinh Cao switch (link_info->link_speed) { 1822aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_100GB: 1823aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_100000; 1824aef74145SAnirudh Venkataramanan break; 1825aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_50GB: 1826aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_50000; 1827aef74145SAnirudh Venkataramanan break; 182848cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_40GB: 182948cb27f2SChinh Cao ks->base.speed = SPEED_40000; 1830fcea6f3dSAnirudh Venkataramanan break; 1831fcea6f3dSAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_25GB: 1832fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_25000; 1833fcea6f3dSAnirudh Venkataramanan break; 183448cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_20GB: 183548cb27f2SChinh Cao ks->base.speed = SPEED_20000; 183648cb27f2SChinh Cao break; 183748cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_10GB: 183848cb27f2SChinh Cao ks->base.speed = SPEED_10000; 183948cb27f2SChinh Cao break; 184048cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_5GB: 184148cb27f2SChinh Cao ks->base.speed = SPEED_5000; 184248cb27f2SChinh Cao break; 184348cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_2500MB: 184448cb27f2SChinh Cao ks->base.speed = SPEED_2500; 184548cb27f2SChinh Cao break; 184648cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_1000MB: 184748cb27f2SChinh Cao ks->base.speed = SPEED_1000; 184848cb27f2SChinh Cao break; 184948cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_100MB: 185048cb27f2SChinh Cao ks->base.speed = SPEED_100; 1851fcea6f3dSAnirudh Venkataramanan break; 1852fcea6f3dSAnirudh Venkataramanan default: 185348cb27f2SChinh Cao netdev_info(netdev, 185448cb27f2SChinh Cao "WARNING: Unrecognized link_speed (0x%x).\n", 185548cb27f2SChinh Cao link_info->link_speed); 1856fcea6f3dSAnirudh Venkataramanan break; 1857fcea6f3dSAnirudh Venkataramanan } 1858fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_FULL; 185948cb27f2SChinh Cao } 186048cb27f2SChinh Cao 186148cb27f2SChinh Cao /** 186248cb27f2SChinh Cao * ice_get_settings_link_down - Get the Link settings when link is down 186348cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 186448cb27f2SChinh Cao * @netdev: network interface device structure 186548cb27f2SChinh Cao * 186648cb27f2SChinh Cao * Reports link settings that can be determined when link is down 186748cb27f2SChinh Cao */ 186848cb27f2SChinh Cao static void 186948cb27f2SChinh Cao ice_get_settings_link_down(struct ethtool_link_ksettings *ks, 1870a03499d6STony Nguyen struct net_device *netdev) 187148cb27f2SChinh Cao { 187248cb27f2SChinh Cao /* link is down and the driver needs to fall back on 1873f9867df6SAnirudh Venkataramanan * supported PHY types to figure out what info to display 187448cb27f2SChinh Cao */ 187548cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, ks); 187648cb27f2SChinh Cao 187748cb27f2SChinh Cao /* With no link, speed and duplex are unknown */ 1878fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_UNKNOWN; 1879fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_UNKNOWN; 1880fcea6f3dSAnirudh Venkataramanan } 1881fcea6f3dSAnirudh Venkataramanan 188248cb27f2SChinh Cao /** 188348cb27f2SChinh Cao * ice_get_link_ksettings - Get Link Speed and Duplex settings 188448cb27f2SChinh Cao * @netdev: network interface device structure 188548cb27f2SChinh Cao * @ks: ethtool ksettings 188648cb27f2SChinh Cao * 188748cb27f2SChinh Cao * Reports speed/duplex settings based on media_type 188848cb27f2SChinh Cao */ 1889c8b7abddSBruce Allan static int 1890c8b7abddSBruce Allan ice_get_link_ksettings(struct net_device *netdev, 189148cb27f2SChinh Cao struct ethtool_link_ksettings *ks) 189248cb27f2SChinh Cao { 189348cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 189448cb27f2SChinh Cao struct ice_link_status *hw_link_info; 189548cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 189648cb27f2SChinh Cao 189748cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 189848cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 189948cb27f2SChinh Cao hw_link_info = &vsi->port_info->phy.link_info; 190048cb27f2SChinh Cao 190148cb27f2SChinh Cao /* set speed and duplex */ 190248cb27f2SChinh Cao if (hw_link_info->link_info & ICE_AQ_LINK_UP) 190348cb27f2SChinh Cao ice_get_settings_link_up(ks, netdev); 190448cb27f2SChinh Cao else 190548cb27f2SChinh Cao ice_get_settings_link_down(ks, netdev); 190648cb27f2SChinh Cao 1907fcea6f3dSAnirudh Venkataramanan /* set autoneg settings */ 190848cb27f2SChinh Cao ks->base.autoneg = (hw_link_info->an_info & ICE_AQ_AN_COMPLETED) ? 190948cb27f2SChinh Cao AUTONEG_ENABLE : AUTONEG_DISABLE; 1910fcea6f3dSAnirudh Venkataramanan 1911fcea6f3dSAnirudh Venkataramanan /* set media type settings */ 1912fcea6f3dSAnirudh Venkataramanan switch (vsi->port_info->phy.media_type) { 1913fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_FIBER: 1914fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 1915fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_FIBRE; 1916fcea6f3dSAnirudh Venkataramanan break; 1917fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BASET: 1918fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, TP); 1919fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, TP); 1920fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_TP; 1921fcea6f3dSAnirudh Venkataramanan break; 1922fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BACKPLANE: 1923fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1924fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Backplane); 1925fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1926fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1927fcea6f3dSAnirudh Venkataramanan Backplane); 1928fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_NONE; 1929fcea6f3dSAnirudh Venkataramanan break; 1930fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_DA: 1931fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 1932fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE); 1933fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_DA; 1934fcea6f3dSAnirudh Venkataramanan break; 1935fcea6f3dSAnirudh Venkataramanan default: 1936fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_OTHER; 1937fcea6f3dSAnirudh Venkataramanan break; 1938fcea6f3dSAnirudh Venkataramanan } 1939fcea6f3dSAnirudh Venkataramanan 1940fcea6f3dSAnirudh Venkataramanan /* flow control is symmetric and always supported */ 1941fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Pause); 1942fcea6f3dSAnirudh Venkataramanan 1943fcea6f3dSAnirudh Venkataramanan switch (vsi->port_info->fc.req_mode) { 1944fcea6f3dSAnirudh Venkataramanan case ICE_FC_FULL: 1945fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 1946fcea6f3dSAnirudh Venkataramanan break; 1947fcea6f3dSAnirudh Venkataramanan case ICE_FC_TX_PAUSE: 1948fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1949fcea6f3dSAnirudh Venkataramanan Asym_Pause); 1950fcea6f3dSAnirudh Venkataramanan break; 1951fcea6f3dSAnirudh Venkataramanan case ICE_FC_RX_PAUSE: 1952fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 1953fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1954fcea6f3dSAnirudh Venkataramanan Asym_Pause); 1955fcea6f3dSAnirudh Venkataramanan break; 1956fcea6f3dSAnirudh Venkataramanan case ICE_FC_PFC: 1957fcea6f3dSAnirudh Venkataramanan default: 1958fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, Pause); 1959fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, 1960fcea6f3dSAnirudh Venkataramanan Asym_Pause); 1961fcea6f3dSAnirudh Venkataramanan break; 1962fcea6f3dSAnirudh Venkataramanan } 1963fcea6f3dSAnirudh Venkataramanan 1964fcea6f3dSAnirudh Venkataramanan return 0; 1965fcea6f3dSAnirudh Venkataramanan } 1966fcea6f3dSAnirudh Venkataramanan 1967fcea6f3dSAnirudh Venkataramanan /** 196848cb27f2SChinh Cao * ice_ksettings_find_adv_link_speed - Find advertising link speed 196948cb27f2SChinh Cao * @ks: ethtool ksettings 197048cb27f2SChinh Cao */ 197148cb27f2SChinh Cao static u16 197248cb27f2SChinh Cao ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks) 197348cb27f2SChinh Cao { 197448cb27f2SChinh Cao u16 adv_link_speed = 0; 197548cb27f2SChinh Cao 197648cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 197748cb27f2SChinh Cao 100baseT_Full)) 197848cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_100MB; 197948cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 198048cb27f2SChinh Cao 1000baseX_Full)) 198148cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 198248cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 198348cb27f2SChinh Cao 1000baseT_Full) || 198448cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 198548cb27f2SChinh Cao 1000baseKX_Full)) 198648cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 198748cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 198848cb27f2SChinh Cao 2500baseT_Full)) 198948cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 199048cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 199148cb27f2SChinh Cao 2500baseX_Full)) 199248cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 199348cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 199448cb27f2SChinh Cao 5000baseT_Full)) 199548cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_5GB; 199648cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 199748cb27f2SChinh Cao 10000baseT_Full) || 199848cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 199948cb27f2SChinh Cao 10000baseKR_Full)) 200048cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 200148cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 200248cb27f2SChinh Cao 10000baseSR_Full) || 200348cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 200448cb27f2SChinh Cao 10000baseLR_Full)) 200548cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 200648cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 200748cb27f2SChinh Cao 25000baseCR_Full) || 200848cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 200948cb27f2SChinh Cao 25000baseSR_Full) || 201048cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 201148cb27f2SChinh Cao 25000baseKR_Full)) 201248cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_25GB; 201348cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 201448cb27f2SChinh Cao 40000baseCR4_Full) || 201548cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 201648cb27f2SChinh Cao 40000baseSR4_Full) || 201748cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 201848cb27f2SChinh Cao 40000baseLR4_Full) || 201948cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 202048cb27f2SChinh Cao 40000baseKR4_Full)) 202148cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_40GB; 2022aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2023aef74145SAnirudh Venkataramanan 50000baseCR2_Full) || 2024aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2025aef74145SAnirudh Venkataramanan 50000baseKR2_Full)) 2026aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 2027aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2028aef74145SAnirudh Venkataramanan 50000baseSR2_Full)) 2029aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 2030aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2031aef74145SAnirudh Venkataramanan 100000baseCR4_Full) || 2032aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2033aef74145SAnirudh Venkataramanan 100000baseSR4_Full) || 2034aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2035aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full) || 2036aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2037aef74145SAnirudh Venkataramanan 100000baseKR4_Full)) 2038aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_100GB; 203948cb27f2SChinh Cao 204048cb27f2SChinh Cao return adv_link_speed; 204148cb27f2SChinh Cao } 204248cb27f2SChinh Cao 204348cb27f2SChinh Cao /** 204448cb27f2SChinh Cao * ice_setup_autoneg 204548cb27f2SChinh Cao * @p: port info 204648cb27f2SChinh Cao * @ks: ethtool_link_ksettings 204748cb27f2SChinh Cao * @config: configuration that will be sent down to FW 204848cb27f2SChinh Cao * @autoneg_enabled: autonegotiation is enabled or not 204948cb27f2SChinh Cao * @autoneg_changed: will there a change in autonegotiation 205048cb27f2SChinh Cao * @netdev: network interface device structure 205148cb27f2SChinh Cao * 205248cb27f2SChinh Cao * Setup PHY autonegotiation feature 205348cb27f2SChinh Cao */ 205448cb27f2SChinh Cao static int 205548cb27f2SChinh Cao ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks, 205648cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data *config, 205748cb27f2SChinh Cao u8 autoneg_enabled, u8 *autoneg_changed, 205848cb27f2SChinh Cao struct net_device *netdev) 205948cb27f2SChinh Cao { 206048cb27f2SChinh Cao int err = 0; 206148cb27f2SChinh Cao 206248cb27f2SChinh Cao *autoneg_changed = 0; 206348cb27f2SChinh Cao 206448cb27f2SChinh Cao /* Check autoneg */ 206548cb27f2SChinh Cao if (autoneg_enabled == AUTONEG_ENABLE) { 206648cb27f2SChinh Cao /* If autoneg was not already enabled */ 206748cb27f2SChinh Cao if (!(p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED)) { 206848cb27f2SChinh Cao /* If autoneg is not supported, return error */ 206948cb27f2SChinh Cao if (!ethtool_link_ksettings_test_link_mode(ks, 207048cb27f2SChinh Cao supported, 207148cb27f2SChinh Cao Autoneg)) { 207248cb27f2SChinh Cao netdev_info(netdev, "Autoneg not supported on this phy.\n"); 207348cb27f2SChinh Cao err = -EINVAL; 207448cb27f2SChinh Cao } else { 207548cb27f2SChinh Cao /* Autoneg is allowed to change */ 207648cb27f2SChinh Cao config->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 207748cb27f2SChinh Cao *autoneg_changed = 1; 207848cb27f2SChinh Cao } 207948cb27f2SChinh Cao } 208048cb27f2SChinh Cao } else { 208148cb27f2SChinh Cao /* If autoneg is currently enabled */ 208248cb27f2SChinh Cao if (p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED) { 2083f9867df6SAnirudh Venkataramanan /* If autoneg is supported 10GBASE_T is the only PHY 208448cb27f2SChinh Cao * that can disable it, so otherwise return error 208548cb27f2SChinh Cao */ 208648cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, 208748cb27f2SChinh Cao supported, 208848cb27f2SChinh Cao Autoneg)) { 208948cb27f2SChinh Cao netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); 209048cb27f2SChinh Cao err = -EINVAL; 209148cb27f2SChinh Cao } else { 209248cb27f2SChinh Cao /* Autoneg is allowed to change */ 209348cb27f2SChinh Cao config->caps &= ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 209448cb27f2SChinh Cao *autoneg_changed = 1; 209548cb27f2SChinh Cao } 209648cb27f2SChinh Cao } 209748cb27f2SChinh Cao } 209848cb27f2SChinh Cao 209948cb27f2SChinh Cao return err; 210048cb27f2SChinh Cao } 210148cb27f2SChinh Cao 210248cb27f2SChinh Cao /** 210348cb27f2SChinh Cao * ice_set_link_ksettings - Set Speed and Duplex 210448cb27f2SChinh Cao * @netdev: network interface device structure 210548cb27f2SChinh Cao * @ks: ethtool ksettings 210648cb27f2SChinh Cao * 210748cb27f2SChinh Cao * Set speed/duplex per media_types advertised/forced 210848cb27f2SChinh Cao */ 2109aef74145SAnirudh Venkataramanan static int 2110aef74145SAnirudh Venkataramanan ice_set_link_ksettings(struct net_device *netdev, 211148cb27f2SChinh Cao const struct ethtool_link_ksettings *ks) 211248cb27f2SChinh Cao { 211348cb27f2SChinh Cao u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0; 211448cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 211548cb27f2SChinh Cao struct ethtool_link_ksettings safe_ks, copy_ks; 211648cb27f2SChinh Cao struct ice_aqc_get_phy_caps_data *abilities; 211748cb27f2SChinh Cao u16 adv_link_speed, curr_link_speed, idx; 211848cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data config; 211948cb27f2SChinh Cao struct ice_pf *pf = np->vsi->back; 212048cb27f2SChinh Cao struct ice_port_info *p; 212148cb27f2SChinh Cao u8 autoneg_changed = 0; 212248cb27f2SChinh Cao enum ice_status status; 2123aef74145SAnirudh Venkataramanan u64 phy_type_high; 212448cb27f2SChinh Cao u64 phy_type_low; 212548cb27f2SChinh Cao int err = 0; 212648cb27f2SChinh Cao bool linkup; 212748cb27f2SChinh Cao 212848cb27f2SChinh Cao p = np->vsi->port_info; 212948cb27f2SChinh Cao 213048cb27f2SChinh Cao if (!p) 213148cb27f2SChinh Cao return -EOPNOTSUPP; 213248cb27f2SChinh Cao 2133f9867df6SAnirudh Venkataramanan /* Check if this is LAN VSI */ 213480ed404aSBrett Creeley ice_for_each_vsi(pf, idx) 213548cb27f2SChinh Cao if (pf->vsi[idx]->type == ICE_VSI_PF) { 213648cb27f2SChinh Cao if (np->vsi != pf->vsi[idx]) 213748cb27f2SChinh Cao return -EOPNOTSUPP; 213848cb27f2SChinh Cao break; 213948cb27f2SChinh Cao } 214048cb27f2SChinh Cao 214148cb27f2SChinh Cao if (p->phy.media_type != ICE_MEDIA_BASET && 214248cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_FIBER && 214348cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_BACKPLANE && 214448cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_DA && 214548cb27f2SChinh Cao p->phy.link_info.link_info & ICE_AQ_LINK_UP) 214648cb27f2SChinh Cao return -EOPNOTSUPP; 214748cb27f2SChinh Cao 214848cb27f2SChinh Cao /* copy the ksettings to copy_ks to avoid modifying the original */ 2149c6dfd690SBruce Allan memcpy(©_ks, ks, sizeof(copy_ks)); 215048cb27f2SChinh Cao 215148cb27f2SChinh Cao /* save autoneg out of ksettings */ 215248cb27f2SChinh Cao autoneg = copy_ks.base.autoneg; 215348cb27f2SChinh Cao 215448cb27f2SChinh Cao memset(&safe_ks, 0, sizeof(safe_ks)); 215548cb27f2SChinh Cao 215648cb27f2SChinh Cao /* Get link modes supported by hardware.*/ 215748cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, &safe_ks); 215848cb27f2SChinh Cao 215948cb27f2SChinh Cao /* and check against modes requested by user. 216048cb27f2SChinh Cao * Return an error if unsupported mode was set. 216148cb27f2SChinh Cao */ 216248cb27f2SChinh Cao if (!bitmap_subset(copy_ks.link_modes.advertising, 216348cb27f2SChinh Cao safe_ks.link_modes.supported, 216448cb27f2SChinh Cao __ETHTOOL_LINK_MODE_MASK_NBITS)) 216548cb27f2SChinh Cao return -EINVAL; 216648cb27f2SChinh Cao 216748cb27f2SChinh Cao /* get our own copy of the bits to check against */ 2168c6dfd690SBruce Allan memset(&safe_ks, 0, sizeof(safe_ks)); 216948cb27f2SChinh Cao safe_ks.base.cmd = copy_ks.base.cmd; 217048cb27f2SChinh Cao safe_ks.base.link_mode_masks_nwords = 217148cb27f2SChinh Cao copy_ks.base.link_mode_masks_nwords; 217248cb27f2SChinh Cao ice_get_link_ksettings(netdev, &safe_ks); 217348cb27f2SChinh Cao 217448cb27f2SChinh Cao /* set autoneg back to what it currently is */ 217548cb27f2SChinh Cao copy_ks.base.autoneg = safe_ks.base.autoneg; 217648cb27f2SChinh Cao /* we don't compare the speed */ 217748cb27f2SChinh Cao copy_ks.base.speed = safe_ks.base.speed; 217848cb27f2SChinh Cao 217948cb27f2SChinh Cao /* If copy_ks.base and safe_ks.base are not the same now, then they are 218048cb27f2SChinh Cao * trying to set something that we do not support. 218148cb27f2SChinh Cao */ 2182c6dfd690SBruce Allan if (memcmp(©_ks.base, &safe_ks.base, sizeof(copy_ks.base))) 218348cb27f2SChinh Cao return -EOPNOTSUPP; 218448cb27f2SChinh Cao 218548cb27f2SChinh Cao while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 218648cb27f2SChinh Cao timeout--; 218748cb27f2SChinh Cao if (!timeout) 218848cb27f2SChinh Cao return -EBUSY; 218948cb27f2SChinh Cao usleep_range(TEST_SET_BITS_SLEEP_MIN, TEST_SET_BITS_SLEEP_MAX); 219048cb27f2SChinh Cao } 219148cb27f2SChinh Cao 219248cb27f2SChinh Cao abilities = devm_kzalloc(&pf->pdev->dev, sizeof(*abilities), 219348cb27f2SChinh Cao GFP_KERNEL); 219448cb27f2SChinh Cao if (!abilities) 219548cb27f2SChinh Cao return -ENOMEM; 219648cb27f2SChinh Cao 2197f9867df6SAnirudh Venkataramanan /* Get the current PHY config */ 219848cb27f2SChinh Cao status = ice_aq_get_phy_caps(p, false, ICE_AQC_REPORT_SW_CFG, abilities, 219948cb27f2SChinh Cao NULL); 220048cb27f2SChinh Cao if (status) { 220148cb27f2SChinh Cao err = -EAGAIN; 220248cb27f2SChinh Cao goto done; 220348cb27f2SChinh Cao } 220448cb27f2SChinh Cao 220548cb27f2SChinh Cao /* Copy abilities to config in case autoneg is not set below */ 2206c6dfd690SBruce Allan memset(&config, 0, sizeof(config)); 220748cb27f2SChinh Cao config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE; 220848cb27f2SChinh Cao if (abilities->caps & ICE_AQC_PHY_AN_MODE) 220948cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 221048cb27f2SChinh Cao 221148cb27f2SChinh Cao /* Check autoneg */ 221248cb27f2SChinh Cao err = ice_setup_autoneg(p, &safe_ks, &config, autoneg, &autoneg_changed, 221348cb27f2SChinh Cao netdev); 221448cb27f2SChinh Cao 221548cb27f2SChinh Cao if (err) 221648cb27f2SChinh Cao goto done; 221748cb27f2SChinh Cao 221848cb27f2SChinh Cao /* Call to get the current link speed */ 221948cb27f2SChinh Cao p->phy.get_link_info = true; 222048cb27f2SChinh Cao status = ice_get_link_status(p, &linkup); 222148cb27f2SChinh Cao if (status) { 222248cb27f2SChinh Cao err = -EAGAIN; 222348cb27f2SChinh Cao goto done; 222448cb27f2SChinh Cao } 222548cb27f2SChinh Cao 222648cb27f2SChinh Cao curr_link_speed = p->phy.link_info.link_speed; 222748cb27f2SChinh Cao adv_link_speed = ice_ksettings_find_adv_link_speed(ks); 222848cb27f2SChinh Cao 222948cb27f2SChinh Cao /* If speed didn't get set, set it to what it currently is. 223048cb27f2SChinh Cao * This is needed because if advertise is 0 (as it is when autoneg 223148cb27f2SChinh Cao * is disabled) then speed won't get set. 223248cb27f2SChinh Cao */ 223348cb27f2SChinh Cao if (!adv_link_speed) 223448cb27f2SChinh Cao adv_link_speed = curr_link_speed; 223548cb27f2SChinh Cao 223648cb27f2SChinh Cao /* Convert the advertise link speeds to their corresponded PHY_TYPE */ 2237aef74145SAnirudh Venkataramanan ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed); 223848cb27f2SChinh Cao 223948cb27f2SChinh Cao if (!autoneg_changed && adv_link_speed == curr_link_speed) { 224048cb27f2SChinh Cao netdev_info(netdev, "Nothing changed, exiting without setting anything.\n"); 224148cb27f2SChinh Cao goto done; 224248cb27f2SChinh Cao } 224348cb27f2SChinh Cao 224448cb27f2SChinh Cao /* copy over the rest of the abilities */ 224548cb27f2SChinh Cao config.low_power_ctrl = abilities->low_power_ctrl; 224648cb27f2SChinh Cao config.eee_cap = abilities->eee_cap; 224748cb27f2SChinh Cao config.eeer_value = abilities->eeer_value; 224848cb27f2SChinh Cao config.link_fec_opt = abilities->link_fec_options; 224948cb27f2SChinh Cao 225048cb27f2SChinh Cao /* save the requested speeds */ 225148cb27f2SChinh Cao p->phy.link_info.req_speeds = adv_link_speed; 225248cb27f2SChinh Cao 225348cb27f2SChinh Cao /* set link and auto negotiation so changes take effect */ 225448cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_LINK; 225548cb27f2SChinh Cao 2256aef74145SAnirudh Venkataramanan if (phy_type_low || phy_type_high) { 2257aef74145SAnirudh Venkataramanan config.phy_type_high = cpu_to_le64(phy_type_high) & 2258aef74145SAnirudh Venkataramanan abilities->phy_type_high; 225948cb27f2SChinh Cao config.phy_type_low = cpu_to_le64(phy_type_low) & 226048cb27f2SChinh Cao abilities->phy_type_low; 226148cb27f2SChinh Cao } else { 226248cb27f2SChinh Cao err = -EAGAIN; 226348cb27f2SChinh Cao netdev_info(netdev, "Nothing changed. No PHY_TYPE is corresponded to advertised link speed.\n"); 226448cb27f2SChinh Cao goto done; 226548cb27f2SChinh Cao } 226648cb27f2SChinh Cao 226748cb27f2SChinh Cao /* If link is up put link down */ 226848cb27f2SChinh Cao if (p->phy.link_info.link_info & ICE_AQ_LINK_UP) { 226948cb27f2SChinh Cao /* Tell the OS link is going down, the link will go 227048cb27f2SChinh Cao * back up when fw says it is ready asynchronously 227148cb27f2SChinh Cao */ 227248cb27f2SChinh Cao ice_print_link_msg(np->vsi, false); 227348cb27f2SChinh Cao netif_carrier_off(netdev); 227448cb27f2SChinh Cao netif_tx_stop_all_queues(netdev); 227548cb27f2SChinh Cao } 227648cb27f2SChinh Cao 227748cb27f2SChinh Cao /* make the aq call */ 227848cb27f2SChinh Cao status = ice_aq_set_phy_cfg(&pf->hw, lport, &config, NULL); 227948cb27f2SChinh Cao if (status) { 228048cb27f2SChinh Cao netdev_info(netdev, "Set phy config failed,\n"); 228148cb27f2SChinh Cao err = -EAGAIN; 228248cb27f2SChinh Cao } 228348cb27f2SChinh Cao 228448cb27f2SChinh Cao done: 228548cb27f2SChinh Cao devm_kfree(&pf->pdev->dev, abilities); 228648cb27f2SChinh Cao clear_bit(__ICE_CFG_BUSY, pf->state); 228748cb27f2SChinh Cao 228848cb27f2SChinh Cao return err; 228948cb27f2SChinh Cao } 229048cb27f2SChinh Cao 229148cb27f2SChinh Cao /** 2292f9867df6SAnirudh Venkataramanan * ice_get_rxnfc - command to get Rx flow classification rules 2293fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2294fcea6f3dSAnirudh Venkataramanan * @cmd: ethtool rxnfc command 2295fcea6f3dSAnirudh Venkataramanan * @rule_locs: buffer to rturn Rx flow classification rules 2296fcea6f3dSAnirudh Venkataramanan * 2297fcea6f3dSAnirudh Venkataramanan * Returns Success if the command is supported. 2298fcea6f3dSAnirudh Venkataramanan */ 2299c8b7abddSBruce Allan static int 2300c8b7abddSBruce Allan ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, 2301fcea6f3dSAnirudh Venkataramanan u32 __always_unused *rule_locs) 2302fcea6f3dSAnirudh Venkataramanan { 2303fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2304fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2305fcea6f3dSAnirudh Venkataramanan int ret = -EOPNOTSUPP; 2306fcea6f3dSAnirudh Venkataramanan 2307fcea6f3dSAnirudh Venkataramanan switch (cmd->cmd) { 2308fcea6f3dSAnirudh Venkataramanan case ETHTOOL_GRXRINGS: 2309fcea6f3dSAnirudh Venkataramanan cmd->data = vsi->rss_size; 2310fcea6f3dSAnirudh Venkataramanan ret = 0; 2311fcea6f3dSAnirudh Venkataramanan break; 2312fcea6f3dSAnirudh Venkataramanan default: 2313fcea6f3dSAnirudh Venkataramanan break; 2314fcea6f3dSAnirudh Venkataramanan } 2315fcea6f3dSAnirudh Venkataramanan 2316fcea6f3dSAnirudh Venkataramanan return ret; 2317fcea6f3dSAnirudh Venkataramanan } 2318fcea6f3dSAnirudh Venkataramanan 2319fcea6f3dSAnirudh Venkataramanan static void 2320fcea6f3dSAnirudh Venkataramanan ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 2321fcea6f3dSAnirudh Venkataramanan { 2322fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2323fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2324fcea6f3dSAnirudh Venkataramanan 2325fcea6f3dSAnirudh Venkataramanan ring->rx_max_pending = ICE_MAX_NUM_DESC; 2326fcea6f3dSAnirudh Venkataramanan ring->tx_max_pending = ICE_MAX_NUM_DESC; 2327fcea6f3dSAnirudh Venkataramanan ring->rx_pending = vsi->rx_rings[0]->count; 2328fcea6f3dSAnirudh Venkataramanan ring->tx_pending = vsi->tx_rings[0]->count; 2329f934bb9bSBruce Allan 2330f934bb9bSBruce Allan /* Rx mini and jumbo rings are not supported */ 2331fcea6f3dSAnirudh Venkataramanan ring->rx_mini_max_pending = 0; 2332fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_max_pending = 0; 2333f934bb9bSBruce Allan ring->rx_mini_pending = 0; 2334fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_pending = 0; 2335fcea6f3dSAnirudh Venkataramanan } 2336fcea6f3dSAnirudh Venkataramanan 2337fcea6f3dSAnirudh Venkataramanan static int 2338fcea6f3dSAnirudh Venkataramanan ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 2339fcea6f3dSAnirudh Venkataramanan { 2340fcea6f3dSAnirudh Venkataramanan struct ice_ring *tx_rings = NULL, *rx_rings = NULL; 2341fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2342fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2343fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2344fcea6f3dSAnirudh Venkataramanan int i, timeout = 50, err = 0; 2345fcea6f3dSAnirudh Venkataramanan u32 new_rx_cnt, new_tx_cnt; 2346fcea6f3dSAnirudh Venkataramanan 2347fcea6f3dSAnirudh Venkataramanan if (ring->tx_pending > ICE_MAX_NUM_DESC || 2348fcea6f3dSAnirudh Venkataramanan ring->tx_pending < ICE_MIN_NUM_DESC || 2349fcea6f3dSAnirudh Venkataramanan ring->rx_pending > ICE_MAX_NUM_DESC || 2350fcea6f3dSAnirudh Venkataramanan ring->rx_pending < ICE_MIN_NUM_DESC) { 2351f934bb9bSBruce Allan netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", 2352fcea6f3dSAnirudh Venkataramanan ring->tx_pending, ring->rx_pending, 2353f934bb9bSBruce Allan ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC, 2354f934bb9bSBruce Allan ICE_REQ_DESC_MULTIPLE); 2355fcea6f3dSAnirudh Venkataramanan return -EINVAL; 2356fcea6f3dSAnirudh Venkataramanan } 2357fcea6f3dSAnirudh Venkataramanan 2358fcea6f3dSAnirudh Venkataramanan new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE); 2359f934bb9bSBruce Allan if (new_tx_cnt != ring->tx_pending) 2360f934bb9bSBruce Allan netdev_info(netdev, 2361f934bb9bSBruce Allan "Requested Tx descriptor count rounded up to %d\n", 2362f934bb9bSBruce Allan new_tx_cnt); 2363fcea6f3dSAnirudh Venkataramanan new_rx_cnt = ALIGN(ring->rx_pending, ICE_REQ_DESC_MULTIPLE); 2364f934bb9bSBruce Allan if (new_rx_cnt != ring->rx_pending) 2365f934bb9bSBruce Allan netdev_info(netdev, 2366f934bb9bSBruce Allan "Requested Rx descriptor count rounded up to %d\n", 2367f934bb9bSBruce Allan new_rx_cnt); 2368fcea6f3dSAnirudh Venkataramanan 2369fcea6f3dSAnirudh Venkataramanan /* if nothing to do return success */ 2370fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count && 2371fcea6f3dSAnirudh Venkataramanan new_rx_cnt == vsi->rx_rings[0]->count) { 2372fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); 2373fcea6f3dSAnirudh Venkataramanan return 0; 2374fcea6f3dSAnirudh Venkataramanan } 2375fcea6f3dSAnirudh Venkataramanan 2376fcea6f3dSAnirudh Venkataramanan while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 2377fcea6f3dSAnirudh Venkataramanan timeout--; 2378fcea6f3dSAnirudh Venkataramanan if (!timeout) 2379fcea6f3dSAnirudh Venkataramanan return -EBUSY; 2380fcea6f3dSAnirudh Venkataramanan usleep_range(1000, 2000); 2381fcea6f3dSAnirudh Venkataramanan } 2382fcea6f3dSAnirudh Venkataramanan 2383fcea6f3dSAnirudh Venkataramanan /* set for the next time the netdev is started */ 2384fcea6f3dSAnirudh Venkataramanan if (!netif_running(vsi->netdev)) { 2385fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) 2386fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[i]->count = new_tx_cnt; 2387fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) 2388fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[i]->count = new_rx_cnt; 2389fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Link is down, descriptor count change happens when link is brought up\n"); 2390fcea6f3dSAnirudh Venkataramanan goto done; 2391fcea6f3dSAnirudh Venkataramanan } 2392fcea6f3dSAnirudh Venkataramanan 2393fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count) 2394fcea6f3dSAnirudh Venkataramanan goto process_rx; 2395fcea6f3dSAnirudh Venkataramanan 2396fcea6f3dSAnirudh Venkataramanan /* alloc updated Tx resources */ 2397fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Tx descriptor count from %d to %d\n", 2398fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[0]->count, new_tx_cnt); 2399fcea6f3dSAnirudh Venkataramanan 2400fcea6f3dSAnirudh Venkataramanan tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 2401c6dfd690SBruce Allan sizeof(*tx_rings), GFP_KERNEL); 2402fcea6f3dSAnirudh Venkataramanan if (!tx_rings) { 2403fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2404fcea6f3dSAnirudh Venkataramanan goto done; 2405fcea6f3dSAnirudh Venkataramanan } 2406fcea6f3dSAnirudh Venkataramanan 2407f8ba7db8SJacob Keller for (i = 0; i < vsi->alloc_txq; i++) { 2408fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 2409fcea6f3dSAnirudh Venkataramanan tx_rings[i] = *vsi->tx_rings[i]; 2410fcea6f3dSAnirudh Venkataramanan tx_rings[i].count = new_tx_cnt; 2411fcea6f3dSAnirudh Venkataramanan tx_rings[i].desc = NULL; 2412fcea6f3dSAnirudh Venkataramanan tx_rings[i].tx_buf = NULL; 2413fcea6f3dSAnirudh Venkataramanan err = ice_setup_tx_ring(&tx_rings[i]); 2414fcea6f3dSAnirudh Venkataramanan if (err) { 2415fcea6f3dSAnirudh Venkataramanan while (i) { 2416fcea6f3dSAnirudh Venkataramanan i--; 2417fcea6f3dSAnirudh Venkataramanan ice_clean_tx_ring(&tx_rings[i]); 2418fcea6f3dSAnirudh Venkataramanan } 2419fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 2420fcea6f3dSAnirudh Venkataramanan goto done; 2421fcea6f3dSAnirudh Venkataramanan } 2422fcea6f3dSAnirudh Venkataramanan } 2423fcea6f3dSAnirudh Venkataramanan 2424fcea6f3dSAnirudh Venkataramanan process_rx: 2425fcea6f3dSAnirudh Venkataramanan if (new_rx_cnt == vsi->rx_rings[0]->count) 2426fcea6f3dSAnirudh Venkataramanan goto process_link; 2427fcea6f3dSAnirudh Venkataramanan 2428fcea6f3dSAnirudh Venkataramanan /* alloc updated Rx resources */ 2429fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Rx descriptor count from %d to %d\n", 2430fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[0]->count, new_rx_cnt); 2431fcea6f3dSAnirudh Venkataramanan 2432fcea6f3dSAnirudh Venkataramanan rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 2433c6dfd690SBruce Allan sizeof(*rx_rings), GFP_KERNEL); 2434fcea6f3dSAnirudh Venkataramanan if (!rx_rings) { 2435fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2436fcea6f3dSAnirudh Venkataramanan goto done; 2437fcea6f3dSAnirudh Venkataramanan } 2438fcea6f3dSAnirudh Venkataramanan 2439f8ba7db8SJacob Keller for (i = 0; i < vsi->alloc_rxq; i++) { 2440fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 2441fcea6f3dSAnirudh Venkataramanan rx_rings[i] = *vsi->rx_rings[i]; 2442fcea6f3dSAnirudh Venkataramanan rx_rings[i].count = new_rx_cnt; 2443fcea6f3dSAnirudh Venkataramanan rx_rings[i].desc = NULL; 2444fcea6f3dSAnirudh Venkataramanan rx_rings[i].rx_buf = NULL; 2445fcea6f3dSAnirudh Venkataramanan /* this is to allow wr32 to have something to write to 2446fcea6f3dSAnirudh Venkataramanan * during early allocation of Rx buffers 2447fcea6f3dSAnirudh Venkataramanan */ 2448fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->back->hw.hw_addr + PRTGEN_STATUS; 2449fcea6f3dSAnirudh Venkataramanan 2450fcea6f3dSAnirudh Venkataramanan err = ice_setup_rx_ring(&rx_rings[i]); 2451fcea6f3dSAnirudh Venkataramanan if (err) 2452fcea6f3dSAnirudh Venkataramanan goto rx_unwind; 2453fcea6f3dSAnirudh Venkataramanan 2454fcea6f3dSAnirudh Venkataramanan /* allocate Rx buffers */ 2455fcea6f3dSAnirudh Venkataramanan err = ice_alloc_rx_bufs(&rx_rings[i], 2456fcea6f3dSAnirudh Venkataramanan ICE_DESC_UNUSED(&rx_rings[i])); 2457fcea6f3dSAnirudh Venkataramanan rx_unwind: 2458fcea6f3dSAnirudh Venkataramanan if (err) { 2459fcea6f3dSAnirudh Venkataramanan while (i) { 2460fcea6f3dSAnirudh Venkataramanan i--; 2461fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(&rx_rings[i]); 2462fcea6f3dSAnirudh Venkataramanan } 2463fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, rx_rings); 2464fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2465fcea6f3dSAnirudh Venkataramanan goto free_tx; 2466fcea6f3dSAnirudh Venkataramanan } 2467fcea6f3dSAnirudh Venkataramanan } 2468fcea6f3dSAnirudh Venkataramanan 2469fcea6f3dSAnirudh Venkataramanan process_link: 2470fcea6f3dSAnirudh Venkataramanan /* Bring interface down, copy in the new ring info, then restore the 2471fcea6f3dSAnirudh Venkataramanan * interface. if VSI is up, bring it down and then back up 2472fcea6f3dSAnirudh Venkataramanan */ 2473fcea6f3dSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) { 2474fcea6f3dSAnirudh Venkataramanan ice_down(vsi); 2475fcea6f3dSAnirudh Venkataramanan 2476fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 2477fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 2478fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 2479fcea6f3dSAnirudh Venkataramanan *vsi->tx_rings[i] = tx_rings[i]; 2480fcea6f3dSAnirudh Venkataramanan } 2481fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 2482fcea6f3dSAnirudh Venkataramanan } 2483fcea6f3dSAnirudh Venkataramanan 2484fcea6f3dSAnirudh Venkataramanan if (rx_rings) { 2485fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 2486fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 2487fcea6f3dSAnirudh Venkataramanan /* copy the real tail offset */ 2488fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->rx_rings[i]->tail; 2489fcea6f3dSAnirudh Venkataramanan /* this is to fake out the allocation routine 2490fcea6f3dSAnirudh Venkataramanan * into thinking it has to realloc everything 2491fcea6f3dSAnirudh Venkataramanan * but the recycling logic will let us re-use 2492fcea6f3dSAnirudh Venkataramanan * the buffers allocated above 2493fcea6f3dSAnirudh Venkataramanan */ 2494fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_use = 0; 2495fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_clean = 0; 2496fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_alloc = 0; 2497fcea6f3dSAnirudh Venkataramanan *vsi->rx_rings[i] = rx_rings[i]; 2498fcea6f3dSAnirudh Venkataramanan } 2499fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, rx_rings); 2500fcea6f3dSAnirudh Venkataramanan } 2501fcea6f3dSAnirudh Venkataramanan 2502fcea6f3dSAnirudh Venkataramanan ice_up(vsi); 2503fcea6f3dSAnirudh Venkataramanan } 2504fcea6f3dSAnirudh Venkataramanan goto done; 2505fcea6f3dSAnirudh Venkataramanan 2506fcea6f3dSAnirudh Venkataramanan free_tx: 2507fcea6f3dSAnirudh Venkataramanan /* error cleanup if the Rx allocations failed after getting Tx */ 2508fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 2509fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) 2510fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(&tx_rings[i]); 2511fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 2512fcea6f3dSAnirudh Venkataramanan } 2513fcea6f3dSAnirudh Venkataramanan 2514fcea6f3dSAnirudh Venkataramanan done: 2515fcea6f3dSAnirudh Venkataramanan clear_bit(__ICE_CFG_BUSY, pf->state); 2516fcea6f3dSAnirudh Venkataramanan return err; 2517fcea6f3dSAnirudh Venkataramanan } 2518fcea6f3dSAnirudh Venkataramanan 2519fcea6f3dSAnirudh Venkataramanan static int ice_nway_reset(struct net_device *netdev) 2520fcea6f3dSAnirudh Venkataramanan { 2521fcea6f3dSAnirudh Venkataramanan /* restart autonegotiation */ 2522fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2523fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2524fcea6f3dSAnirudh Venkataramanan struct ice_port_info *pi; 2525fcea6f3dSAnirudh Venkataramanan enum ice_status status; 2526fcea6f3dSAnirudh Venkataramanan 2527fcea6f3dSAnirudh Venkataramanan pi = vsi->port_info; 2528d38b0883SAkeem G Abodunrin /* If VSI state is up, then restart autoneg with link up */ 2529d38b0883SAkeem G Abodunrin if (!test_bit(__ICE_DOWN, vsi->back->state)) 2530d38b0883SAkeem G Abodunrin status = ice_aq_set_link_restart_an(pi, true, NULL); 2531d38b0883SAkeem G Abodunrin else 2532d38b0883SAkeem G Abodunrin status = ice_aq_set_link_restart_an(pi, false, NULL); 2533fcea6f3dSAnirudh Venkataramanan 2534fcea6f3dSAnirudh Venkataramanan if (status) { 2535fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "link restart failed, err %d aq_err %d\n", 2536fcea6f3dSAnirudh Venkataramanan status, pi->hw->adminq.sq_last_status); 2537fcea6f3dSAnirudh Venkataramanan return -EIO; 2538fcea6f3dSAnirudh Venkataramanan } 2539fcea6f3dSAnirudh Venkataramanan 2540fcea6f3dSAnirudh Venkataramanan return 0; 2541fcea6f3dSAnirudh Venkataramanan } 2542fcea6f3dSAnirudh Venkataramanan 2543fcea6f3dSAnirudh Venkataramanan /** 2544fcea6f3dSAnirudh Venkataramanan * ice_get_pauseparam - Get Flow Control status 2545fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2546fcea6f3dSAnirudh Venkataramanan * @pause: ethernet pause (flow control) parameters 2547fcea6f3dSAnirudh Venkataramanan */ 2548fcea6f3dSAnirudh Venkataramanan static void 2549fcea6f3dSAnirudh Venkataramanan ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 2550fcea6f3dSAnirudh Venkataramanan { 2551fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 255240c3c546SLukasz Czapnik struct ice_port_info *pi = np->vsi->port_info; 255340c3c546SLukasz Czapnik struct ice_aqc_get_phy_caps_data *pcaps; 255440c3c546SLukasz Czapnik struct ice_vsi *vsi = np->vsi; 25553a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 255640c3c546SLukasz Czapnik enum ice_status status; 2557fcea6f3dSAnirudh Venkataramanan 255840c3c546SLukasz Czapnik /* Initialize pause params */ 255940c3c546SLukasz Czapnik pause->rx_pause = 0; 256040c3c546SLukasz Czapnik pause->tx_pause = 0; 256140c3c546SLukasz Czapnik 25623a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 25633a257a14SAnirudh Venkataramanan 256440c3c546SLukasz Czapnik pcaps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*pcaps), 256540c3c546SLukasz Czapnik GFP_KERNEL); 256640c3c546SLukasz Czapnik if (!pcaps) 256740c3c546SLukasz Czapnik return; 256840c3c546SLukasz Czapnik 2569f9867df6SAnirudh Venkataramanan /* Get current PHY config */ 257040c3c546SLukasz Czapnik status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, 257140c3c546SLukasz Czapnik NULL); 257240c3c546SLukasz Czapnik if (status) 257340c3c546SLukasz Czapnik goto out; 257440c3c546SLukasz Czapnik 257540c3c546SLukasz Czapnik pause->autoneg = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ? 2576fcea6f3dSAnirudh Venkataramanan AUTONEG_ENABLE : AUTONEG_DISABLE); 2577fcea6f3dSAnirudh Venkataramanan 25783a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) 25793a257a14SAnirudh Venkataramanan /* PFC enabled so report LFC as off */ 25803a257a14SAnirudh Venkataramanan goto out; 25813a257a14SAnirudh Venkataramanan 258240c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) 2583fcea6f3dSAnirudh Venkataramanan pause->tx_pause = 1; 258440c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 2585fcea6f3dSAnirudh Venkataramanan pause->rx_pause = 1; 258640c3c546SLukasz Czapnik 258740c3c546SLukasz Czapnik out: 258840c3c546SLukasz Czapnik devm_kfree(&vsi->back->pdev->dev, pcaps); 2589fcea6f3dSAnirudh Venkataramanan } 2590fcea6f3dSAnirudh Venkataramanan 2591fcea6f3dSAnirudh Venkataramanan /** 2592fcea6f3dSAnirudh Venkataramanan * ice_set_pauseparam - Set Flow Control parameter 2593fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2594d337f2afSAnirudh Venkataramanan * @pause: return Tx/Rx flow control status 2595fcea6f3dSAnirudh Venkataramanan */ 2596fcea6f3dSAnirudh Venkataramanan static int 2597fcea6f3dSAnirudh Venkataramanan ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 2598fcea6f3dSAnirudh Venkataramanan { 2599fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2600fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 2601fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 26023a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 2603fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2604fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2605fcea6f3dSAnirudh Venkataramanan struct ice_port_info *pi; 2606fcea6f3dSAnirudh Venkataramanan enum ice_status status; 2607fcea6f3dSAnirudh Venkataramanan u8 aq_failures; 2608fcea6f3dSAnirudh Venkataramanan bool link_up; 2609fcea6f3dSAnirudh Venkataramanan int err = 0; 2610fcea6f3dSAnirudh Venkataramanan 2611fcea6f3dSAnirudh Venkataramanan pi = vsi->port_info; 2612fcea6f3dSAnirudh Venkataramanan hw_link_info = &pi->phy.link_info; 26133a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 2614fcea6f3dSAnirudh Venkataramanan link_up = hw_link_info->link_info & ICE_AQ_LINK_UP; 2615fcea6f3dSAnirudh Venkataramanan 2616fcea6f3dSAnirudh Venkataramanan /* Changing the port's flow control is not supported if this isn't the 2617fcea6f3dSAnirudh Venkataramanan * PF VSI 2618fcea6f3dSAnirudh Venkataramanan */ 2619fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) { 2620fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing flow control parameters only supported for PF VSI\n"); 2621fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2622fcea6f3dSAnirudh Venkataramanan } 2623fcea6f3dSAnirudh Venkataramanan 2624fcea6f3dSAnirudh Venkataramanan if (pause->autoneg != (hw_link_info->an_info & ICE_AQ_AN_COMPLETED)) { 2625fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n"); 2626fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2627fcea6f3dSAnirudh Venkataramanan } 2628fcea6f3dSAnirudh Venkataramanan 2629fcea6f3dSAnirudh Venkataramanan /* If we have link and don't have autoneg */ 2630fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state) && 2631fcea6f3dSAnirudh Venkataramanan !(hw_link_info->an_info & ICE_AQ_AN_COMPLETED)) { 2632fcea6f3dSAnirudh Venkataramanan /* Send message that it might not necessarily work*/ 2633fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n"); 2634fcea6f3dSAnirudh Venkataramanan } 2635fcea6f3dSAnirudh Venkataramanan 26363a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) { 26373a257a14SAnirudh Venkataramanan netdev_info(netdev, "Priority flow control enabled. Cannot set link flow control.\n"); 26383a257a14SAnirudh Venkataramanan return -EOPNOTSUPP; 26393a257a14SAnirudh Venkataramanan } 2640fcea6f3dSAnirudh Venkataramanan if (pause->rx_pause && pause->tx_pause) 2641fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_FULL; 2642fcea6f3dSAnirudh Venkataramanan else if (pause->rx_pause && !pause->tx_pause) 2643fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_RX_PAUSE; 2644fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && pause->tx_pause) 2645fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_TX_PAUSE; 2646fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && !pause->tx_pause) 2647fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_NONE; 2648fcea6f3dSAnirudh Venkataramanan else 2649fcea6f3dSAnirudh Venkataramanan return -EINVAL; 2650fcea6f3dSAnirudh Venkataramanan 2651fcea6f3dSAnirudh Venkataramanan /* Tell the OS link is going down, the link will go back up when fw 2652fcea6f3dSAnirudh Venkataramanan * says it is ready asynchronously 2653fcea6f3dSAnirudh Venkataramanan */ 2654fcea6f3dSAnirudh Venkataramanan ice_print_link_msg(vsi, false); 2655fcea6f3dSAnirudh Venkataramanan netif_carrier_off(netdev); 2656fcea6f3dSAnirudh Venkataramanan netif_tx_stop_all_queues(netdev); 2657fcea6f3dSAnirudh Venkataramanan 2658fcea6f3dSAnirudh Venkataramanan /* Set the FC mode and only restart AN if link is up */ 2659fcea6f3dSAnirudh Venkataramanan status = ice_set_fc(pi, &aq_failures, link_up); 2660fcea6f3dSAnirudh Venkataramanan 2661fcea6f3dSAnirudh Venkataramanan if (aq_failures & ICE_SET_FC_AQ_FAIL_GET) { 2662fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the get_phy_capabilities call with err %d aq_err %d\n", 2663fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2664fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2665fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_SET) { 2666fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the set_phy_config call with err %d aq_err %d\n", 2667fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2668fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2669fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_UPDATE) { 2670fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the get_link_info call with err %d aq_err %d\n", 2671fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2672fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2673fcea6f3dSAnirudh Venkataramanan } 2674fcea6f3dSAnirudh Venkataramanan 2675fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) { 26760f5d4c21SAkeem G Abodunrin /* Give it a little more time to try to come back. If still 26770f5d4c21SAkeem G Abodunrin * down, restart autoneg link or reinitialize the interface. 26780f5d4c21SAkeem G Abodunrin */ 2679fcea6f3dSAnirudh Venkataramanan msleep(75); 2680fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) 2681fcea6f3dSAnirudh Venkataramanan return ice_nway_reset(netdev); 26820f5d4c21SAkeem G Abodunrin 26830f5d4c21SAkeem G Abodunrin ice_down(vsi); 26840f5d4c21SAkeem G Abodunrin ice_up(vsi); 2685fcea6f3dSAnirudh Venkataramanan } 2686fcea6f3dSAnirudh Venkataramanan 2687fcea6f3dSAnirudh Venkataramanan return err; 2688fcea6f3dSAnirudh Venkataramanan } 2689fcea6f3dSAnirudh Venkataramanan 2690fcea6f3dSAnirudh Venkataramanan /** 2691fcea6f3dSAnirudh Venkataramanan * ice_get_rxfh_key_size - get the RSS hash key size 2692fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2693fcea6f3dSAnirudh Venkataramanan * 2694fcea6f3dSAnirudh Venkataramanan * Returns the table size. 2695fcea6f3dSAnirudh Venkataramanan */ 2696fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_key_size(struct net_device __always_unused *netdev) 2697fcea6f3dSAnirudh Venkataramanan { 2698fcea6f3dSAnirudh Venkataramanan return ICE_VSIQF_HKEY_ARRAY_SIZE; 2699fcea6f3dSAnirudh Venkataramanan } 2700fcea6f3dSAnirudh Venkataramanan 2701fcea6f3dSAnirudh Venkataramanan /** 2702d337f2afSAnirudh Venkataramanan * ice_get_rxfh_indir_size - get the Rx flow hash indirection table size 2703fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2704fcea6f3dSAnirudh Venkataramanan * 2705fcea6f3dSAnirudh Venkataramanan * Returns the table size. 2706fcea6f3dSAnirudh Venkataramanan */ 2707fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_indir_size(struct net_device *netdev) 2708fcea6f3dSAnirudh Venkataramanan { 2709fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2710fcea6f3dSAnirudh Venkataramanan 2711fcea6f3dSAnirudh Venkataramanan return np->vsi->rss_table_size; 2712fcea6f3dSAnirudh Venkataramanan } 2713fcea6f3dSAnirudh Venkataramanan 2714fcea6f3dSAnirudh Venkataramanan /** 2715d337f2afSAnirudh Venkataramanan * ice_get_rxfh - get the Rx flow hash indirection table 2716fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2717fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 2718fcea6f3dSAnirudh Venkataramanan * @key: hash key 2719fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 2720fcea6f3dSAnirudh Venkataramanan * 2721fcea6f3dSAnirudh Venkataramanan * Reads the indirection table directly from the hardware. 2722fcea6f3dSAnirudh Venkataramanan */ 2723fcea6f3dSAnirudh Venkataramanan static int 2724fcea6f3dSAnirudh Venkataramanan ice_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) 2725fcea6f3dSAnirudh Venkataramanan { 2726fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2727fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2728fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2729fcea6f3dSAnirudh Venkataramanan int ret = 0, i; 2730fcea6f3dSAnirudh Venkataramanan u8 *lut; 2731fcea6f3dSAnirudh Venkataramanan 2732fcea6f3dSAnirudh Venkataramanan if (hfunc) 2733fcea6f3dSAnirudh Venkataramanan *hfunc = ETH_RSS_HASH_TOP; 2734fcea6f3dSAnirudh Venkataramanan 2735fcea6f3dSAnirudh Venkataramanan if (!indir) 2736fcea6f3dSAnirudh Venkataramanan return 0; 2737fcea6f3dSAnirudh Venkataramanan 2738fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 2739fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 2740fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 2741fcea6f3dSAnirudh Venkataramanan return -EIO; 2742fcea6f3dSAnirudh Venkataramanan } 2743fcea6f3dSAnirudh Venkataramanan 2744fcea6f3dSAnirudh Venkataramanan lut = devm_kzalloc(&pf->pdev->dev, vsi->rss_table_size, GFP_KERNEL); 2745fcea6f3dSAnirudh Venkataramanan if (!lut) 2746fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 2747fcea6f3dSAnirudh Venkataramanan 2748fcea6f3dSAnirudh Venkataramanan if (ice_get_rss(vsi, key, lut, vsi->rss_table_size)) { 2749fcea6f3dSAnirudh Venkataramanan ret = -EIO; 2750fcea6f3dSAnirudh Venkataramanan goto out; 2751fcea6f3dSAnirudh Venkataramanan } 2752fcea6f3dSAnirudh Venkataramanan 2753fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 2754fcea6f3dSAnirudh Venkataramanan indir[i] = (u32)(lut[i]); 2755fcea6f3dSAnirudh Venkataramanan 2756fcea6f3dSAnirudh Venkataramanan out: 2757fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, lut); 2758fcea6f3dSAnirudh Venkataramanan return ret; 2759fcea6f3dSAnirudh Venkataramanan } 2760fcea6f3dSAnirudh Venkataramanan 2761fcea6f3dSAnirudh Venkataramanan /** 2762d337f2afSAnirudh Venkataramanan * ice_set_rxfh - set the Rx flow hash indirection table 2763fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2764fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 2765fcea6f3dSAnirudh Venkataramanan * @key: hash key 2766fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 2767fcea6f3dSAnirudh Venkataramanan * 2768f9867df6SAnirudh Venkataramanan * Returns -EINVAL if the table specifies an invalid queue ID, otherwise 2769fcea6f3dSAnirudh Venkataramanan * returns 0 after programming the table. 2770fcea6f3dSAnirudh Venkataramanan */ 2771c8b7abddSBruce Allan static int 2772c8b7abddSBruce Allan ice_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, 2773c8b7abddSBruce Allan const u8 hfunc) 2774fcea6f3dSAnirudh Venkataramanan { 2775fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2776fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2777fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2778fcea6f3dSAnirudh Venkataramanan u8 *seed = NULL; 2779fcea6f3dSAnirudh Venkataramanan 2780fcea6f3dSAnirudh Venkataramanan if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 2781fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2782fcea6f3dSAnirudh Venkataramanan 2783fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 2784fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 2785fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 2786fcea6f3dSAnirudh Venkataramanan return -EIO; 2787fcea6f3dSAnirudh Venkataramanan } 2788fcea6f3dSAnirudh Venkataramanan 2789fcea6f3dSAnirudh Venkataramanan if (key) { 2790fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) { 2791fcea6f3dSAnirudh Venkataramanan vsi->rss_hkey_user = 2792fcea6f3dSAnirudh Venkataramanan devm_kzalloc(&pf->pdev->dev, 2793fcea6f3dSAnirudh Venkataramanan ICE_VSIQF_HKEY_ARRAY_SIZE, 2794fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 2795fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) 2796fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 2797fcea6f3dSAnirudh Venkataramanan } 2798fcea6f3dSAnirudh Venkataramanan memcpy(vsi->rss_hkey_user, key, ICE_VSIQF_HKEY_ARRAY_SIZE); 2799fcea6f3dSAnirudh Venkataramanan seed = vsi->rss_hkey_user; 2800fcea6f3dSAnirudh Venkataramanan } 2801fcea6f3dSAnirudh Venkataramanan 2802fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) { 2803fcea6f3dSAnirudh Venkataramanan vsi->rss_lut_user = devm_kzalloc(&pf->pdev->dev, 2804fcea6f3dSAnirudh Venkataramanan vsi->rss_table_size, 2805fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 2806fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) 2807fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 2808fcea6f3dSAnirudh Venkataramanan } 2809fcea6f3dSAnirudh Venkataramanan 2810fcea6f3dSAnirudh Venkataramanan /* Each 32 bits pointed by 'indir' is stored with a lut entry */ 2811fcea6f3dSAnirudh Venkataramanan if (indir) { 2812fcea6f3dSAnirudh Venkataramanan int i; 2813fcea6f3dSAnirudh Venkataramanan 2814fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 2815fcea6f3dSAnirudh Venkataramanan vsi->rss_lut_user[i] = (u8)(indir[i]); 2816fcea6f3dSAnirudh Venkataramanan } else { 2817fcea6f3dSAnirudh Venkataramanan ice_fill_rss_lut(vsi->rss_lut_user, vsi->rss_table_size, 2818fcea6f3dSAnirudh Venkataramanan vsi->rss_size); 2819fcea6f3dSAnirudh Venkataramanan } 2820fcea6f3dSAnirudh Venkataramanan 2821fcea6f3dSAnirudh Venkataramanan if (ice_set_rss(vsi, seed, vsi->rss_lut_user, vsi->rss_table_size)) 2822fcea6f3dSAnirudh Venkataramanan return -EIO; 2823fcea6f3dSAnirudh Venkataramanan 2824fcea6f3dSAnirudh Venkataramanan return 0; 2825fcea6f3dSAnirudh Venkataramanan } 2826fcea6f3dSAnirudh Venkataramanan 282767fe64d7SBrett Creeley enum ice_container_type { 282867fe64d7SBrett Creeley ICE_RX_CONTAINER, 282967fe64d7SBrett Creeley ICE_TX_CONTAINER, 283067fe64d7SBrett Creeley }; 283167fe64d7SBrett Creeley 283267fe64d7SBrett Creeley /** 283367fe64d7SBrett Creeley * ice_get_rc_coalesce - get ITR values for specific ring container 283467fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 2835f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 283667fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 283767fe64d7SBrett Creeley * 283867fe64d7SBrett Creeley * Query the device for ice_ring_container specific ITR values. This is 283967fe64d7SBrett Creeley * done per ice_ring_container because each q_vector can have 1 or more rings 284067fe64d7SBrett Creeley * and all of said ring(s) will have the same ITR values. 284167fe64d7SBrett Creeley * 284267fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 284367fe64d7SBrett Creeley */ 284467fe64d7SBrett Creeley static int 284567fe64d7SBrett Creeley ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, 284667fe64d7SBrett Creeley struct ice_ring_container *rc) 284767fe64d7SBrett Creeley { 2848b9c8bb06SBrett Creeley struct ice_pf *pf; 2849b9c8bb06SBrett Creeley 2850b9c8bb06SBrett Creeley if (!rc->ring) 2851b9c8bb06SBrett Creeley return -EINVAL; 2852b9c8bb06SBrett Creeley 2853b9c8bb06SBrett Creeley pf = rc->ring->vsi->back; 285467fe64d7SBrett Creeley 285567fe64d7SBrett Creeley switch (c_type) { 285667fe64d7SBrett Creeley case ICE_RX_CONTAINER: 285767fe64d7SBrett Creeley ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 285867fe64d7SBrett Creeley ec->rx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 2859b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high = rc->ring->q_vector->intrl; 286067fe64d7SBrett Creeley break; 286167fe64d7SBrett Creeley case ICE_TX_CONTAINER: 286267fe64d7SBrett Creeley ec->use_adaptive_tx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 286367fe64d7SBrett Creeley ec->tx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 286467fe64d7SBrett Creeley break; 286567fe64d7SBrett Creeley default: 286667fe64d7SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid c_type %d\n", c_type); 286767fe64d7SBrett Creeley return -EINVAL; 286867fe64d7SBrett Creeley } 286967fe64d7SBrett Creeley 287067fe64d7SBrett Creeley return 0; 287167fe64d7SBrett Creeley } 287267fe64d7SBrett Creeley 287367fe64d7SBrett Creeley /** 2874e40c899aSBrett Creeley * ice_get_q_coalesce - get a queue's ITR/INTRL (coalesce) settings 2875e40c899aSBrett Creeley * @vsi: VSI associated to the queue for getting ITR/INTRL (coalesce) settings 2876e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 2877e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 2878e40c899aSBrett Creeley * 2879e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 2880e40c899aSBrett Creeley * 1. Getting Tx or Rx ITR/INTRL (coalesce) settings failed. 2881e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 2882e40c899aSBrett Creeley */ 2883e40c899aSBrett Creeley static int 2884e40c899aSBrett Creeley ice_get_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 2885e40c899aSBrett Creeley { 2886e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 2887e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2888e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 2889e40c899aSBrett Creeley return -EINVAL; 2890e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2891e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 2892e40c899aSBrett Creeley return -EINVAL; 2893e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 2894e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 2895e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 2896e40c899aSBrett Creeley return -EINVAL; 2897e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 2898e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 2899e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 2900e40c899aSBrett Creeley return -EINVAL; 2901e40c899aSBrett Creeley } else { 2902e40c899aSBrett Creeley return -EINVAL; 2903e40c899aSBrett Creeley } 2904e40c899aSBrett Creeley 2905e40c899aSBrett Creeley return 0; 2906e40c899aSBrett Creeley } 2907e40c899aSBrett Creeley 2908e40c899aSBrett Creeley /** 290967fe64d7SBrett Creeley * __ice_get_coalesce - get ITR/INTRL values for the device 291067fe64d7SBrett Creeley * @netdev: pointer to the netdev associated with this query 291167fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 291267fe64d7SBrett Creeley * @q_num: queue number to get the coalesce settings for 2913e40c899aSBrett Creeley * 2914e40c899aSBrett Creeley * If the caller passes in a negative q_num then we return coalesce settings 2915e40c899aSBrett Creeley * based on queue number 0, else use the actual q_num passed in. 291667fe64d7SBrett Creeley */ 291767fe64d7SBrett Creeley static int 291867fe64d7SBrett Creeley __ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 291967fe64d7SBrett Creeley int q_num) 292067fe64d7SBrett Creeley { 292167fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 292267fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 292367fe64d7SBrett Creeley 2924e40c899aSBrett Creeley if (q_num < 0) 2925e40c899aSBrett Creeley q_num = 0; 292667fe64d7SBrett Creeley 2927e40c899aSBrett Creeley if (ice_get_q_coalesce(vsi, ec, q_num)) 292867fe64d7SBrett Creeley return -EINVAL; 292967fe64d7SBrett Creeley 293067fe64d7SBrett Creeley if (q_num < vsi->num_txq) 293167fe64d7SBrett Creeley ec->tx_max_coalesced_frames_irq = vsi->work_lmt; 293267fe64d7SBrett Creeley 293367fe64d7SBrett Creeley if (q_num < vsi->num_rxq) 293467fe64d7SBrett Creeley ec->rx_max_coalesced_frames_irq = vsi->work_lmt; 293567fe64d7SBrett Creeley 293667fe64d7SBrett Creeley return 0; 293767fe64d7SBrett Creeley } 293867fe64d7SBrett Creeley 293967fe64d7SBrett Creeley static int 294067fe64d7SBrett Creeley ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 294167fe64d7SBrett Creeley { 294267fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, -1); 294367fe64d7SBrett Creeley } 294467fe64d7SBrett Creeley 2945c8b7abddSBruce Allan static int 2946c8b7abddSBruce Allan ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num, 294767fe64d7SBrett Creeley struct ethtool_coalesce *ec) 294867fe64d7SBrett Creeley { 294967fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, q_num); 295067fe64d7SBrett Creeley } 295167fe64d7SBrett Creeley 295267fe64d7SBrett Creeley /** 295367fe64d7SBrett Creeley * ice_set_rc_coalesce - set ITR values for specific ring container 2954f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 295567fe64d7SBrett Creeley * @ec: ethtool structure from user to update ITR settings 295667fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 295767fe64d7SBrett Creeley * @vsi: VSI associated to the ring container 295867fe64d7SBrett Creeley * 295967fe64d7SBrett Creeley * Set specific ITR values. This is done per ice_ring_container because each 296067fe64d7SBrett Creeley * q_vector can have 1 or more rings and all of said ring(s) will have the same 296167fe64d7SBrett Creeley * ITR values. 296267fe64d7SBrett Creeley * 296367fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 296467fe64d7SBrett Creeley */ 296567fe64d7SBrett Creeley static int 296667fe64d7SBrett Creeley ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec, 296767fe64d7SBrett Creeley struct ice_ring_container *rc, struct ice_vsi *vsi) 296867fe64d7SBrett Creeley { 296967fe64d7SBrett Creeley struct ice_pf *pf = vsi->back; 297067fe64d7SBrett Creeley u16 itr_setting; 297167fe64d7SBrett Creeley 297267fe64d7SBrett Creeley if (!rc->ring) 297367fe64d7SBrett Creeley return -EINVAL; 297467fe64d7SBrett Creeley 297567fe64d7SBrett Creeley itr_setting = rc->itr_setting & ~ICE_ITR_DYNAMIC; 297667fe64d7SBrett Creeley 297767fe64d7SBrett Creeley switch (c_type) { 297867fe64d7SBrett Creeley case ICE_RX_CONTAINER: 2979b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high > ICE_MAX_INTRL || 2980b9c8bb06SBrett Creeley (ec->rx_coalesce_usecs_high && 2981b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high < pf->hw.intrl_gran)) { 2982b9c8bb06SBrett Creeley netdev_info(vsi->netdev, 2983b9c8bb06SBrett Creeley "Invalid value, rx-usecs-high valid values are 0 (disabled), %d-%d\n", 2984b9c8bb06SBrett Creeley pf->hw.intrl_gran, ICE_MAX_INTRL); 2985b9c8bb06SBrett Creeley return -EINVAL; 2986b9c8bb06SBrett Creeley } 2987b9c8bb06SBrett Creeley 2988b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high != rc->ring->q_vector->intrl) { 2989b9c8bb06SBrett Creeley rc->ring->q_vector->intrl = ec->rx_coalesce_usecs_high; 2990cbe66bfeSBrett Creeley wr32(&pf->hw, GLINT_RATE(rc->ring->q_vector->reg_idx), 2991b9c8bb06SBrett Creeley ice_intrl_usec_to_reg(ec->rx_coalesce_usecs_high, 2992b9c8bb06SBrett Creeley pf->hw.intrl_gran)); 2993b9c8bb06SBrett Creeley } 2994b9c8bb06SBrett Creeley 299567fe64d7SBrett Creeley if (ec->rx_coalesce_usecs != itr_setting && 299667fe64d7SBrett Creeley ec->use_adaptive_rx_coalesce) { 299767fe64d7SBrett Creeley netdev_info(vsi->netdev, 299867fe64d7SBrett Creeley "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n"); 299967fe64d7SBrett Creeley return -EINVAL; 300067fe64d7SBrett Creeley } 300167fe64d7SBrett Creeley 300267fe64d7SBrett Creeley if (ec->rx_coalesce_usecs > ICE_ITR_MAX) { 300367fe64d7SBrett Creeley netdev_info(vsi->netdev, 300467fe64d7SBrett Creeley "Invalid value, rx-usecs range is 0-%d\n", 300567fe64d7SBrett Creeley ICE_ITR_MAX); 300667fe64d7SBrett Creeley return -EINVAL; 300767fe64d7SBrett Creeley } 300867fe64d7SBrett Creeley 300967fe64d7SBrett Creeley if (ec->use_adaptive_rx_coalesce) { 301067fe64d7SBrett Creeley rc->itr_setting |= ICE_ITR_DYNAMIC; 301167fe64d7SBrett Creeley } else { 301267fe64d7SBrett Creeley rc->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs); 301367fe64d7SBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 301467fe64d7SBrett Creeley } 301567fe64d7SBrett Creeley break; 301667fe64d7SBrett Creeley case ICE_TX_CONTAINER: 3017b9c8bb06SBrett Creeley if (ec->tx_coalesce_usecs_high) { 3018b9c8bb06SBrett Creeley netdev_info(vsi->netdev, 3019b9c8bb06SBrett Creeley "setting tx-usecs-high is not supported\n"); 3020b9c8bb06SBrett Creeley return -EINVAL; 3021b9c8bb06SBrett Creeley } 3022b9c8bb06SBrett Creeley 302367fe64d7SBrett Creeley if (ec->tx_coalesce_usecs != itr_setting && 302467fe64d7SBrett Creeley ec->use_adaptive_tx_coalesce) { 302567fe64d7SBrett Creeley netdev_info(vsi->netdev, 302667fe64d7SBrett Creeley "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n"); 302767fe64d7SBrett Creeley return -EINVAL; 302867fe64d7SBrett Creeley } 302967fe64d7SBrett Creeley 303067fe64d7SBrett Creeley if (ec->tx_coalesce_usecs > ICE_ITR_MAX) { 303167fe64d7SBrett Creeley netdev_info(vsi->netdev, 303267fe64d7SBrett Creeley "Invalid value, tx-usecs range is 0-%d\n", 303367fe64d7SBrett Creeley ICE_ITR_MAX); 303467fe64d7SBrett Creeley return -EINVAL; 303567fe64d7SBrett Creeley } 303667fe64d7SBrett Creeley 303767fe64d7SBrett Creeley if (ec->use_adaptive_tx_coalesce) { 303867fe64d7SBrett Creeley rc->itr_setting |= ICE_ITR_DYNAMIC; 303967fe64d7SBrett Creeley } else { 304067fe64d7SBrett Creeley rc->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs); 304167fe64d7SBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 304267fe64d7SBrett Creeley } 304367fe64d7SBrett Creeley break; 304467fe64d7SBrett Creeley default: 304567fe64d7SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid container type %d\n", c_type); 304667fe64d7SBrett Creeley return -EINVAL; 304767fe64d7SBrett Creeley } 304867fe64d7SBrett Creeley 304967fe64d7SBrett Creeley return 0; 305067fe64d7SBrett Creeley } 305167fe64d7SBrett Creeley 3052e40c899aSBrett Creeley /** 3053e40c899aSBrett Creeley * ice_set_q_coalesce - set a queue's ITR/INTRL (coalesce) settings 3054e40c899aSBrett Creeley * @vsi: VSI associated to the queue that need updating 3055e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 3056e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 3057e40c899aSBrett Creeley * 3058e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 3059e40c899aSBrett Creeley * 1. Setting Tx or Rx ITR/INTRL (coalesce) settings failed. 3060e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 3061e40c899aSBrett Creeley */ 3062e40c899aSBrett Creeley static int 3063e40c899aSBrett Creeley ice_set_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 3064e40c899aSBrett Creeley { 3065e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 3066e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 3067e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 3068e40c899aSBrett Creeley vsi)) 3069e40c899aSBrett Creeley return -EINVAL; 3070e40c899aSBrett Creeley 3071e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 3072e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 3073e40c899aSBrett Creeley vsi)) 3074e40c899aSBrett Creeley return -EINVAL; 3075e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 3076e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 3077e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 3078e40c899aSBrett Creeley vsi)) 3079e40c899aSBrett Creeley return -EINVAL; 3080e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 3081e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 3082e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 3083e40c899aSBrett Creeley vsi)) 3084e40c899aSBrett Creeley return -EINVAL; 3085e40c899aSBrett Creeley } else { 3086e40c899aSBrett Creeley return -EINVAL; 3087e40c899aSBrett Creeley } 3088e40c899aSBrett Creeley 3089e40c899aSBrett Creeley return 0; 3090e40c899aSBrett Creeley } 3091e40c899aSBrett Creeley 3092e40c899aSBrett Creeley /** 3093e40c899aSBrett Creeley * __ice_set_coalesce - set ITR/INTRL values for the device 3094e40c899aSBrett Creeley * @netdev: pointer to the netdev associated with this query 3095e40c899aSBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 3096e40c899aSBrett Creeley * @q_num: queue number to get the coalesce settings for 3097e40c899aSBrett Creeley * 3098e40c899aSBrett Creeley * If the caller passes in a negative q_num then we set the coalesce settings 3099e40c899aSBrett Creeley * for all Tx/Rx queues, else use the actual q_num passed in. 3100e40c899aSBrett Creeley */ 310167fe64d7SBrett Creeley static int 310267fe64d7SBrett Creeley __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 310367fe64d7SBrett Creeley int q_num) 310467fe64d7SBrett Creeley { 310567fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 310667fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 310767fe64d7SBrett Creeley 310867fe64d7SBrett Creeley if (q_num < 0) { 310967fe64d7SBrett Creeley int i; 311067fe64d7SBrett Creeley 311167fe64d7SBrett Creeley ice_for_each_q_vector(vsi, i) { 3112e40c899aSBrett Creeley if (ice_set_q_coalesce(vsi, ec, i)) 311367fe64d7SBrett Creeley return -EINVAL; 311467fe64d7SBrett Creeley } 311567fe64d7SBrett Creeley goto set_work_lmt; 311667fe64d7SBrett Creeley } 311767fe64d7SBrett Creeley 3118e40c899aSBrett Creeley if (ice_set_q_coalesce(vsi, ec, q_num)) 311967fe64d7SBrett Creeley return -EINVAL; 312067fe64d7SBrett Creeley 312167fe64d7SBrett Creeley set_work_lmt: 3122e40c899aSBrett Creeley 312367fe64d7SBrett Creeley if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) 312467fe64d7SBrett Creeley vsi->work_lmt = max(ec->tx_max_coalesced_frames_irq, 312567fe64d7SBrett Creeley ec->rx_max_coalesced_frames_irq); 312667fe64d7SBrett Creeley 312767fe64d7SBrett Creeley return 0; 312867fe64d7SBrett Creeley } 312967fe64d7SBrett Creeley 313067fe64d7SBrett Creeley static int 313167fe64d7SBrett Creeley ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 313267fe64d7SBrett Creeley { 313367fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, -1); 313467fe64d7SBrett Creeley } 313567fe64d7SBrett Creeley 3136c8b7abddSBruce Allan static int 3137c8b7abddSBruce Allan ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num, 313867fe64d7SBrett Creeley struct ethtool_coalesce *ec) 313967fe64d7SBrett Creeley { 314067fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, q_num); 314167fe64d7SBrett Creeley } 314267fe64d7SBrett Creeley 3143fcea6f3dSAnirudh Venkataramanan static const struct ethtool_ops ice_ethtool_ops = { 3144fcea6f3dSAnirudh Venkataramanan .get_link_ksettings = ice_get_link_ksettings, 314548cb27f2SChinh Cao .set_link_ksettings = ice_set_link_ksettings, 3146fcea6f3dSAnirudh Venkataramanan .get_drvinfo = ice_get_drvinfo, 3147fcea6f3dSAnirudh Venkataramanan .get_regs_len = ice_get_regs_len, 3148fcea6f3dSAnirudh Venkataramanan .get_regs = ice_get_regs, 3149fcea6f3dSAnirudh Venkataramanan .get_msglevel = ice_get_msglevel, 3150fcea6f3dSAnirudh Venkataramanan .set_msglevel = ice_set_msglevel, 31510e674aebSAnirudh Venkataramanan .self_test = ice_self_test, 3152fcea6f3dSAnirudh Venkataramanan .get_link = ethtool_op_get_link, 31534c98ab55SBruce Allan .get_eeprom_len = ice_get_eeprom_len, 31544c98ab55SBruce Allan .get_eeprom = ice_get_eeprom, 315567fe64d7SBrett Creeley .get_coalesce = ice_get_coalesce, 315667fe64d7SBrett Creeley .set_coalesce = ice_set_coalesce, 3157fcea6f3dSAnirudh Venkataramanan .get_strings = ice_get_strings, 31588e151d50SAnirudh Venkataramanan .set_phys_id = ice_set_phys_id, 3159fcea6f3dSAnirudh Venkataramanan .get_ethtool_stats = ice_get_ethtool_stats, 3160ab4ab73fSBruce Allan .get_priv_flags = ice_get_priv_flags, 3161ab4ab73fSBruce Allan .set_priv_flags = ice_set_priv_flags, 3162fcea6f3dSAnirudh Venkataramanan .get_sset_count = ice_get_sset_count, 3163fcea6f3dSAnirudh Venkataramanan .get_rxnfc = ice_get_rxnfc, 3164fcea6f3dSAnirudh Venkataramanan .get_ringparam = ice_get_ringparam, 3165fcea6f3dSAnirudh Venkataramanan .set_ringparam = ice_set_ringparam, 3166fcea6f3dSAnirudh Venkataramanan .nway_reset = ice_nway_reset, 3167fcea6f3dSAnirudh Venkataramanan .get_pauseparam = ice_get_pauseparam, 3168fcea6f3dSAnirudh Venkataramanan .set_pauseparam = ice_set_pauseparam, 3169fcea6f3dSAnirudh Venkataramanan .get_rxfh_key_size = ice_get_rxfh_key_size, 3170fcea6f3dSAnirudh Venkataramanan .get_rxfh_indir_size = ice_get_rxfh_indir_size, 3171fcea6f3dSAnirudh Venkataramanan .get_rxfh = ice_get_rxfh, 3172fcea6f3dSAnirudh Venkataramanan .set_rxfh = ice_set_rxfh, 3173a8939784STony Nguyen .get_ts_info = ethtool_op_get_ts_info, 317467fe64d7SBrett Creeley .get_per_queue_coalesce = ice_get_per_q_coalesce, 317567fe64d7SBrett Creeley .set_per_queue_coalesce = ice_set_per_q_coalesce, 3176fcea6f3dSAnirudh Venkataramanan }; 3177fcea6f3dSAnirudh Venkataramanan 3178fcea6f3dSAnirudh Venkataramanan /** 3179fcea6f3dSAnirudh Venkataramanan * ice_set_ethtool_ops - setup netdev ethtool ops 3180fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3181fcea6f3dSAnirudh Venkataramanan * 3182fcea6f3dSAnirudh Venkataramanan * setup netdev ethtool ops with ice specific ops 3183fcea6f3dSAnirudh Venkataramanan */ 3184fcea6f3dSAnirudh Venkataramanan void ice_set_ethtool_ops(struct net_device *netdev) 3185fcea6f3dSAnirudh Venkataramanan { 3186fcea6f3dSAnirudh Venkataramanan netdev->ethtool_ops = &ice_ethtool_ops; 3187fcea6f3dSAnirudh Venkataramanan } 3188