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 /** 963f776b3acSPaul Greenwalt * ice_set_fec_cfg - Set link FEC options 964f776b3acSPaul Greenwalt * @netdev: network interface device structure 965f776b3acSPaul Greenwalt * @req_fec: FEC mode to configure 966f776b3acSPaul Greenwalt */ 967f776b3acSPaul Greenwalt static int ice_set_fec_cfg(struct net_device *netdev, enum ice_fec_mode req_fec) 968f776b3acSPaul Greenwalt { 969f776b3acSPaul Greenwalt struct ice_netdev_priv *np = netdev_priv(netdev); 970f776b3acSPaul Greenwalt struct ice_aqc_set_phy_cfg_data config = { 0 }; 971f776b3acSPaul Greenwalt struct ice_aqc_get_phy_caps_data *caps; 972f776b3acSPaul Greenwalt struct ice_vsi *vsi = np->vsi; 973f776b3acSPaul Greenwalt u8 sw_cfg_caps, sw_cfg_fec; 974f776b3acSPaul Greenwalt struct ice_port_info *pi; 975f776b3acSPaul Greenwalt enum ice_status status; 976f776b3acSPaul Greenwalt int err = 0; 977f776b3acSPaul Greenwalt 978f776b3acSPaul Greenwalt pi = vsi->port_info; 979f776b3acSPaul Greenwalt if (!pi) 980f776b3acSPaul Greenwalt return -EOPNOTSUPP; 981f776b3acSPaul Greenwalt 982f776b3acSPaul Greenwalt /* Changing the FEC parameters is not supported if not the PF VSI */ 983f776b3acSPaul Greenwalt if (vsi->type != ICE_VSI_PF) { 984f776b3acSPaul Greenwalt netdev_info(netdev, "Changing FEC parameters only supported for PF VSI\n"); 985f776b3acSPaul Greenwalt return -EOPNOTSUPP; 986f776b3acSPaul Greenwalt } 987f776b3acSPaul Greenwalt 988f776b3acSPaul Greenwalt /* Get last SW configuration */ 989f776b3acSPaul Greenwalt caps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*caps), GFP_KERNEL); 990f776b3acSPaul Greenwalt if (!caps) 991f776b3acSPaul Greenwalt return -ENOMEM; 992f776b3acSPaul Greenwalt 993f776b3acSPaul Greenwalt status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, 994f776b3acSPaul Greenwalt caps, NULL); 995f776b3acSPaul Greenwalt if (status) { 996f776b3acSPaul Greenwalt err = -EAGAIN; 997f776b3acSPaul Greenwalt goto done; 998f776b3acSPaul Greenwalt } 999f776b3acSPaul Greenwalt 1000f776b3acSPaul Greenwalt /* Copy SW configuration returned from PHY caps to PHY config */ 1001f776b3acSPaul Greenwalt ice_copy_phy_caps_to_cfg(caps, &config); 1002f776b3acSPaul Greenwalt sw_cfg_caps = caps->caps; 1003f776b3acSPaul Greenwalt sw_cfg_fec = caps->link_fec_options; 1004f776b3acSPaul Greenwalt 1005f776b3acSPaul Greenwalt /* Get toloplogy caps, then copy PHY FEC topoloy caps to PHY config */ 1006f776b3acSPaul Greenwalt memset(caps, 0, sizeof(*caps)); 1007f776b3acSPaul Greenwalt 1008f776b3acSPaul Greenwalt status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, 1009f776b3acSPaul Greenwalt caps, NULL); 1010f776b3acSPaul Greenwalt if (status) { 1011f776b3acSPaul Greenwalt err = -EAGAIN; 1012f776b3acSPaul Greenwalt goto done; 1013f776b3acSPaul Greenwalt } 1014f776b3acSPaul Greenwalt 1015f776b3acSPaul Greenwalt config.caps |= (caps->caps & ICE_AQC_PHY_EN_AUTO_FEC); 1016f776b3acSPaul Greenwalt config.link_fec_opt = caps->link_fec_options; 1017f776b3acSPaul Greenwalt 1018f776b3acSPaul Greenwalt ice_cfg_phy_fec(&config, req_fec); 1019f776b3acSPaul Greenwalt 1020f776b3acSPaul Greenwalt /* If FEC mode has changed, then set PHY configuration and enable AN. */ 1021f776b3acSPaul Greenwalt if ((config.caps & ICE_AQ_PHY_ENA_AUTO_FEC) != 1022f776b3acSPaul Greenwalt (sw_cfg_caps & ICE_AQC_PHY_EN_AUTO_FEC) || 1023f776b3acSPaul Greenwalt config.link_fec_opt != sw_cfg_fec) { 1024f776b3acSPaul Greenwalt if (caps->caps & ICE_AQC_PHY_AN_MODE) 1025f776b3acSPaul Greenwalt config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 1026f776b3acSPaul Greenwalt 1027f776b3acSPaul Greenwalt status = ice_aq_set_phy_cfg(pi->hw, pi->lport, &config, NULL); 1028f776b3acSPaul Greenwalt 1029f776b3acSPaul Greenwalt if (status) 1030f776b3acSPaul Greenwalt err = -EAGAIN; 1031f776b3acSPaul Greenwalt } 1032f776b3acSPaul Greenwalt 1033f776b3acSPaul Greenwalt done: 1034f776b3acSPaul Greenwalt devm_kfree(&vsi->back->pdev->dev, caps); 1035f776b3acSPaul Greenwalt return err; 1036f776b3acSPaul Greenwalt } 1037f776b3acSPaul Greenwalt 1038f776b3acSPaul Greenwalt /** 1039f776b3acSPaul Greenwalt * ice_set_fecparam - Set FEC link options 1040f776b3acSPaul Greenwalt * @netdev: network interface device structure 1041f776b3acSPaul Greenwalt * @fecparam: Ethtool structure to retrieve FEC parameters 1042f776b3acSPaul Greenwalt */ 1043f776b3acSPaul Greenwalt static int 1044f776b3acSPaul Greenwalt ice_set_fecparam(struct net_device *netdev, struct ethtool_fecparam *fecparam) 1045f776b3acSPaul Greenwalt { 1046f776b3acSPaul Greenwalt struct ice_netdev_priv *np = netdev_priv(netdev); 1047f776b3acSPaul Greenwalt struct ice_vsi *vsi = np->vsi; 1048f776b3acSPaul Greenwalt enum ice_fec_mode fec; 1049f776b3acSPaul Greenwalt 1050f776b3acSPaul Greenwalt switch (fecparam->fec) { 1051f776b3acSPaul Greenwalt case ETHTOOL_FEC_AUTO: 1052f776b3acSPaul Greenwalt fec = ICE_FEC_AUTO; 1053f776b3acSPaul Greenwalt break; 1054f776b3acSPaul Greenwalt case ETHTOOL_FEC_RS: 1055f776b3acSPaul Greenwalt fec = ICE_FEC_RS; 1056f776b3acSPaul Greenwalt break; 1057f776b3acSPaul Greenwalt case ETHTOOL_FEC_BASER: 1058f776b3acSPaul Greenwalt fec = ICE_FEC_BASER; 1059f776b3acSPaul Greenwalt break; 1060f776b3acSPaul Greenwalt case ETHTOOL_FEC_OFF: 1061f776b3acSPaul Greenwalt case ETHTOOL_FEC_NONE: 1062f776b3acSPaul Greenwalt fec = ICE_FEC_NONE; 1063f776b3acSPaul Greenwalt break; 1064f776b3acSPaul Greenwalt default: 1065f776b3acSPaul Greenwalt dev_warn(&vsi->back->pdev->dev, "Unsupported FEC mode: %d\n", 1066f776b3acSPaul Greenwalt fecparam->fec); 1067f776b3acSPaul Greenwalt return -EINVAL; 1068f776b3acSPaul Greenwalt } 1069f776b3acSPaul Greenwalt 1070f776b3acSPaul Greenwalt return ice_set_fec_cfg(netdev, fec); 1071f776b3acSPaul Greenwalt } 1072f776b3acSPaul Greenwalt 1073f776b3acSPaul Greenwalt /** 1074f776b3acSPaul Greenwalt * ice_get_fecparam - Get link FEC options 1075f776b3acSPaul Greenwalt * @netdev: network interface device structure 1076f776b3acSPaul Greenwalt * @fecparam: Ethtool structure to retrieve FEC parameters 1077f776b3acSPaul Greenwalt */ 1078f776b3acSPaul Greenwalt static int 1079f776b3acSPaul Greenwalt ice_get_fecparam(struct net_device *netdev, struct ethtool_fecparam *fecparam) 1080f776b3acSPaul Greenwalt { 1081f776b3acSPaul Greenwalt struct ice_netdev_priv *np = netdev_priv(netdev); 1082f776b3acSPaul Greenwalt struct ice_aqc_get_phy_caps_data *caps; 1083f776b3acSPaul Greenwalt struct ice_link_status *link_info; 1084f776b3acSPaul Greenwalt struct ice_vsi *vsi = np->vsi; 1085f776b3acSPaul Greenwalt struct ice_port_info *pi; 1086f776b3acSPaul Greenwalt enum ice_status status; 1087f776b3acSPaul Greenwalt int err = 0; 1088f776b3acSPaul Greenwalt 1089f776b3acSPaul Greenwalt pi = vsi->port_info; 1090f776b3acSPaul Greenwalt 1091f776b3acSPaul Greenwalt if (!pi) 1092f776b3acSPaul Greenwalt return -EOPNOTSUPP; 1093f776b3acSPaul Greenwalt link_info = &pi->phy.link_info; 1094f776b3acSPaul Greenwalt 1095f776b3acSPaul Greenwalt /* Set FEC mode based on negotiated link info */ 1096f776b3acSPaul Greenwalt switch (link_info->fec_info) { 1097f776b3acSPaul Greenwalt case ICE_AQ_LINK_25G_KR_FEC_EN: 1098f776b3acSPaul Greenwalt fecparam->active_fec = ETHTOOL_FEC_BASER; 1099f776b3acSPaul Greenwalt break; 1100f776b3acSPaul Greenwalt case ICE_AQ_LINK_25G_RS_528_FEC_EN: 1101f776b3acSPaul Greenwalt /* fall through */ 1102f776b3acSPaul Greenwalt case ICE_AQ_LINK_25G_RS_544_FEC_EN: 1103f776b3acSPaul Greenwalt fecparam->active_fec = ETHTOOL_FEC_RS; 1104f776b3acSPaul Greenwalt break; 1105f776b3acSPaul Greenwalt default: 1106f776b3acSPaul Greenwalt fecparam->active_fec = ETHTOOL_FEC_OFF; 1107f776b3acSPaul Greenwalt break; 1108f776b3acSPaul Greenwalt } 1109f776b3acSPaul Greenwalt 1110f776b3acSPaul Greenwalt caps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*caps), GFP_KERNEL); 1111f776b3acSPaul Greenwalt if (!caps) 1112f776b3acSPaul Greenwalt return -ENOMEM; 1113f776b3acSPaul Greenwalt 1114f776b3acSPaul Greenwalt status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, 1115f776b3acSPaul Greenwalt caps, NULL); 1116f776b3acSPaul Greenwalt if (status) { 1117f776b3acSPaul Greenwalt err = -EAGAIN; 1118f776b3acSPaul Greenwalt goto done; 1119f776b3acSPaul Greenwalt } 1120f776b3acSPaul Greenwalt 1121f776b3acSPaul Greenwalt /* Set supported/configured FEC modes based on PHY capability */ 1122f776b3acSPaul Greenwalt if (caps->caps & ICE_AQC_PHY_EN_AUTO_FEC) 1123f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_AUTO; 1124f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN || 1125f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ || 1126f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN || 1127f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_REQ) 1128f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_BASER; 1129f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_528_REQ || 1130f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_544_REQ || 1131f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN) 1132f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_RS; 1133f776b3acSPaul Greenwalt if (caps->link_fec_options == 0) 1134f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_OFF; 1135f776b3acSPaul Greenwalt 1136f776b3acSPaul Greenwalt done: 1137f776b3acSPaul Greenwalt devm_kfree(&vsi->back->pdev->dev, caps); 1138f776b3acSPaul Greenwalt return err; 1139f776b3acSPaul Greenwalt } 1140f776b3acSPaul Greenwalt 1141f776b3acSPaul Greenwalt /** 1142ab4ab73fSBruce Allan * ice_get_priv_flags - report device private flags 1143ab4ab73fSBruce Allan * @netdev: network interface device structure 1144ab4ab73fSBruce Allan * 1145ab4ab73fSBruce Allan * The get string set count and the string set should be matched for each 1146ab4ab73fSBruce Allan * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags 1147ab4ab73fSBruce Allan * array. 1148ab4ab73fSBruce Allan * 1149ab4ab73fSBruce Allan * Returns a u32 bitmap of flags. 1150ab4ab73fSBruce Allan */ 1151ab4ab73fSBruce Allan static u32 ice_get_priv_flags(struct net_device *netdev) 1152ab4ab73fSBruce Allan { 1153ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 1154ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 1155ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 1156ab4ab73fSBruce Allan u32 i, ret_flags = 0; 1157ab4ab73fSBruce Allan 1158ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 1159ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 1160ab4ab73fSBruce Allan 1161ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 1162ab4ab73fSBruce Allan 1163ab4ab73fSBruce Allan if (test_bit(priv_flag->bitno, pf->flags)) 1164ab4ab73fSBruce Allan ret_flags |= BIT(i); 1165ab4ab73fSBruce Allan } 1166ab4ab73fSBruce Allan 1167ab4ab73fSBruce Allan return ret_flags; 1168ab4ab73fSBruce Allan } 1169ab4ab73fSBruce Allan 1170ab4ab73fSBruce Allan /** 1171ab4ab73fSBruce Allan * ice_set_priv_flags - set private flags 1172ab4ab73fSBruce Allan * @netdev: network interface device structure 1173ab4ab73fSBruce Allan * @flags: bit flags to be set 1174ab4ab73fSBruce Allan */ 1175ab4ab73fSBruce Allan static int ice_set_priv_flags(struct net_device *netdev, u32 flags) 1176ab4ab73fSBruce Allan { 1177ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 11783a257a14SAnirudh Venkataramanan DECLARE_BITMAP(change_flags, ICE_PF_FLAGS_NBITS); 11793a257a14SAnirudh Venkataramanan DECLARE_BITMAP(orig_flags, ICE_PF_FLAGS_NBITS); 1180ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 1181ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 11823a257a14SAnirudh Venkataramanan int ret = 0; 1183ab4ab73fSBruce Allan u32 i; 1184ab4ab73fSBruce Allan 1185ab4ab73fSBruce Allan if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE)) 1186ab4ab73fSBruce Allan return -EINVAL; 1187ab4ab73fSBruce Allan 11883a257a14SAnirudh Venkataramanan set_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 11893a257a14SAnirudh Venkataramanan 11903a257a14SAnirudh Venkataramanan bitmap_copy(orig_flags, pf->flags, ICE_PF_FLAGS_NBITS); 1191ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 1192ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 1193ab4ab73fSBruce Allan 1194ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 1195ab4ab73fSBruce Allan 1196ab4ab73fSBruce Allan if (flags & BIT(i)) 1197ab4ab73fSBruce Allan set_bit(priv_flag->bitno, pf->flags); 1198ab4ab73fSBruce Allan else 1199ab4ab73fSBruce Allan clear_bit(priv_flag->bitno, pf->flags); 1200ab4ab73fSBruce Allan } 1201ab4ab73fSBruce Allan 12023a257a14SAnirudh Venkataramanan bitmap_xor(change_flags, pf->flags, orig_flags, ICE_PF_FLAGS_NBITS); 12033a257a14SAnirudh Venkataramanan 120431eafa40SAnirudh Venkataramanan if (test_bit(ICE_FLAG_ENABLE_FW_LLDP, change_flags)) { 120531eafa40SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags)) { 12063a257a14SAnirudh Venkataramanan enum ice_status status; 12073a257a14SAnirudh Venkataramanan 12082e0e6228SDave Ertman /* Disable FW LLDP engine */ 12093a257a14SAnirudh Venkataramanan status = ice_aq_cfg_lldp_mib_change(&pf->hw, false, 12103a257a14SAnirudh Venkataramanan NULL); 12113a257a14SAnirudh Venkataramanan /* If unregistering for LLDP events fails, this is 12123a257a14SAnirudh Venkataramanan * not an error state, as there shouldn't be any 12133a257a14SAnirudh Venkataramanan * events to respond to. 12143a257a14SAnirudh Venkataramanan */ 12153a257a14SAnirudh Venkataramanan if (status) 12163a257a14SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 12173a257a14SAnirudh Venkataramanan "Failed to unreg for LLDP events\n"); 12183a257a14SAnirudh Venkataramanan 12193a257a14SAnirudh Venkataramanan /* The AQ call to stop the FW LLDP agent will generate 12203a257a14SAnirudh Venkataramanan * an error if the agent is already stopped. 12213a257a14SAnirudh Venkataramanan */ 122231eafa40SAnirudh Venkataramanan status = ice_aq_stop_lldp(&pf->hw, true, true, NULL); 12233a257a14SAnirudh Venkataramanan if (status) 12243a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 12253a257a14SAnirudh Venkataramanan "Fail to stop LLDP agent\n"); 12263a257a14SAnirudh Venkataramanan /* Use case for having the FW LLDP agent stopped 12273a257a14SAnirudh Venkataramanan * will likely not need DCB, so failure to init is 12283a257a14SAnirudh Venkataramanan * not a concern of ethtool 12293a257a14SAnirudh Venkataramanan */ 1230e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 12313a257a14SAnirudh Venkataramanan if (status) 12323a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Fail to init DCB\n"); 12332e0e6228SDave Ertman 12342e0e6228SDave Ertman /* Forward LLDP packets to default VSI so that they 12352e0e6228SDave Ertman * are passed up the stack 12362e0e6228SDave Ertman */ 12372e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, true); 12383a257a14SAnirudh Venkataramanan } else { 12393a257a14SAnirudh Venkataramanan enum ice_status status; 12403a257a14SAnirudh Venkataramanan bool dcbx_agent_status; 12413a257a14SAnirudh Venkataramanan 12423a257a14SAnirudh Venkataramanan /* AQ command to start FW LLDP agent will return an 12433a257a14SAnirudh Venkataramanan * error if the agent is already started 12443a257a14SAnirudh Venkataramanan */ 124531eafa40SAnirudh Venkataramanan status = ice_aq_start_lldp(&pf->hw, true, NULL); 12463a257a14SAnirudh Venkataramanan if (status) 12473a257a14SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, 12483a257a14SAnirudh Venkataramanan "Fail to start LLDP Agent\n"); 12493a257a14SAnirudh Venkataramanan 12503a257a14SAnirudh Venkataramanan /* AQ command to start FW DCBx agent will fail if 12513a257a14SAnirudh Venkataramanan * the agent is already started 12523a257a14SAnirudh Venkataramanan */ 12533a257a14SAnirudh Venkataramanan status = ice_aq_start_stop_dcbx(&pf->hw, true, 12543a257a14SAnirudh Venkataramanan &dcbx_agent_status, 12553a257a14SAnirudh Venkataramanan NULL); 12563a257a14SAnirudh Venkataramanan if (status) 12573a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 12583a257a14SAnirudh Venkataramanan "Failed to start FW DCBX\n"); 12593a257a14SAnirudh Venkataramanan 12603a257a14SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "FW DCBX agent is %s\n", 12613a257a14SAnirudh Venkataramanan dcbx_agent_status ? "ACTIVE" : "DISABLED"); 12623a257a14SAnirudh Venkataramanan 12633a257a14SAnirudh Venkataramanan /* Failure to configure MIB change or init DCB is not 12643a257a14SAnirudh Venkataramanan * relevant to ethtool. Print notification that 12653a257a14SAnirudh Venkataramanan * registration/init failed but do not return error 12663a257a14SAnirudh Venkataramanan * state to ethtool 12673a257a14SAnirudh Venkataramanan */ 1268e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 12693a257a14SAnirudh Venkataramanan if (status) 12703a257a14SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "Fail to init DCB\n"); 12712e0e6228SDave Ertman 12722e0e6228SDave Ertman /* Remove rule to direct LLDP packets to default VSI. 12732e0e6228SDave Ertman * The FW LLDP engine will now be consuming them. 12742e0e6228SDave Ertman */ 12752e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, false); 12763a257a14SAnirudh Venkataramanan } 12773a257a14SAnirudh Venkataramanan } 12783a257a14SAnirudh Venkataramanan clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 12793a257a14SAnirudh Venkataramanan return ret; 1280ab4ab73fSBruce Allan } 1281ab4ab73fSBruce Allan 1282fcea6f3dSAnirudh Venkataramanan static int ice_get_sset_count(struct net_device *netdev, int sset) 1283fcea6f3dSAnirudh Venkataramanan { 1284fcea6f3dSAnirudh Venkataramanan switch (sset) { 1285fcea6f3dSAnirudh Venkataramanan case ETH_SS_STATS: 1286f8ba7db8SJacob Keller /* The number (and order) of strings reported *must* remain 1287f8ba7db8SJacob Keller * constant for a given netdevice. This function must not 1288f8ba7db8SJacob Keller * report a different number based on run time parameters 1289f8ba7db8SJacob Keller * (such as the number of queues in use, or the setting of 1290f8ba7db8SJacob Keller * a private ethtool flag). This is due to the nature of the 1291f8ba7db8SJacob Keller * ethtool stats API. 1292f8ba7db8SJacob Keller * 1293f8ba7db8SJacob Keller * Userspace programs such as ethtool must make 3 separate 1294f8ba7db8SJacob Keller * ioctl requests, one for size, one for the strings, and 1295f8ba7db8SJacob Keller * finally one for the stats. Since these cross into 1296f8ba7db8SJacob Keller * userspace, changes to the number or size could result in 1297f8ba7db8SJacob Keller * undefined memory access or incorrect string<->value 1298f8ba7db8SJacob Keller * correlations for statistics. 1299f8ba7db8SJacob Keller * 1300f8ba7db8SJacob Keller * Even if it appears to be safe, changes to the size or 1301f8ba7db8SJacob Keller * order of strings will suffer from race conditions and are 1302f8ba7db8SJacob Keller * not safe. 1303f8ba7db8SJacob Keller */ 1304fcea6f3dSAnirudh Venkataramanan return ICE_ALL_STATS_LEN(netdev); 13050e674aebSAnirudh Venkataramanan case ETH_SS_TEST: 13060e674aebSAnirudh Venkataramanan return ICE_TEST_LEN; 1307ab4ab73fSBruce Allan case ETH_SS_PRIV_FLAGS: 1308ab4ab73fSBruce Allan return ICE_PRIV_FLAG_ARRAY_SIZE; 1309fcea6f3dSAnirudh Venkataramanan default: 1310fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 1311fcea6f3dSAnirudh Venkataramanan } 1312fcea6f3dSAnirudh Venkataramanan } 1313fcea6f3dSAnirudh Venkataramanan 1314fcea6f3dSAnirudh Venkataramanan static void 1315fcea6f3dSAnirudh Venkataramanan ice_get_ethtool_stats(struct net_device *netdev, 1316fcea6f3dSAnirudh Venkataramanan struct ethtool_stats __always_unused *stats, u64 *data) 1317fcea6f3dSAnirudh Venkataramanan { 1318fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1319fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1320fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1321fcea6f3dSAnirudh Venkataramanan struct ice_ring *ring; 1322fcea6f3dSAnirudh Venkataramanan unsigned int j = 0; 1323fcea6f3dSAnirudh Venkataramanan int i = 0; 1324fcea6f3dSAnirudh Venkataramanan char *p; 1325fcea6f3dSAnirudh Venkataramanan 1326fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_VSI_STATS_LEN; j++) { 1327fcea6f3dSAnirudh Venkataramanan p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; 1328fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == 1329fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 1330fcea6f3dSAnirudh Venkataramanan } 1331fcea6f3dSAnirudh Venkataramanan 1332fcea6f3dSAnirudh Venkataramanan /* populate per queue stats */ 1333fcea6f3dSAnirudh Venkataramanan rcu_read_lock(); 1334fcea6f3dSAnirudh Venkataramanan 1335f8ba7db8SJacob Keller ice_for_each_alloc_txq(vsi, j) { 1336fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->tx_rings[j]); 1337f8ba7db8SJacob Keller if (ring) { 1338fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 1339fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 1340f8ba7db8SJacob Keller } else { 1341f8ba7db8SJacob Keller data[i++] = 0; 1342f8ba7db8SJacob Keller data[i++] = 0; 1343f8ba7db8SJacob Keller } 1344fcea6f3dSAnirudh Venkataramanan } 1345fcea6f3dSAnirudh Venkataramanan 1346f8ba7db8SJacob Keller ice_for_each_alloc_rxq(vsi, j) { 1347fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->rx_rings[j]); 1348f8ba7db8SJacob Keller if (ring) { 1349fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 1350fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 1351f8ba7db8SJacob Keller } else { 1352f8ba7db8SJacob Keller data[i++] = 0; 1353f8ba7db8SJacob Keller data[i++] = 0; 1354f8ba7db8SJacob Keller } 1355fcea6f3dSAnirudh Venkataramanan } 1356fcea6f3dSAnirudh Venkataramanan 1357fcea6f3dSAnirudh Venkataramanan rcu_read_unlock(); 1358fcea6f3dSAnirudh Venkataramanan 1359fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 1360fcea6f3dSAnirudh Venkataramanan return; 1361fcea6f3dSAnirudh Venkataramanan 1362fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_PF_STATS_LEN; j++) { 1363fcea6f3dSAnirudh Venkataramanan p = (char *)pf + ice_gstrings_pf_stats[j].stat_offset; 1364fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_pf_stats[j].sizeof_stat == 1365fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 1366fcea6f3dSAnirudh Venkataramanan } 13674b0fdcebSAnirudh Venkataramanan 13684b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 13694b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_tx[j]; 13704b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_tx[j]; 13714b0fdcebSAnirudh Venkataramanan } 13724b0fdcebSAnirudh Venkataramanan 13734b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 13744b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_rx[j]; 13754b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_rx[j]; 13764b0fdcebSAnirudh Venkataramanan } 1377fcea6f3dSAnirudh Venkataramanan } 1378fcea6f3dSAnirudh Venkataramanan 137948cb27f2SChinh Cao /** 138048cb27f2SChinh Cao * ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes 138148cb27f2SChinh Cao * @netdev: network interface device structure 138248cb27f2SChinh Cao * @ks: ethtool link ksettings struct to fill out 138348cb27f2SChinh Cao */ 1384aef74145SAnirudh Venkataramanan static void 1385aef74145SAnirudh Venkataramanan ice_phy_type_to_ethtool(struct net_device *netdev, 1386fcea6f3dSAnirudh Venkataramanan struct ethtool_link_ksettings *ks) 1387fcea6f3dSAnirudh Venkataramanan { 1388fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1389fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 1390aef74145SAnirudh Venkataramanan bool need_add_adv_mode = false; 1391fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1392aef74145SAnirudh Venkataramanan u64 phy_types_high; 139348cb27f2SChinh Cao u64 phy_types_low; 1394fcea6f3dSAnirudh Venkataramanan 1395fcea6f3dSAnirudh Venkataramanan hw_link_info = &vsi->port_info->phy.link_info; 139648cb27f2SChinh Cao phy_types_low = vsi->port_info->phy.phy_type_low; 1397aef74145SAnirudh Venkataramanan phy_types_high = vsi->port_info->phy.phy_type_high; 1398fcea6f3dSAnirudh Venkataramanan 139948cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 140048cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 140148cb27f2SChinh Cao 140248cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 140348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_100M_SGMII) { 140448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 140548cb27f2SChinh Cao 100baseT_Full); 14069ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14079ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100MB) 140848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 140948cb27f2SChinh Cao 100baseT_Full); 141048cb27f2SChinh Cao } 141148cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 141248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1G_SGMII) { 141348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 141448cb27f2SChinh Cao 1000baseT_Full); 14159ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14169ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 141748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 141848cb27f2SChinh Cao 1000baseT_Full); 141948cb27f2SChinh Cao } 142048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX) { 142148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 142248cb27f2SChinh Cao 1000baseKX_Full); 14239ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14249ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 142548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 142648cb27f2SChinh Cao 1000baseKX_Full); 142748cb27f2SChinh Cao } 142848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_SX || 142948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_LX) { 143048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 143148cb27f2SChinh Cao 1000baseX_Full); 14329ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14339ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 143448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 143548cb27f2SChinh Cao 1000baseX_Full); 143648cb27f2SChinh Cao } 143748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T) { 143848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 143948cb27f2SChinh Cao 2500baseT_Full); 14409ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14419ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 144248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 144348cb27f2SChinh Cao 2500baseT_Full); 144448cb27f2SChinh Cao } 144548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_X || 144648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX) { 144748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 144848cb27f2SChinh Cao 2500baseX_Full); 14499ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14509ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 145148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 145248cb27f2SChinh Cao 2500baseX_Full); 145348cb27f2SChinh Cao } 145448cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 145548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR) { 145648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 145748cb27f2SChinh Cao 5000baseT_Full); 14589ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14599ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_5GB) 146048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 146148cb27f2SChinh Cao 5000baseT_Full); 146248cb27f2SChinh Cao } 146348cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 146448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_DA || 146548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC || 146648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_C2C) { 1467fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1468fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 14699ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14709ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 1471fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1472fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 147348cb27f2SChinh Cao } 147448cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1) { 147548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 147648cb27f2SChinh Cao 10000baseKR_Full); 14779ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14789ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 147948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 148048cb27f2SChinh Cao 10000baseKR_Full); 148148cb27f2SChinh Cao } 148248cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_SR) { 148348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 148448cb27f2SChinh Cao 10000baseSR_Full); 14859ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14869ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 148748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 148848cb27f2SChinh Cao 10000baseSR_Full); 148948cb27f2SChinh Cao } 149048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_LR) { 149148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 149248cb27f2SChinh Cao 10000baseLR_Full); 14939ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14949ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 149548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 149648cb27f2SChinh Cao 10000baseLR_Full); 149748cb27f2SChinh Cao } 149848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 149948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 150048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 150148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 150248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC || 150348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_C2C) { 150448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 150548cb27f2SChinh Cao 25000baseCR_Full); 15069ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15079ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 150848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 150948cb27f2SChinh Cao 25000baseCR_Full); 151048cb27f2SChinh Cao } 151148cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_SR || 151248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_LR) { 151348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 151448cb27f2SChinh Cao 25000baseSR_Full); 15159ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15169ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 151748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 151848cb27f2SChinh Cao 25000baseSR_Full); 151948cb27f2SChinh Cao } 152048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 152148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 152248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1) { 152348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 152448cb27f2SChinh Cao 25000baseKR_Full); 15259ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15269ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 152748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 152848cb27f2SChinh Cao 25000baseKR_Full); 152948cb27f2SChinh Cao } 153048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 153148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 153248cb27f2SChinh Cao 40000baseKR4_Full); 15339ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15349ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 153548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 153648cb27f2SChinh Cao 40000baseKR4_Full); 153748cb27f2SChinh Cao } 153848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 153948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC || 154048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI) { 154148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 154248cb27f2SChinh Cao 40000baseCR4_Full); 15439ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15449ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 154548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 154648cb27f2SChinh Cao 40000baseCR4_Full); 154748cb27f2SChinh Cao } 154848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_SR4) { 154948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 155048cb27f2SChinh Cao 40000baseSR4_Full); 15519ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15529ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 155348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 155448cb27f2SChinh Cao 40000baseSR4_Full); 155548cb27f2SChinh Cao } 155648cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_LR4) { 155748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 155848cb27f2SChinh Cao 40000baseLR4_Full); 15599ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15609ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 156148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 156248cb27f2SChinh Cao 40000baseLR4_Full); 156348cb27f2SChinh Cao } 1564aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 1565aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC || 1566aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2 || 1567aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC || 1568aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2 || 1569aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 1570aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR || 1571aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC || 1572aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1) { 1573aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1574aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 15759ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15769ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1577aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1578aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1579aef74145SAnirudh Venkataramanan } 1580aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 1581aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 1582aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1583aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 15849ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15859ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1586aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1587aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1588aef74145SAnirudh Venkataramanan } 1589aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR2 || 1590aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR2 || 1591aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_FR || 1592aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR) { 1593aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1594aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 15959ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15969ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1597aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1598aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 1599aef74145SAnirudh Venkataramanan } 1600aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 1601aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC || 1602aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4 || 1603aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC || 1604aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4 || 1605aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 || 1606aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2 || 1607aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC || 1608aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2 || 1609aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC || 1610aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2) { 1611aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1612aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 16139ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16149ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1615aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1616aef74145SAnirudh Venkataramanan } 1617aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1618aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1619aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1620aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1621aef74145SAnirudh Venkataramanan } 1622aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4 || 1623aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) { 1624aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1625aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 16269ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16279ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1628aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1629aef74145SAnirudh Venkataramanan } 1630aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1631aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1632aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1633aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 1634aef74145SAnirudh Venkataramanan } 1635aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_LR4 || 1636aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_DR) { 1637aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1638aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 16399ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16409ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1641aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1642aef74145SAnirudh Venkataramanan } 1643aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1644aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1645aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1646aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 1647aef74145SAnirudh Venkataramanan } 1648aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || 1649aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || 1650aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) { 1651aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1652aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 16539ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16549ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1655aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1656aef74145SAnirudh Venkataramanan } 1657aef74145SAnirudh Venkataramanan if (need_add_adv_mode) 1658aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1659aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1660fcea6f3dSAnirudh Venkataramanan 166148cb27f2SChinh Cao /* Autoneg PHY types */ 166248cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 166348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 166448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX || 166548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T || 166648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX || 166748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 166848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR || 166948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 167048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 || 167148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 167248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 167348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 167448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 167548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 167648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 167748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1 || 167848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 167948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 168048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 168148cb27f2SChinh Cao Autoneg); 168248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 168348cb27f2SChinh Cao Autoneg); 168448cb27f2SChinh Cao } 1685aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 1686aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 1687aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 1688aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 1689aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1690aef74145SAnirudh Venkataramanan Autoneg); 1691aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1692aef74145SAnirudh Venkataramanan Autoneg); 1693aef74145SAnirudh Venkataramanan } 1694aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 1695aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || 1696aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || 1697aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) { 1698aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1699aef74145SAnirudh Venkataramanan Autoneg); 1700aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1701aef74145SAnirudh Venkataramanan Autoneg); 1702aef74145SAnirudh Venkataramanan } 170348cb27f2SChinh Cao } 170448cb27f2SChinh Cao 170548cb27f2SChinh Cao #define TEST_SET_BITS_TIMEOUT 50 170648cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MAX 2000 170748cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MIN 1000 170848cb27f2SChinh Cao 170948cb27f2SChinh Cao /** 171048cb27f2SChinh Cao * ice_get_settings_link_up - Get Link settings for when link is up 171148cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 171248cb27f2SChinh Cao * @netdev: network interface device structure 171348cb27f2SChinh Cao */ 1714aef74145SAnirudh Venkataramanan static void 1715aef74145SAnirudh Venkataramanan ice_get_settings_link_up(struct ethtool_link_ksettings *ks, 171648cb27f2SChinh Cao struct net_device *netdev) 171748cb27f2SChinh Cao { 171848cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 171948cb27f2SChinh Cao struct ethtool_link_ksettings cap_ksettings; 172048cb27f2SChinh Cao struct ice_link_status *link_info; 172148cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 1722aef74145SAnirudh Venkataramanan bool unrecog_phy_high = false; 172348cb27f2SChinh Cao bool unrecog_phy_low = false; 172448cb27f2SChinh Cao 172548cb27f2SChinh Cao link_info = &vsi->port_info->phy.link_info; 172648cb27f2SChinh Cao 1727f9867df6SAnirudh Venkataramanan /* Initialize supported and advertised settings based on PHY settings */ 172848cb27f2SChinh Cao switch (link_info->phy_type_low) { 172948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_100BASE_TX: 173048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 173148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 173248cb27f2SChinh Cao 100baseT_Full); 173348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 173448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 173548cb27f2SChinh Cao 100baseT_Full); 1736fcea6f3dSAnirudh Venkataramanan break; 173748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_100M_SGMII: 173848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 173948cb27f2SChinh Cao 100baseT_Full); 1740fcea6f3dSAnirudh Venkataramanan break; 174148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_T: 174248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 174348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 174448cb27f2SChinh Cao 1000baseT_Full); 174548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 174648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 174748cb27f2SChinh Cao 1000baseT_Full); 1748fcea6f3dSAnirudh Venkataramanan break; 174948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1G_SGMII: 175048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 175148cb27f2SChinh Cao 1000baseT_Full); 175248cb27f2SChinh Cao break; 175348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_SX: 175448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_LX: 175548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 175648cb27f2SChinh Cao 1000baseX_Full); 175748cb27f2SChinh Cao break; 175848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_1000BASE_KX: 175948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 176048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 176148cb27f2SChinh Cao 1000baseKX_Full); 176248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 176348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 176448cb27f2SChinh Cao 1000baseKX_Full); 176548cb27f2SChinh Cao break; 176648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_T: 176748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 176848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 176948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 177048cb27f2SChinh Cao 2500baseT_Full); 177148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 177248cb27f2SChinh Cao 2500baseT_Full); 177348cb27f2SChinh Cao break; 177448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_X: 177548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 177648cb27f2SChinh Cao 2500baseX_Full); 177748cb27f2SChinh Cao break; 177848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_2500BASE_KX: 177948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 178048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 178148cb27f2SChinh Cao 2500baseX_Full); 178248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 178348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 178448cb27f2SChinh Cao 2500baseX_Full); 178548cb27f2SChinh Cao break; 178648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_5GBASE_T: 178748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_5GBASE_KR: 178848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 178948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 179048cb27f2SChinh Cao 5000baseT_Full); 179148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 179248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 179348cb27f2SChinh Cao 5000baseT_Full); 179448cb27f2SChinh Cao break; 179548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_T: 179648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 179748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 179848cb27f2SChinh Cao 10000baseT_Full); 179948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 180048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 180148cb27f2SChinh Cao 10000baseT_Full); 180248cb27f2SChinh Cao break; 180348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_DA: 180448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC: 180548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10G_SFI_C2C: 180648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 180748cb27f2SChinh Cao 10000baseT_Full); 180848cb27f2SChinh Cao break; 180948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_SR: 181048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 181148cb27f2SChinh Cao 10000baseSR_Full); 181248cb27f2SChinh Cao break; 181348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_LR: 181448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 181548cb27f2SChinh Cao 10000baseLR_Full); 181648cb27f2SChinh Cao break; 181748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_10GBASE_KR_CR1: 181848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 181948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 182048cb27f2SChinh Cao 10000baseKR_Full); 182148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 182248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 182348cb27f2SChinh Cao 10000baseKR_Full); 182448cb27f2SChinh Cao break; 182548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_T: 182648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR: 182748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR_S: 182848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_CR1: 182948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 183048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 183148cb27f2SChinh Cao 25000baseCR_Full); 183248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 183348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 183448cb27f2SChinh Cao 25000baseCR_Full); 183548cb27f2SChinh Cao break; 183648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC: 183749a6a5d7STony Nguyen case ICE_PHY_TYPE_LOW_25G_AUI_C2C: 183848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 183948cb27f2SChinh Cao 25000baseCR_Full); 184048cb27f2SChinh Cao break; 184148cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_SR: 184248cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_LR: 184348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 184448cb27f2SChinh Cao 25000baseSR_Full); 184548cb27f2SChinh Cao break; 184648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR: 184748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR1: 184848cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_25GBASE_KR_S: 184948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 185048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 185148cb27f2SChinh Cao 25000baseKR_Full); 185248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 185348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 185448cb27f2SChinh Cao 25000baseKR_Full); 185548cb27f2SChinh Cao break; 185648cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_CR4: 185748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 185848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 185948cb27f2SChinh Cao 40000baseCR4_Full); 186048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 186148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 186248cb27f2SChinh Cao 40000baseCR4_Full); 186348cb27f2SChinh Cao break; 186448cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC: 186548cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40G_XLAUI: 186648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 186748cb27f2SChinh Cao 40000baseCR4_Full); 186848cb27f2SChinh Cao break; 186948cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_SR4: 187048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 187148cb27f2SChinh Cao 40000baseSR4_Full); 187248cb27f2SChinh Cao break; 187348cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_LR4: 187448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 187548cb27f2SChinh Cao 40000baseLR4_Full); 187648cb27f2SChinh Cao break; 187748cb27f2SChinh Cao case ICE_PHY_TYPE_LOW_40GBASE_KR4: 187848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 187948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 188048cb27f2SChinh Cao 40000baseKR4_Full); 188148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 188248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 188348cb27f2SChinh Cao 40000baseKR4_Full); 188448cb27f2SChinh Cao break; 1885aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_CR2: 1886aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_CP: 1887aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1888aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1889aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1890aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1891aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1892aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1893aef74145SAnirudh Venkataramanan break; 1894aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC: 1895aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_LAUI2: 1896aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC: 1897aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI2: 1898aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_SR: 1899aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC: 1900aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50G_AUI1: 1901aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1902aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1903aef74145SAnirudh Venkataramanan break; 1904aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_KR2: 1905aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4: 1906aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1907aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1908aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1909aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1910aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1911aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1912aef74145SAnirudh Venkataramanan break; 1913aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_SR2: 1914aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_LR2: 1915aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_FR: 1916aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_50GBASE_LR: 1917aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1918aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 1919aef74145SAnirudh Venkataramanan break; 1920aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CR4: 1921aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1922aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1923aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1924aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1925aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1926aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1927aef74145SAnirudh Venkataramanan break; 1928aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC: 1929aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_CAUI4: 1930aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC: 1931aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100G_AUI4: 1932aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4: 1933aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1934aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1935aef74145SAnirudh Venkataramanan break; 1936aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_CP2: 1937aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1938aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1939aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1940aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1941aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1942aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1943aef74145SAnirudh Venkataramanan break; 1944aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_SR4: 1945aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_SR2: 1946aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1947aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 1948aef74145SAnirudh Venkataramanan break; 1949aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_LR4: 1950aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_DR: 1951aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1952aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 1953aef74145SAnirudh Venkataramanan break; 1954aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_KR4: 1955aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4: 1956aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1957aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1958aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1959aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1960aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1961aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1962aef74145SAnirudh Venkataramanan break; 196348cb27f2SChinh Cao default: 196448cb27f2SChinh Cao unrecog_phy_low = true; 196548cb27f2SChinh Cao } 196648cb27f2SChinh Cao 1967aef74145SAnirudh Venkataramanan switch (link_info->phy_type_high) { 1968aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4: 1969aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1970aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1971aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1972aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1973aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1974aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1975aef74145SAnirudh Venkataramanan break; 1976aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC: 1977aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_CAUI2: 1978aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC: 1979aef74145SAnirudh Venkataramanan case ICE_PHY_TYPE_HIGH_100G_AUI2: 1980aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1981aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1982aef74145SAnirudh Venkataramanan break; 1983aef74145SAnirudh Venkataramanan default: 1984aef74145SAnirudh Venkataramanan unrecog_phy_high = true; 1985aef74145SAnirudh Venkataramanan } 1986aef74145SAnirudh Venkataramanan 1987aef74145SAnirudh Venkataramanan if (unrecog_phy_low && unrecog_phy_high) { 198848cb27f2SChinh Cao /* if we got here and link is up something bad is afoot */ 1989aef74145SAnirudh Venkataramanan netdev_info(netdev, 1990aef74145SAnirudh Venkataramanan "WARNING: Unrecognized PHY_Low (0x%llx).\n", 199148cb27f2SChinh Cao (u64)link_info->phy_type_low); 1992aef74145SAnirudh Venkataramanan netdev_info(netdev, 1993aef74145SAnirudh Venkataramanan "WARNING: Unrecognized PHY_High (0x%llx).\n", 1994aef74145SAnirudh Venkataramanan (u64)link_info->phy_type_high); 199548cb27f2SChinh Cao } 199648cb27f2SChinh Cao 199748cb27f2SChinh Cao /* Now that we've worked out everything that could be supported by the 199848cb27f2SChinh Cao * current PHY type, get what is supported by the NVM and intersect 199948cb27f2SChinh Cao * them to get what is truly supported 200048cb27f2SChinh Cao */ 2001c6dfd690SBruce Allan memset(&cap_ksettings, 0, sizeof(cap_ksettings)); 200248cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, &cap_ksettings); 200348cb27f2SChinh Cao ethtool_intersect_link_masks(ks, &cap_ksettings); 200448cb27f2SChinh Cao 200548cb27f2SChinh Cao switch (link_info->link_speed) { 2006aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_100GB: 2007aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_100000; 2008aef74145SAnirudh Venkataramanan break; 2009aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_50GB: 2010aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_50000; 2011aef74145SAnirudh Venkataramanan break; 201248cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_40GB: 201348cb27f2SChinh Cao ks->base.speed = SPEED_40000; 2014fcea6f3dSAnirudh Venkataramanan break; 2015fcea6f3dSAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_25GB: 2016fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_25000; 2017fcea6f3dSAnirudh Venkataramanan break; 201848cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_20GB: 201948cb27f2SChinh Cao ks->base.speed = SPEED_20000; 202048cb27f2SChinh Cao break; 202148cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_10GB: 202248cb27f2SChinh Cao ks->base.speed = SPEED_10000; 202348cb27f2SChinh Cao break; 202448cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_5GB: 202548cb27f2SChinh Cao ks->base.speed = SPEED_5000; 202648cb27f2SChinh Cao break; 202748cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_2500MB: 202848cb27f2SChinh Cao ks->base.speed = SPEED_2500; 202948cb27f2SChinh Cao break; 203048cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_1000MB: 203148cb27f2SChinh Cao ks->base.speed = SPEED_1000; 203248cb27f2SChinh Cao break; 203348cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_100MB: 203448cb27f2SChinh Cao ks->base.speed = SPEED_100; 2035fcea6f3dSAnirudh Venkataramanan break; 2036fcea6f3dSAnirudh Venkataramanan default: 203748cb27f2SChinh Cao netdev_info(netdev, 203848cb27f2SChinh Cao "WARNING: Unrecognized link_speed (0x%x).\n", 203948cb27f2SChinh Cao link_info->link_speed); 2040fcea6f3dSAnirudh Venkataramanan break; 2041fcea6f3dSAnirudh Venkataramanan } 2042fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_FULL; 204348cb27f2SChinh Cao } 204448cb27f2SChinh Cao 204548cb27f2SChinh Cao /** 204648cb27f2SChinh Cao * ice_get_settings_link_down - Get the Link settings when link is down 204748cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 204848cb27f2SChinh Cao * @netdev: network interface device structure 204948cb27f2SChinh Cao * 205048cb27f2SChinh Cao * Reports link settings that can be determined when link is down 205148cb27f2SChinh Cao */ 205248cb27f2SChinh Cao static void 205348cb27f2SChinh Cao ice_get_settings_link_down(struct ethtool_link_ksettings *ks, 2054a03499d6STony Nguyen struct net_device *netdev) 205548cb27f2SChinh Cao { 205648cb27f2SChinh Cao /* link is down and the driver needs to fall back on 2057f9867df6SAnirudh Venkataramanan * supported PHY types to figure out what info to display 205848cb27f2SChinh Cao */ 205948cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, ks); 206048cb27f2SChinh Cao 206148cb27f2SChinh Cao /* With no link, speed and duplex are unknown */ 2062fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_UNKNOWN; 2063fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_UNKNOWN; 2064fcea6f3dSAnirudh Venkataramanan } 2065fcea6f3dSAnirudh Venkataramanan 206648cb27f2SChinh Cao /** 206748cb27f2SChinh Cao * ice_get_link_ksettings - Get Link Speed and Duplex settings 206848cb27f2SChinh Cao * @netdev: network interface device structure 206948cb27f2SChinh Cao * @ks: ethtool ksettings 207048cb27f2SChinh Cao * 207148cb27f2SChinh Cao * Reports speed/duplex settings based on media_type 207248cb27f2SChinh Cao */ 2073c8b7abddSBruce Allan static int 2074c8b7abddSBruce Allan ice_get_link_ksettings(struct net_device *netdev, 207548cb27f2SChinh Cao struct ethtool_link_ksettings *ks) 207648cb27f2SChinh Cao { 207748cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 2078f776b3acSPaul Greenwalt struct ice_aqc_get_phy_caps_data *caps; 207948cb27f2SChinh Cao struct ice_link_status *hw_link_info; 208048cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 208148cb27f2SChinh Cao 208248cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 208348cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 208448cb27f2SChinh Cao hw_link_info = &vsi->port_info->phy.link_info; 208548cb27f2SChinh Cao 208648cb27f2SChinh Cao /* set speed and duplex */ 208748cb27f2SChinh Cao if (hw_link_info->link_info & ICE_AQ_LINK_UP) 208848cb27f2SChinh Cao ice_get_settings_link_up(ks, netdev); 208948cb27f2SChinh Cao else 209048cb27f2SChinh Cao ice_get_settings_link_down(ks, netdev); 209148cb27f2SChinh Cao 2092fcea6f3dSAnirudh Venkataramanan /* set autoneg settings */ 209348cb27f2SChinh Cao ks->base.autoneg = (hw_link_info->an_info & ICE_AQ_AN_COMPLETED) ? 209448cb27f2SChinh Cao AUTONEG_ENABLE : AUTONEG_DISABLE; 2095fcea6f3dSAnirudh Venkataramanan 2096fcea6f3dSAnirudh Venkataramanan /* set media type settings */ 2097fcea6f3dSAnirudh Venkataramanan switch (vsi->port_info->phy.media_type) { 2098fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_FIBER: 2099fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 2100fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_FIBRE; 2101fcea6f3dSAnirudh Venkataramanan break; 2102fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BASET: 2103fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, TP); 2104fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, TP); 2105fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_TP; 2106fcea6f3dSAnirudh Venkataramanan break; 2107fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BACKPLANE: 2108fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 2109fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Backplane); 2110fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 2111fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 2112fcea6f3dSAnirudh Venkataramanan Backplane); 2113fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_NONE; 2114fcea6f3dSAnirudh Venkataramanan break; 2115fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_DA: 2116fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 2117fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE); 2118fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_DA; 2119fcea6f3dSAnirudh Venkataramanan break; 2120fcea6f3dSAnirudh Venkataramanan default: 2121fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_OTHER; 2122fcea6f3dSAnirudh Venkataramanan break; 2123fcea6f3dSAnirudh Venkataramanan } 2124fcea6f3dSAnirudh Venkataramanan 2125fcea6f3dSAnirudh Venkataramanan /* flow control is symmetric and always supported */ 2126fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Pause); 2127fcea6f3dSAnirudh Venkataramanan 2128fcea6f3dSAnirudh Venkataramanan switch (vsi->port_info->fc.req_mode) { 2129fcea6f3dSAnirudh Venkataramanan case ICE_FC_FULL: 2130fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 2131fcea6f3dSAnirudh Venkataramanan break; 2132fcea6f3dSAnirudh Venkataramanan case ICE_FC_TX_PAUSE: 2133fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 2134fcea6f3dSAnirudh Venkataramanan Asym_Pause); 2135fcea6f3dSAnirudh Venkataramanan break; 2136fcea6f3dSAnirudh Venkataramanan case ICE_FC_RX_PAUSE: 2137fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 2138fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 2139fcea6f3dSAnirudh Venkataramanan Asym_Pause); 2140fcea6f3dSAnirudh Venkataramanan break; 2141fcea6f3dSAnirudh Venkataramanan case ICE_FC_PFC: 2142fcea6f3dSAnirudh Venkataramanan default: 2143fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, Pause); 2144fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, 2145fcea6f3dSAnirudh Venkataramanan Asym_Pause); 2146fcea6f3dSAnirudh Venkataramanan break; 2147fcea6f3dSAnirudh Venkataramanan } 2148fcea6f3dSAnirudh Venkataramanan 2149f776b3acSPaul Greenwalt caps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*caps), GFP_KERNEL); 2150f776b3acSPaul Greenwalt if (!caps) 2151f776b3acSPaul Greenwalt goto done; 2152f776b3acSPaul Greenwalt 2153f776b3acSPaul Greenwalt if (ice_aq_get_phy_caps(vsi->port_info, false, ICE_AQC_REPORT_TOPO_CAP, 2154f776b3acSPaul Greenwalt caps, NULL)) 2155f776b3acSPaul Greenwalt netdev_info(netdev, "Get phy capability failed.\n"); 2156f776b3acSPaul Greenwalt 2157f776b3acSPaul Greenwalt /* Set supported FEC modes based on PHY capability */ 2158f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); 2159f776b3acSPaul Greenwalt 2160f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN || 2161f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN) 2162f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); 2163f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN) 2164f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); 2165f776b3acSPaul Greenwalt 2166f776b3acSPaul Greenwalt if (ice_aq_get_phy_caps(vsi->port_info, false, ICE_AQC_REPORT_SW_CFG, 2167f776b3acSPaul Greenwalt caps, NULL)) 2168f776b3acSPaul Greenwalt netdev_info(netdev, "Get phy capability failed.\n"); 2169f776b3acSPaul Greenwalt 2170f776b3acSPaul Greenwalt /* Set advertised FEC modes based on PHY capability */ 2171f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); 2172f776b3acSPaul Greenwalt 2173f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ || 2174f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_REQ) 2175f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, 2176f776b3acSPaul Greenwalt FEC_BASER); 2177f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_528_REQ || 2178f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_544_REQ) 2179f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); 2180f776b3acSPaul Greenwalt 2181f776b3acSPaul Greenwalt done: 2182f776b3acSPaul Greenwalt devm_kfree(&vsi->back->pdev->dev, caps); 2183fcea6f3dSAnirudh Venkataramanan return 0; 2184fcea6f3dSAnirudh Venkataramanan } 2185fcea6f3dSAnirudh Venkataramanan 2186fcea6f3dSAnirudh Venkataramanan /** 218748cb27f2SChinh Cao * ice_ksettings_find_adv_link_speed - Find advertising link speed 218848cb27f2SChinh Cao * @ks: ethtool ksettings 218948cb27f2SChinh Cao */ 219048cb27f2SChinh Cao static u16 219148cb27f2SChinh Cao ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks) 219248cb27f2SChinh Cao { 219348cb27f2SChinh Cao u16 adv_link_speed = 0; 219448cb27f2SChinh Cao 219548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 219648cb27f2SChinh Cao 100baseT_Full)) 219748cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_100MB; 219848cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 219948cb27f2SChinh Cao 1000baseX_Full)) 220048cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 220148cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 220248cb27f2SChinh Cao 1000baseT_Full) || 220348cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 220448cb27f2SChinh Cao 1000baseKX_Full)) 220548cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 220648cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 220748cb27f2SChinh Cao 2500baseT_Full)) 220848cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 220948cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 221048cb27f2SChinh Cao 2500baseX_Full)) 221148cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 221248cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 221348cb27f2SChinh Cao 5000baseT_Full)) 221448cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_5GB; 221548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 221648cb27f2SChinh Cao 10000baseT_Full) || 221748cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 221848cb27f2SChinh Cao 10000baseKR_Full)) 221948cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 222048cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 222148cb27f2SChinh Cao 10000baseSR_Full) || 222248cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 222348cb27f2SChinh Cao 10000baseLR_Full)) 222448cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 222548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 222648cb27f2SChinh Cao 25000baseCR_Full) || 222748cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 222848cb27f2SChinh Cao 25000baseSR_Full) || 222948cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 223048cb27f2SChinh Cao 25000baseKR_Full)) 223148cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_25GB; 223248cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 223348cb27f2SChinh Cao 40000baseCR4_Full) || 223448cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 223548cb27f2SChinh Cao 40000baseSR4_Full) || 223648cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 223748cb27f2SChinh Cao 40000baseLR4_Full) || 223848cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 223948cb27f2SChinh Cao 40000baseKR4_Full)) 224048cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_40GB; 2241aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2242aef74145SAnirudh Venkataramanan 50000baseCR2_Full) || 2243aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2244aef74145SAnirudh Venkataramanan 50000baseKR2_Full)) 2245aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 2246aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2247aef74145SAnirudh Venkataramanan 50000baseSR2_Full)) 2248aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 2249aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2250aef74145SAnirudh Venkataramanan 100000baseCR4_Full) || 2251aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2252aef74145SAnirudh Venkataramanan 100000baseSR4_Full) || 2253aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2254aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full) || 2255aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2256aef74145SAnirudh Venkataramanan 100000baseKR4_Full)) 2257aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_100GB; 225848cb27f2SChinh Cao 225948cb27f2SChinh Cao return adv_link_speed; 226048cb27f2SChinh Cao } 226148cb27f2SChinh Cao 226248cb27f2SChinh Cao /** 226348cb27f2SChinh Cao * ice_setup_autoneg 226448cb27f2SChinh Cao * @p: port info 226548cb27f2SChinh Cao * @ks: ethtool_link_ksettings 226648cb27f2SChinh Cao * @config: configuration that will be sent down to FW 226748cb27f2SChinh Cao * @autoneg_enabled: autonegotiation is enabled or not 226848cb27f2SChinh Cao * @autoneg_changed: will there a change in autonegotiation 226948cb27f2SChinh Cao * @netdev: network interface device structure 227048cb27f2SChinh Cao * 227148cb27f2SChinh Cao * Setup PHY autonegotiation feature 227248cb27f2SChinh Cao */ 227348cb27f2SChinh Cao static int 227448cb27f2SChinh Cao ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks, 227548cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data *config, 227648cb27f2SChinh Cao u8 autoneg_enabled, u8 *autoneg_changed, 227748cb27f2SChinh Cao struct net_device *netdev) 227848cb27f2SChinh Cao { 227948cb27f2SChinh Cao int err = 0; 228048cb27f2SChinh Cao 228148cb27f2SChinh Cao *autoneg_changed = 0; 228248cb27f2SChinh Cao 228348cb27f2SChinh Cao /* Check autoneg */ 228448cb27f2SChinh Cao if (autoneg_enabled == AUTONEG_ENABLE) { 228548cb27f2SChinh Cao /* If autoneg was not already enabled */ 228648cb27f2SChinh Cao if (!(p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED)) { 228748cb27f2SChinh Cao /* If autoneg is not supported, return error */ 228848cb27f2SChinh Cao if (!ethtool_link_ksettings_test_link_mode(ks, 228948cb27f2SChinh Cao supported, 229048cb27f2SChinh Cao Autoneg)) { 229148cb27f2SChinh Cao netdev_info(netdev, "Autoneg not supported on this phy.\n"); 229248cb27f2SChinh Cao err = -EINVAL; 229348cb27f2SChinh Cao } else { 229448cb27f2SChinh Cao /* Autoneg is allowed to change */ 229548cb27f2SChinh Cao config->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 229648cb27f2SChinh Cao *autoneg_changed = 1; 229748cb27f2SChinh Cao } 229848cb27f2SChinh Cao } 229948cb27f2SChinh Cao } else { 230048cb27f2SChinh Cao /* If autoneg is currently enabled */ 230148cb27f2SChinh Cao if (p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED) { 2302f9867df6SAnirudh Venkataramanan /* If autoneg is supported 10GBASE_T is the only PHY 230348cb27f2SChinh Cao * that can disable it, so otherwise return error 230448cb27f2SChinh Cao */ 230548cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, 230648cb27f2SChinh Cao supported, 230748cb27f2SChinh Cao Autoneg)) { 230848cb27f2SChinh Cao netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); 230948cb27f2SChinh Cao err = -EINVAL; 231048cb27f2SChinh Cao } else { 231148cb27f2SChinh Cao /* Autoneg is allowed to change */ 231248cb27f2SChinh Cao config->caps &= ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 231348cb27f2SChinh Cao *autoneg_changed = 1; 231448cb27f2SChinh Cao } 231548cb27f2SChinh Cao } 231648cb27f2SChinh Cao } 231748cb27f2SChinh Cao 231848cb27f2SChinh Cao return err; 231948cb27f2SChinh Cao } 232048cb27f2SChinh Cao 232148cb27f2SChinh Cao /** 232248cb27f2SChinh Cao * ice_set_link_ksettings - Set Speed and Duplex 232348cb27f2SChinh Cao * @netdev: network interface device structure 232448cb27f2SChinh Cao * @ks: ethtool ksettings 232548cb27f2SChinh Cao * 232648cb27f2SChinh Cao * Set speed/duplex per media_types advertised/forced 232748cb27f2SChinh Cao */ 2328aef74145SAnirudh Venkataramanan static int 2329aef74145SAnirudh Venkataramanan ice_set_link_ksettings(struct net_device *netdev, 233048cb27f2SChinh Cao const struct ethtool_link_ksettings *ks) 233148cb27f2SChinh Cao { 233248cb27f2SChinh Cao u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0; 233348cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 233448cb27f2SChinh Cao struct ethtool_link_ksettings safe_ks, copy_ks; 233548cb27f2SChinh Cao struct ice_aqc_get_phy_caps_data *abilities; 233648cb27f2SChinh Cao u16 adv_link_speed, curr_link_speed, idx; 233748cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data config; 233848cb27f2SChinh Cao struct ice_pf *pf = np->vsi->back; 233948cb27f2SChinh Cao struct ice_port_info *p; 234048cb27f2SChinh Cao u8 autoneg_changed = 0; 234148cb27f2SChinh Cao enum ice_status status; 2342aef74145SAnirudh Venkataramanan u64 phy_type_high; 234348cb27f2SChinh Cao u64 phy_type_low; 234448cb27f2SChinh Cao int err = 0; 234548cb27f2SChinh Cao bool linkup; 234648cb27f2SChinh Cao 234748cb27f2SChinh Cao p = np->vsi->port_info; 234848cb27f2SChinh Cao 234948cb27f2SChinh Cao if (!p) 235048cb27f2SChinh Cao return -EOPNOTSUPP; 235148cb27f2SChinh Cao 2352f9867df6SAnirudh Venkataramanan /* Check if this is LAN VSI */ 235380ed404aSBrett Creeley ice_for_each_vsi(pf, idx) 235448cb27f2SChinh Cao if (pf->vsi[idx]->type == ICE_VSI_PF) { 235548cb27f2SChinh Cao if (np->vsi != pf->vsi[idx]) 235648cb27f2SChinh Cao return -EOPNOTSUPP; 235748cb27f2SChinh Cao break; 235848cb27f2SChinh Cao } 235948cb27f2SChinh Cao 236048cb27f2SChinh Cao if (p->phy.media_type != ICE_MEDIA_BASET && 236148cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_FIBER && 236248cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_BACKPLANE && 236348cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_DA && 236448cb27f2SChinh Cao p->phy.link_info.link_info & ICE_AQ_LINK_UP) 236548cb27f2SChinh Cao return -EOPNOTSUPP; 236648cb27f2SChinh Cao 236748cb27f2SChinh Cao /* copy the ksettings to copy_ks to avoid modifying the original */ 2368c6dfd690SBruce Allan memcpy(©_ks, ks, sizeof(copy_ks)); 236948cb27f2SChinh Cao 237048cb27f2SChinh Cao /* save autoneg out of ksettings */ 237148cb27f2SChinh Cao autoneg = copy_ks.base.autoneg; 237248cb27f2SChinh Cao 237348cb27f2SChinh Cao memset(&safe_ks, 0, sizeof(safe_ks)); 237448cb27f2SChinh Cao 237548cb27f2SChinh Cao /* Get link modes supported by hardware.*/ 237648cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, &safe_ks); 237748cb27f2SChinh Cao 237848cb27f2SChinh Cao /* and check against modes requested by user. 237948cb27f2SChinh Cao * Return an error if unsupported mode was set. 238048cb27f2SChinh Cao */ 238148cb27f2SChinh Cao if (!bitmap_subset(copy_ks.link_modes.advertising, 238248cb27f2SChinh Cao safe_ks.link_modes.supported, 238348cb27f2SChinh Cao __ETHTOOL_LINK_MODE_MASK_NBITS)) 238448cb27f2SChinh Cao return -EINVAL; 238548cb27f2SChinh Cao 238648cb27f2SChinh Cao /* get our own copy of the bits to check against */ 2387c6dfd690SBruce Allan memset(&safe_ks, 0, sizeof(safe_ks)); 238848cb27f2SChinh Cao safe_ks.base.cmd = copy_ks.base.cmd; 238948cb27f2SChinh Cao safe_ks.base.link_mode_masks_nwords = 239048cb27f2SChinh Cao copy_ks.base.link_mode_masks_nwords; 239148cb27f2SChinh Cao ice_get_link_ksettings(netdev, &safe_ks); 239248cb27f2SChinh Cao 239348cb27f2SChinh Cao /* set autoneg back to what it currently is */ 239448cb27f2SChinh Cao copy_ks.base.autoneg = safe_ks.base.autoneg; 239548cb27f2SChinh Cao /* we don't compare the speed */ 239648cb27f2SChinh Cao copy_ks.base.speed = safe_ks.base.speed; 239748cb27f2SChinh Cao 239848cb27f2SChinh Cao /* If copy_ks.base and safe_ks.base are not the same now, then they are 239948cb27f2SChinh Cao * trying to set something that we do not support. 240048cb27f2SChinh Cao */ 2401c6dfd690SBruce Allan if (memcmp(©_ks.base, &safe_ks.base, sizeof(copy_ks.base))) 240248cb27f2SChinh Cao return -EOPNOTSUPP; 240348cb27f2SChinh Cao 240448cb27f2SChinh Cao while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 240548cb27f2SChinh Cao timeout--; 240648cb27f2SChinh Cao if (!timeout) 240748cb27f2SChinh Cao return -EBUSY; 240848cb27f2SChinh Cao usleep_range(TEST_SET_BITS_SLEEP_MIN, TEST_SET_BITS_SLEEP_MAX); 240948cb27f2SChinh Cao } 241048cb27f2SChinh Cao 241148cb27f2SChinh Cao abilities = devm_kzalloc(&pf->pdev->dev, sizeof(*abilities), 241248cb27f2SChinh Cao GFP_KERNEL); 241348cb27f2SChinh Cao if (!abilities) 241448cb27f2SChinh Cao return -ENOMEM; 241548cb27f2SChinh Cao 2416f9867df6SAnirudh Venkataramanan /* Get the current PHY config */ 241748cb27f2SChinh Cao status = ice_aq_get_phy_caps(p, false, ICE_AQC_REPORT_SW_CFG, abilities, 241848cb27f2SChinh Cao NULL); 241948cb27f2SChinh Cao if (status) { 242048cb27f2SChinh Cao err = -EAGAIN; 242148cb27f2SChinh Cao goto done; 242248cb27f2SChinh Cao } 242348cb27f2SChinh Cao 242448cb27f2SChinh Cao /* Copy abilities to config in case autoneg is not set below */ 2425c6dfd690SBruce Allan memset(&config, 0, sizeof(config)); 242648cb27f2SChinh Cao config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE; 242748cb27f2SChinh Cao if (abilities->caps & ICE_AQC_PHY_AN_MODE) 242848cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 242948cb27f2SChinh Cao 243048cb27f2SChinh Cao /* Check autoneg */ 243148cb27f2SChinh Cao err = ice_setup_autoneg(p, &safe_ks, &config, autoneg, &autoneg_changed, 243248cb27f2SChinh Cao netdev); 243348cb27f2SChinh Cao 243448cb27f2SChinh Cao if (err) 243548cb27f2SChinh Cao goto done; 243648cb27f2SChinh Cao 243748cb27f2SChinh Cao /* Call to get the current link speed */ 243848cb27f2SChinh Cao p->phy.get_link_info = true; 243948cb27f2SChinh Cao status = ice_get_link_status(p, &linkup); 244048cb27f2SChinh Cao if (status) { 244148cb27f2SChinh Cao err = -EAGAIN; 244248cb27f2SChinh Cao goto done; 244348cb27f2SChinh Cao } 244448cb27f2SChinh Cao 244548cb27f2SChinh Cao curr_link_speed = p->phy.link_info.link_speed; 244648cb27f2SChinh Cao adv_link_speed = ice_ksettings_find_adv_link_speed(ks); 244748cb27f2SChinh Cao 244848cb27f2SChinh Cao /* If speed didn't get set, set it to what it currently is. 244948cb27f2SChinh Cao * This is needed because if advertise is 0 (as it is when autoneg 245048cb27f2SChinh Cao * is disabled) then speed won't get set. 245148cb27f2SChinh Cao */ 245248cb27f2SChinh Cao if (!adv_link_speed) 245348cb27f2SChinh Cao adv_link_speed = curr_link_speed; 245448cb27f2SChinh Cao 245548cb27f2SChinh Cao /* Convert the advertise link speeds to their corresponded PHY_TYPE */ 2456aef74145SAnirudh Venkataramanan ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed); 245748cb27f2SChinh Cao 245848cb27f2SChinh Cao if (!autoneg_changed && adv_link_speed == curr_link_speed) { 245948cb27f2SChinh Cao netdev_info(netdev, "Nothing changed, exiting without setting anything.\n"); 246048cb27f2SChinh Cao goto done; 246148cb27f2SChinh Cao } 246248cb27f2SChinh Cao 246348cb27f2SChinh Cao /* copy over the rest of the abilities */ 246448cb27f2SChinh Cao config.low_power_ctrl = abilities->low_power_ctrl; 246548cb27f2SChinh Cao config.eee_cap = abilities->eee_cap; 246648cb27f2SChinh Cao config.eeer_value = abilities->eeer_value; 246748cb27f2SChinh Cao config.link_fec_opt = abilities->link_fec_options; 246848cb27f2SChinh Cao 246948cb27f2SChinh Cao /* save the requested speeds */ 247048cb27f2SChinh Cao p->phy.link_info.req_speeds = adv_link_speed; 247148cb27f2SChinh Cao 247248cb27f2SChinh Cao /* set link and auto negotiation so changes take effect */ 247348cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_LINK; 247448cb27f2SChinh Cao 2475aef74145SAnirudh Venkataramanan if (phy_type_low || phy_type_high) { 2476aef74145SAnirudh Venkataramanan config.phy_type_high = cpu_to_le64(phy_type_high) & 2477aef74145SAnirudh Venkataramanan abilities->phy_type_high; 247848cb27f2SChinh Cao config.phy_type_low = cpu_to_le64(phy_type_low) & 247948cb27f2SChinh Cao abilities->phy_type_low; 248048cb27f2SChinh Cao } else { 248148cb27f2SChinh Cao err = -EAGAIN; 248248cb27f2SChinh Cao netdev_info(netdev, "Nothing changed. No PHY_TYPE is corresponded to advertised link speed.\n"); 248348cb27f2SChinh Cao goto done; 248448cb27f2SChinh Cao } 248548cb27f2SChinh Cao 248648cb27f2SChinh Cao /* If link is up put link down */ 248748cb27f2SChinh Cao if (p->phy.link_info.link_info & ICE_AQ_LINK_UP) { 248848cb27f2SChinh Cao /* Tell the OS link is going down, the link will go 248948cb27f2SChinh Cao * back up when fw says it is ready asynchronously 249048cb27f2SChinh Cao */ 249148cb27f2SChinh Cao ice_print_link_msg(np->vsi, false); 249248cb27f2SChinh Cao netif_carrier_off(netdev); 249348cb27f2SChinh Cao netif_tx_stop_all_queues(netdev); 249448cb27f2SChinh Cao } 249548cb27f2SChinh Cao 249648cb27f2SChinh Cao /* make the aq call */ 249748cb27f2SChinh Cao status = ice_aq_set_phy_cfg(&pf->hw, lport, &config, NULL); 249848cb27f2SChinh Cao if (status) { 249948cb27f2SChinh Cao netdev_info(netdev, "Set phy config failed,\n"); 250048cb27f2SChinh Cao err = -EAGAIN; 250148cb27f2SChinh Cao } 250248cb27f2SChinh Cao 250348cb27f2SChinh Cao done: 250448cb27f2SChinh Cao devm_kfree(&pf->pdev->dev, abilities); 250548cb27f2SChinh Cao clear_bit(__ICE_CFG_BUSY, pf->state); 250648cb27f2SChinh Cao 250748cb27f2SChinh Cao return err; 250848cb27f2SChinh Cao } 250948cb27f2SChinh Cao 251048cb27f2SChinh Cao /** 2511f9867df6SAnirudh Venkataramanan * ice_get_rxnfc - command to get Rx flow classification rules 2512fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2513fcea6f3dSAnirudh Venkataramanan * @cmd: ethtool rxnfc command 2514fcea6f3dSAnirudh Venkataramanan * @rule_locs: buffer to rturn Rx flow classification rules 2515fcea6f3dSAnirudh Venkataramanan * 2516fcea6f3dSAnirudh Venkataramanan * Returns Success if the command is supported. 2517fcea6f3dSAnirudh Venkataramanan */ 2518c8b7abddSBruce Allan static int 2519c8b7abddSBruce Allan ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, 2520fcea6f3dSAnirudh Venkataramanan u32 __always_unused *rule_locs) 2521fcea6f3dSAnirudh Venkataramanan { 2522fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2523fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2524fcea6f3dSAnirudh Venkataramanan int ret = -EOPNOTSUPP; 2525fcea6f3dSAnirudh Venkataramanan 2526fcea6f3dSAnirudh Venkataramanan switch (cmd->cmd) { 2527fcea6f3dSAnirudh Venkataramanan case ETHTOOL_GRXRINGS: 2528fcea6f3dSAnirudh Venkataramanan cmd->data = vsi->rss_size; 2529fcea6f3dSAnirudh Venkataramanan ret = 0; 2530fcea6f3dSAnirudh Venkataramanan break; 2531fcea6f3dSAnirudh Venkataramanan default: 2532fcea6f3dSAnirudh Venkataramanan break; 2533fcea6f3dSAnirudh Venkataramanan } 2534fcea6f3dSAnirudh Venkataramanan 2535fcea6f3dSAnirudh Venkataramanan return ret; 2536fcea6f3dSAnirudh Venkataramanan } 2537fcea6f3dSAnirudh Venkataramanan 2538fcea6f3dSAnirudh Venkataramanan static void 2539fcea6f3dSAnirudh Venkataramanan ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 2540fcea6f3dSAnirudh Venkataramanan { 2541fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2542fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2543fcea6f3dSAnirudh Venkataramanan 2544fcea6f3dSAnirudh Venkataramanan ring->rx_max_pending = ICE_MAX_NUM_DESC; 2545fcea6f3dSAnirudh Venkataramanan ring->tx_max_pending = ICE_MAX_NUM_DESC; 2546fcea6f3dSAnirudh Venkataramanan ring->rx_pending = vsi->rx_rings[0]->count; 2547fcea6f3dSAnirudh Venkataramanan ring->tx_pending = vsi->tx_rings[0]->count; 2548f934bb9bSBruce Allan 2549f934bb9bSBruce Allan /* Rx mini and jumbo rings are not supported */ 2550fcea6f3dSAnirudh Venkataramanan ring->rx_mini_max_pending = 0; 2551fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_max_pending = 0; 2552f934bb9bSBruce Allan ring->rx_mini_pending = 0; 2553fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_pending = 0; 2554fcea6f3dSAnirudh Venkataramanan } 2555fcea6f3dSAnirudh Venkataramanan 2556fcea6f3dSAnirudh Venkataramanan static int 2557fcea6f3dSAnirudh Venkataramanan ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 2558fcea6f3dSAnirudh Venkataramanan { 2559fcea6f3dSAnirudh Venkataramanan struct ice_ring *tx_rings = NULL, *rx_rings = NULL; 2560fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2561fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2562fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2563fcea6f3dSAnirudh Venkataramanan int i, timeout = 50, err = 0; 2564fcea6f3dSAnirudh Venkataramanan u32 new_rx_cnt, new_tx_cnt; 2565fcea6f3dSAnirudh Venkataramanan 2566fcea6f3dSAnirudh Venkataramanan if (ring->tx_pending > ICE_MAX_NUM_DESC || 2567fcea6f3dSAnirudh Venkataramanan ring->tx_pending < ICE_MIN_NUM_DESC || 2568fcea6f3dSAnirudh Venkataramanan ring->rx_pending > ICE_MAX_NUM_DESC || 2569fcea6f3dSAnirudh Venkataramanan ring->rx_pending < ICE_MIN_NUM_DESC) { 2570f934bb9bSBruce Allan netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", 2571fcea6f3dSAnirudh Venkataramanan ring->tx_pending, ring->rx_pending, 2572f934bb9bSBruce Allan ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC, 2573f934bb9bSBruce Allan ICE_REQ_DESC_MULTIPLE); 2574fcea6f3dSAnirudh Venkataramanan return -EINVAL; 2575fcea6f3dSAnirudh Venkataramanan } 2576fcea6f3dSAnirudh Venkataramanan 2577fcea6f3dSAnirudh Venkataramanan new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE); 2578f934bb9bSBruce Allan if (new_tx_cnt != ring->tx_pending) 2579f934bb9bSBruce Allan netdev_info(netdev, 2580f934bb9bSBruce Allan "Requested Tx descriptor count rounded up to %d\n", 2581f934bb9bSBruce Allan new_tx_cnt); 2582fcea6f3dSAnirudh Venkataramanan new_rx_cnt = ALIGN(ring->rx_pending, ICE_REQ_DESC_MULTIPLE); 2583f934bb9bSBruce Allan if (new_rx_cnt != ring->rx_pending) 2584f934bb9bSBruce Allan netdev_info(netdev, 2585f934bb9bSBruce Allan "Requested Rx descriptor count rounded up to %d\n", 2586f934bb9bSBruce Allan new_rx_cnt); 2587fcea6f3dSAnirudh Venkataramanan 2588fcea6f3dSAnirudh Venkataramanan /* if nothing to do return success */ 2589fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count && 2590fcea6f3dSAnirudh Venkataramanan new_rx_cnt == vsi->rx_rings[0]->count) { 2591fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); 2592fcea6f3dSAnirudh Venkataramanan return 0; 2593fcea6f3dSAnirudh Venkataramanan } 2594fcea6f3dSAnirudh Venkataramanan 2595fcea6f3dSAnirudh Venkataramanan while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 2596fcea6f3dSAnirudh Venkataramanan timeout--; 2597fcea6f3dSAnirudh Venkataramanan if (!timeout) 2598fcea6f3dSAnirudh Venkataramanan return -EBUSY; 2599fcea6f3dSAnirudh Venkataramanan usleep_range(1000, 2000); 2600fcea6f3dSAnirudh Venkataramanan } 2601fcea6f3dSAnirudh Venkataramanan 2602fcea6f3dSAnirudh Venkataramanan /* set for the next time the netdev is started */ 2603fcea6f3dSAnirudh Venkataramanan if (!netif_running(vsi->netdev)) { 2604fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) 2605fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[i]->count = new_tx_cnt; 2606fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) 2607fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[i]->count = new_rx_cnt; 2608fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Link is down, descriptor count change happens when link is brought up\n"); 2609fcea6f3dSAnirudh Venkataramanan goto done; 2610fcea6f3dSAnirudh Venkataramanan } 2611fcea6f3dSAnirudh Venkataramanan 2612fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count) 2613fcea6f3dSAnirudh Venkataramanan goto process_rx; 2614fcea6f3dSAnirudh Venkataramanan 2615fcea6f3dSAnirudh Venkataramanan /* alloc updated Tx resources */ 2616fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Tx descriptor count from %d to %d\n", 2617fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[0]->count, new_tx_cnt); 2618fcea6f3dSAnirudh Venkataramanan 2619fcea6f3dSAnirudh Venkataramanan tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 2620c6dfd690SBruce Allan sizeof(*tx_rings), GFP_KERNEL); 2621fcea6f3dSAnirudh Venkataramanan if (!tx_rings) { 2622fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2623fcea6f3dSAnirudh Venkataramanan goto done; 2624fcea6f3dSAnirudh Venkataramanan } 2625fcea6f3dSAnirudh Venkataramanan 2626f8ba7db8SJacob Keller for (i = 0; i < vsi->alloc_txq; i++) { 2627fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 2628fcea6f3dSAnirudh Venkataramanan tx_rings[i] = *vsi->tx_rings[i]; 2629fcea6f3dSAnirudh Venkataramanan tx_rings[i].count = new_tx_cnt; 2630fcea6f3dSAnirudh Venkataramanan tx_rings[i].desc = NULL; 2631fcea6f3dSAnirudh Venkataramanan tx_rings[i].tx_buf = NULL; 2632fcea6f3dSAnirudh Venkataramanan err = ice_setup_tx_ring(&tx_rings[i]); 2633fcea6f3dSAnirudh Venkataramanan if (err) { 2634fcea6f3dSAnirudh Venkataramanan while (i) { 2635fcea6f3dSAnirudh Venkataramanan i--; 2636fcea6f3dSAnirudh Venkataramanan ice_clean_tx_ring(&tx_rings[i]); 2637fcea6f3dSAnirudh Venkataramanan } 2638fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 2639fcea6f3dSAnirudh Venkataramanan goto done; 2640fcea6f3dSAnirudh Venkataramanan } 2641fcea6f3dSAnirudh Venkataramanan } 2642fcea6f3dSAnirudh Venkataramanan 2643fcea6f3dSAnirudh Venkataramanan process_rx: 2644fcea6f3dSAnirudh Venkataramanan if (new_rx_cnt == vsi->rx_rings[0]->count) 2645fcea6f3dSAnirudh Venkataramanan goto process_link; 2646fcea6f3dSAnirudh Venkataramanan 2647fcea6f3dSAnirudh Venkataramanan /* alloc updated Rx resources */ 2648fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Rx descriptor count from %d to %d\n", 2649fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[0]->count, new_rx_cnt); 2650fcea6f3dSAnirudh Venkataramanan 2651fcea6f3dSAnirudh Venkataramanan rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 2652c6dfd690SBruce Allan sizeof(*rx_rings), GFP_KERNEL); 2653fcea6f3dSAnirudh Venkataramanan if (!rx_rings) { 2654fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2655fcea6f3dSAnirudh Venkataramanan goto done; 2656fcea6f3dSAnirudh Venkataramanan } 2657fcea6f3dSAnirudh Venkataramanan 2658f8ba7db8SJacob Keller for (i = 0; i < vsi->alloc_rxq; i++) { 2659fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 2660fcea6f3dSAnirudh Venkataramanan rx_rings[i] = *vsi->rx_rings[i]; 2661fcea6f3dSAnirudh Venkataramanan rx_rings[i].count = new_rx_cnt; 2662fcea6f3dSAnirudh Venkataramanan rx_rings[i].desc = NULL; 2663fcea6f3dSAnirudh Venkataramanan rx_rings[i].rx_buf = NULL; 2664fcea6f3dSAnirudh Venkataramanan /* this is to allow wr32 to have something to write to 2665fcea6f3dSAnirudh Venkataramanan * during early allocation of Rx buffers 2666fcea6f3dSAnirudh Venkataramanan */ 2667fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->back->hw.hw_addr + PRTGEN_STATUS; 2668fcea6f3dSAnirudh Venkataramanan 2669fcea6f3dSAnirudh Venkataramanan err = ice_setup_rx_ring(&rx_rings[i]); 2670fcea6f3dSAnirudh Venkataramanan if (err) 2671fcea6f3dSAnirudh Venkataramanan goto rx_unwind; 2672fcea6f3dSAnirudh Venkataramanan 2673fcea6f3dSAnirudh Venkataramanan /* allocate Rx buffers */ 2674fcea6f3dSAnirudh Venkataramanan err = ice_alloc_rx_bufs(&rx_rings[i], 2675fcea6f3dSAnirudh Venkataramanan ICE_DESC_UNUSED(&rx_rings[i])); 2676fcea6f3dSAnirudh Venkataramanan rx_unwind: 2677fcea6f3dSAnirudh Venkataramanan if (err) { 2678fcea6f3dSAnirudh Venkataramanan while (i) { 2679fcea6f3dSAnirudh Venkataramanan i--; 2680fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(&rx_rings[i]); 2681fcea6f3dSAnirudh Venkataramanan } 2682fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, rx_rings); 2683fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2684fcea6f3dSAnirudh Venkataramanan goto free_tx; 2685fcea6f3dSAnirudh Venkataramanan } 2686fcea6f3dSAnirudh Venkataramanan } 2687fcea6f3dSAnirudh Venkataramanan 2688fcea6f3dSAnirudh Venkataramanan process_link: 2689fcea6f3dSAnirudh Venkataramanan /* Bring interface down, copy in the new ring info, then restore the 2690fcea6f3dSAnirudh Venkataramanan * interface. if VSI is up, bring it down and then back up 2691fcea6f3dSAnirudh Venkataramanan */ 2692fcea6f3dSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) { 2693fcea6f3dSAnirudh Venkataramanan ice_down(vsi); 2694fcea6f3dSAnirudh Venkataramanan 2695fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 2696fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 2697fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 2698fcea6f3dSAnirudh Venkataramanan *vsi->tx_rings[i] = tx_rings[i]; 2699fcea6f3dSAnirudh Venkataramanan } 2700fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 2701fcea6f3dSAnirudh Venkataramanan } 2702fcea6f3dSAnirudh Venkataramanan 2703fcea6f3dSAnirudh Venkataramanan if (rx_rings) { 2704fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 2705fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 2706fcea6f3dSAnirudh Venkataramanan /* copy the real tail offset */ 2707fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->rx_rings[i]->tail; 2708fcea6f3dSAnirudh Venkataramanan /* this is to fake out the allocation routine 2709fcea6f3dSAnirudh Venkataramanan * into thinking it has to realloc everything 2710fcea6f3dSAnirudh Venkataramanan * but the recycling logic will let us re-use 2711fcea6f3dSAnirudh Venkataramanan * the buffers allocated above 2712fcea6f3dSAnirudh Venkataramanan */ 2713fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_use = 0; 2714fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_clean = 0; 2715fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_alloc = 0; 2716fcea6f3dSAnirudh Venkataramanan *vsi->rx_rings[i] = rx_rings[i]; 2717fcea6f3dSAnirudh Venkataramanan } 2718fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, rx_rings); 2719fcea6f3dSAnirudh Venkataramanan } 2720fcea6f3dSAnirudh Venkataramanan 2721fcea6f3dSAnirudh Venkataramanan ice_up(vsi); 2722fcea6f3dSAnirudh Venkataramanan } 2723fcea6f3dSAnirudh Venkataramanan goto done; 2724fcea6f3dSAnirudh Venkataramanan 2725fcea6f3dSAnirudh Venkataramanan free_tx: 2726fcea6f3dSAnirudh Venkataramanan /* error cleanup if the Rx allocations failed after getting Tx */ 2727fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 2728fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) 2729fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(&tx_rings[i]); 2730fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, tx_rings); 2731fcea6f3dSAnirudh Venkataramanan } 2732fcea6f3dSAnirudh Venkataramanan 2733fcea6f3dSAnirudh Venkataramanan done: 2734fcea6f3dSAnirudh Venkataramanan clear_bit(__ICE_CFG_BUSY, pf->state); 2735fcea6f3dSAnirudh Venkataramanan return err; 2736fcea6f3dSAnirudh Venkataramanan } 2737fcea6f3dSAnirudh Venkataramanan 2738fcea6f3dSAnirudh Venkataramanan static int ice_nway_reset(struct net_device *netdev) 2739fcea6f3dSAnirudh Venkataramanan { 2740fcea6f3dSAnirudh Venkataramanan /* restart autonegotiation */ 2741fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2742fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2743fcea6f3dSAnirudh Venkataramanan struct ice_port_info *pi; 2744fcea6f3dSAnirudh Venkataramanan enum ice_status status; 2745fcea6f3dSAnirudh Venkataramanan 2746fcea6f3dSAnirudh Venkataramanan pi = vsi->port_info; 2747d38b0883SAkeem G Abodunrin /* If VSI state is up, then restart autoneg with link up */ 2748d38b0883SAkeem G Abodunrin if (!test_bit(__ICE_DOWN, vsi->back->state)) 2749d38b0883SAkeem G Abodunrin status = ice_aq_set_link_restart_an(pi, true, NULL); 2750d38b0883SAkeem G Abodunrin else 2751d38b0883SAkeem G Abodunrin status = ice_aq_set_link_restart_an(pi, false, NULL); 2752fcea6f3dSAnirudh Venkataramanan 2753fcea6f3dSAnirudh Venkataramanan if (status) { 2754fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "link restart failed, err %d aq_err %d\n", 2755fcea6f3dSAnirudh Venkataramanan status, pi->hw->adminq.sq_last_status); 2756fcea6f3dSAnirudh Venkataramanan return -EIO; 2757fcea6f3dSAnirudh Venkataramanan } 2758fcea6f3dSAnirudh Venkataramanan 2759fcea6f3dSAnirudh Venkataramanan return 0; 2760fcea6f3dSAnirudh Venkataramanan } 2761fcea6f3dSAnirudh Venkataramanan 2762fcea6f3dSAnirudh Venkataramanan /** 2763fcea6f3dSAnirudh Venkataramanan * ice_get_pauseparam - Get Flow Control status 2764fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2765fcea6f3dSAnirudh Venkataramanan * @pause: ethernet pause (flow control) parameters 2766fcea6f3dSAnirudh Venkataramanan */ 2767fcea6f3dSAnirudh Venkataramanan static void 2768fcea6f3dSAnirudh Venkataramanan ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 2769fcea6f3dSAnirudh Venkataramanan { 2770fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 277140c3c546SLukasz Czapnik struct ice_port_info *pi = np->vsi->port_info; 277240c3c546SLukasz Czapnik struct ice_aqc_get_phy_caps_data *pcaps; 277340c3c546SLukasz Czapnik struct ice_vsi *vsi = np->vsi; 27743a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 277540c3c546SLukasz Czapnik enum ice_status status; 2776fcea6f3dSAnirudh Venkataramanan 277740c3c546SLukasz Czapnik /* Initialize pause params */ 277840c3c546SLukasz Czapnik pause->rx_pause = 0; 277940c3c546SLukasz Czapnik pause->tx_pause = 0; 278040c3c546SLukasz Czapnik 27813a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 27823a257a14SAnirudh Venkataramanan 278340c3c546SLukasz Czapnik pcaps = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*pcaps), 278440c3c546SLukasz Czapnik GFP_KERNEL); 278540c3c546SLukasz Czapnik if (!pcaps) 278640c3c546SLukasz Czapnik return; 278740c3c546SLukasz Czapnik 2788f9867df6SAnirudh Venkataramanan /* Get current PHY config */ 278940c3c546SLukasz Czapnik status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, 279040c3c546SLukasz Czapnik NULL); 279140c3c546SLukasz Czapnik if (status) 279240c3c546SLukasz Czapnik goto out; 279340c3c546SLukasz Czapnik 279440c3c546SLukasz Czapnik pause->autoneg = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ? 2795fcea6f3dSAnirudh Venkataramanan AUTONEG_ENABLE : AUTONEG_DISABLE); 2796fcea6f3dSAnirudh Venkataramanan 27973a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) 27983a257a14SAnirudh Venkataramanan /* PFC enabled so report LFC as off */ 27993a257a14SAnirudh Venkataramanan goto out; 28003a257a14SAnirudh Venkataramanan 280140c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) 2802fcea6f3dSAnirudh Venkataramanan pause->tx_pause = 1; 280340c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 2804fcea6f3dSAnirudh Venkataramanan pause->rx_pause = 1; 280540c3c546SLukasz Czapnik 280640c3c546SLukasz Czapnik out: 280740c3c546SLukasz Czapnik devm_kfree(&vsi->back->pdev->dev, pcaps); 2808fcea6f3dSAnirudh Venkataramanan } 2809fcea6f3dSAnirudh Venkataramanan 2810fcea6f3dSAnirudh Venkataramanan /** 2811fcea6f3dSAnirudh Venkataramanan * ice_set_pauseparam - Set Flow Control parameter 2812fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2813d337f2afSAnirudh Venkataramanan * @pause: return Tx/Rx flow control status 2814fcea6f3dSAnirudh Venkataramanan */ 2815fcea6f3dSAnirudh Venkataramanan static int 2816fcea6f3dSAnirudh Venkataramanan ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 2817fcea6f3dSAnirudh Venkataramanan { 2818fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2819fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 2820fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 28213a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 2822fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2823fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2824fcea6f3dSAnirudh Venkataramanan struct ice_port_info *pi; 2825fcea6f3dSAnirudh Venkataramanan enum ice_status status; 2826fcea6f3dSAnirudh Venkataramanan u8 aq_failures; 2827fcea6f3dSAnirudh Venkataramanan bool link_up; 2828fcea6f3dSAnirudh Venkataramanan int err = 0; 2829fcea6f3dSAnirudh Venkataramanan 2830fcea6f3dSAnirudh Venkataramanan pi = vsi->port_info; 2831fcea6f3dSAnirudh Venkataramanan hw_link_info = &pi->phy.link_info; 28323a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 2833fcea6f3dSAnirudh Venkataramanan link_up = hw_link_info->link_info & ICE_AQ_LINK_UP; 2834fcea6f3dSAnirudh Venkataramanan 2835fcea6f3dSAnirudh Venkataramanan /* Changing the port's flow control is not supported if this isn't the 2836fcea6f3dSAnirudh Venkataramanan * PF VSI 2837fcea6f3dSAnirudh Venkataramanan */ 2838fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) { 2839fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing flow control parameters only supported for PF VSI\n"); 2840fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2841fcea6f3dSAnirudh Venkataramanan } 2842fcea6f3dSAnirudh Venkataramanan 2843fcea6f3dSAnirudh Venkataramanan if (pause->autoneg != (hw_link_info->an_info & ICE_AQ_AN_COMPLETED)) { 2844fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n"); 2845fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2846fcea6f3dSAnirudh Venkataramanan } 2847fcea6f3dSAnirudh Venkataramanan 2848fcea6f3dSAnirudh Venkataramanan /* If we have link and don't have autoneg */ 2849fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state) && 2850fcea6f3dSAnirudh Venkataramanan !(hw_link_info->an_info & ICE_AQ_AN_COMPLETED)) { 2851fcea6f3dSAnirudh Venkataramanan /* Send message that it might not necessarily work*/ 2852fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n"); 2853fcea6f3dSAnirudh Venkataramanan } 2854fcea6f3dSAnirudh Venkataramanan 28553a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) { 28563a257a14SAnirudh Venkataramanan netdev_info(netdev, "Priority flow control enabled. Cannot set link flow control.\n"); 28573a257a14SAnirudh Venkataramanan return -EOPNOTSUPP; 28583a257a14SAnirudh Venkataramanan } 2859fcea6f3dSAnirudh Venkataramanan if (pause->rx_pause && pause->tx_pause) 2860fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_FULL; 2861fcea6f3dSAnirudh Venkataramanan else if (pause->rx_pause && !pause->tx_pause) 2862fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_RX_PAUSE; 2863fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && pause->tx_pause) 2864fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_TX_PAUSE; 2865fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && !pause->tx_pause) 2866fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_NONE; 2867fcea6f3dSAnirudh Venkataramanan else 2868fcea6f3dSAnirudh Venkataramanan return -EINVAL; 2869fcea6f3dSAnirudh Venkataramanan 2870fcea6f3dSAnirudh Venkataramanan /* Tell the OS link is going down, the link will go back up when fw 2871fcea6f3dSAnirudh Venkataramanan * says it is ready asynchronously 2872fcea6f3dSAnirudh Venkataramanan */ 2873fcea6f3dSAnirudh Venkataramanan ice_print_link_msg(vsi, false); 2874fcea6f3dSAnirudh Venkataramanan netif_carrier_off(netdev); 2875fcea6f3dSAnirudh Venkataramanan netif_tx_stop_all_queues(netdev); 2876fcea6f3dSAnirudh Venkataramanan 2877fcea6f3dSAnirudh Venkataramanan /* Set the FC mode and only restart AN if link is up */ 2878fcea6f3dSAnirudh Venkataramanan status = ice_set_fc(pi, &aq_failures, link_up); 2879fcea6f3dSAnirudh Venkataramanan 2880fcea6f3dSAnirudh Venkataramanan if (aq_failures & ICE_SET_FC_AQ_FAIL_GET) { 2881fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the get_phy_capabilities call with err %d aq_err %d\n", 2882fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2883fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2884fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_SET) { 2885fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the set_phy_config call with err %d aq_err %d\n", 2886fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2887fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2888fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_UPDATE) { 2889fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Set fc failed on the get_link_info call with err %d aq_err %d\n", 2890fcea6f3dSAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2891fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2892fcea6f3dSAnirudh Venkataramanan } 2893fcea6f3dSAnirudh Venkataramanan 2894fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) { 28950f5d4c21SAkeem G Abodunrin /* Give it a little more time to try to come back. If still 28960f5d4c21SAkeem G Abodunrin * down, restart autoneg link or reinitialize the interface. 28970f5d4c21SAkeem G Abodunrin */ 2898fcea6f3dSAnirudh Venkataramanan msleep(75); 2899fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state)) 2900fcea6f3dSAnirudh Venkataramanan return ice_nway_reset(netdev); 29010f5d4c21SAkeem G Abodunrin 29020f5d4c21SAkeem G Abodunrin ice_down(vsi); 29030f5d4c21SAkeem G Abodunrin ice_up(vsi); 2904fcea6f3dSAnirudh Venkataramanan } 2905fcea6f3dSAnirudh Venkataramanan 2906fcea6f3dSAnirudh Venkataramanan return err; 2907fcea6f3dSAnirudh Venkataramanan } 2908fcea6f3dSAnirudh Venkataramanan 2909fcea6f3dSAnirudh Venkataramanan /** 2910fcea6f3dSAnirudh Venkataramanan * ice_get_rxfh_key_size - get the RSS hash key size 2911fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2912fcea6f3dSAnirudh Venkataramanan * 2913fcea6f3dSAnirudh Venkataramanan * Returns the table size. 2914fcea6f3dSAnirudh Venkataramanan */ 2915fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_key_size(struct net_device __always_unused *netdev) 2916fcea6f3dSAnirudh Venkataramanan { 2917fcea6f3dSAnirudh Venkataramanan return ICE_VSIQF_HKEY_ARRAY_SIZE; 2918fcea6f3dSAnirudh Venkataramanan } 2919fcea6f3dSAnirudh Venkataramanan 2920fcea6f3dSAnirudh Venkataramanan /** 2921d337f2afSAnirudh Venkataramanan * ice_get_rxfh_indir_size - get the Rx flow hash indirection table size 2922fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2923fcea6f3dSAnirudh Venkataramanan * 2924fcea6f3dSAnirudh Venkataramanan * Returns the table size. 2925fcea6f3dSAnirudh Venkataramanan */ 2926fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_indir_size(struct net_device *netdev) 2927fcea6f3dSAnirudh Venkataramanan { 2928fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2929fcea6f3dSAnirudh Venkataramanan 2930fcea6f3dSAnirudh Venkataramanan return np->vsi->rss_table_size; 2931fcea6f3dSAnirudh Venkataramanan } 2932fcea6f3dSAnirudh Venkataramanan 2933fcea6f3dSAnirudh Venkataramanan /** 2934d337f2afSAnirudh Venkataramanan * ice_get_rxfh - get the Rx flow hash indirection table 2935fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2936fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 2937fcea6f3dSAnirudh Venkataramanan * @key: hash key 2938fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 2939fcea6f3dSAnirudh Venkataramanan * 2940fcea6f3dSAnirudh Venkataramanan * Reads the indirection table directly from the hardware. 2941fcea6f3dSAnirudh Venkataramanan */ 2942fcea6f3dSAnirudh Venkataramanan static int 2943fcea6f3dSAnirudh Venkataramanan ice_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) 2944fcea6f3dSAnirudh Venkataramanan { 2945fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2946fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2947fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2948fcea6f3dSAnirudh Venkataramanan int ret = 0, i; 2949fcea6f3dSAnirudh Venkataramanan u8 *lut; 2950fcea6f3dSAnirudh Venkataramanan 2951fcea6f3dSAnirudh Venkataramanan if (hfunc) 2952fcea6f3dSAnirudh Venkataramanan *hfunc = ETH_RSS_HASH_TOP; 2953fcea6f3dSAnirudh Venkataramanan 2954fcea6f3dSAnirudh Venkataramanan if (!indir) 2955fcea6f3dSAnirudh Venkataramanan return 0; 2956fcea6f3dSAnirudh Venkataramanan 2957fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 2958fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 2959fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 2960fcea6f3dSAnirudh Venkataramanan return -EIO; 2961fcea6f3dSAnirudh Venkataramanan } 2962fcea6f3dSAnirudh Venkataramanan 2963fcea6f3dSAnirudh Venkataramanan lut = devm_kzalloc(&pf->pdev->dev, vsi->rss_table_size, GFP_KERNEL); 2964fcea6f3dSAnirudh Venkataramanan if (!lut) 2965fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 2966fcea6f3dSAnirudh Venkataramanan 2967fcea6f3dSAnirudh Venkataramanan if (ice_get_rss(vsi, key, lut, vsi->rss_table_size)) { 2968fcea6f3dSAnirudh Venkataramanan ret = -EIO; 2969fcea6f3dSAnirudh Venkataramanan goto out; 2970fcea6f3dSAnirudh Venkataramanan } 2971fcea6f3dSAnirudh Venkataramanan 2972fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 2973fcea6f3dSAnirudh Venkataramanan indir[i] = (u32)(lut[i]); 2974fcea6f3dSAnirudh Venkataramanan 2975fcea6f3dSAnirudh Venkataramanan out: 2976fcea6f3dSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, lut); 2977fcea6f3dSAnirudh Venkataramanan return ret; 2978fcea6f3dSAnirudh Venkataramanan } 2979fcea6f3dSAnirudh Venkataramanan 2980fcea6f3dSAnirudh Venkataramanan /** 2981d337f2afSAnirudh Venkataramanan * ice_set_rxfh - set the Rx flow hash indirection table 2982fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2983fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 2984fcea6f3dSAnirudh Venkataramanan * @key: hash key 2985fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 2986fcea6f3dSAnirudh Venkataramanan * 2987f9867df6SAnirudh Venkataramanan * Returns -EINVAL if the table specifies an invalid queue ID, otherwise 2988fcea6f3dSAnirudh Venkataramanan * returns 0 after programming the table. 2989fcea6f3dSAnirudh Venkataramanan */ 2990c8b7abddSBruce Allan static int 2991c8b7abddSBruce Allan ice_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, 2992c8b7abddSBruce Allan const u8 hfunc) 2993fcea6f3dSAnirudh Venkataramanan { 2994fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2995fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2996fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2997fcea6f3dSAnirudh Venkataramanan u8 *seed = NULL; 2998fcea6f3dSAnirudh Venkataramanan 2999fcea6f3dSAnirudh Venkataramanan if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 3000fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 3001fcea6f3dSAnirudh Venkataramanan 3002fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 3003fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 3004fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 3005fcea6f3dSAnirudh Venkataramanan return -EIO; 3006fcea6f3dSAnirudh Venkataramanan } 3007fcea6f3dSAnirudh Venkataramanan 3008fcea6f3dSAnirudh Venkataramanan if (key) { 3009fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) { 3010fcea6f3dSAnirudh Venkataramanan vsi->rss_hkey_user = 3011fcea6f3dSAnirudh Venkataramanan devm_kzalloc(&pf->pdev->dev, 3012fcea6f3dSAnirudh Venkataramanan ICE_VSIQF_HKEY_ARRAY_SIZE, 3013fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 3014fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) 3015fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 3016fcea6f3dSAnirudh Venkataramanan } 3017fcea6f3dSAnirudh Venkataramanan memcpy(vsi->rss_hkey_user, key, ICE_VSIQF_HKEY_ARRAY_SIZE); 3018fcea6f3dSAnirudh Venkataramanan seed = vsi->rss_hkey_user; 3019fcea6f3dSAnirudh Venkataramanan } 3020fcea6f3dSAnirudh Venkataramanan 3021fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) { 3022fcea6f3dSAnirudh Venkataramanan vsi->rss_lut_user = devm_kzalloc(&pf->pdev->dev, 3023fcea6f3dSAnirudh Venkataramanan vsi->rss_table_size, 3024fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 3025fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) 3026fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 3027fcea6f3dSAnirudh Venkataramanan } 3028fcea6f3dSAnirudh Venkataramanan 3029fcea6f3dSAnirudh Venkataramanan /* Each 32 bits pointed by 'indir' is stored with a lut entry */ 3030fcea6f3dSAnirudh Venkataramanan if (indir) { 3031fcea6f3dSAnirudh Venkataramanan int i; 3032fcea6f3dSAnirudh Venkataramanan 3033fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 3034fcea6f3dSAnirudh Venkataramanan vsi->rss_lut_user[i] = (u8)(indir[i]); 3035fcea6f3dSAnirudh Venkataramanan } else { 3036fcea6f3dSAnirudh Venkataramanan ice_fill_rss_lut(vsi->rss_lut_user, vsi->rss_table_size, 3037fcea6f3dSAnirudh Venkataramanan vsi->rss_size); 3038fcea6f3dSAnirudh Venkataramanan } 3039fcea6f3dSAnirudh Venkataramanan 3040fcea6f3dSAnirudh Venkataramanan if (ice_set_rss(vsi, seed, vsi->rss_lut_user, vsi->rss_table_size)) 3041fcea6f3dSAnirudh Venkataramanan return -EIO; 3042fcea6f3dSAnirudh Venkataramanan 3043fcea6f3dSAnirudh Venkataramanan return 0; 3044fcea6f3dSAnirudh Venkataramanan } 3045fcea6f3dSAnirudh Venkataramanan 304667fe64d7SBrett Creeley enum ice_container_type { 304767fe64d7SBrett Creeley ICE_RX_CONTAINER, 304867fe64d7SBrett Creeley ICE_TX_CONTAINER, 304967fe64d7SBrett Creeley }; 305067fe64d7SBrett Creeley 305167fe64d7SBrett Creeley /** 305267fe64d7SBrett Creeley * ice_get_rc_coalesce - get ITR values for specific ring container 305367fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 3054f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 305567fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 305667fe64d7SBrett Creeley * 305767fe64d7SBrett Creeley * Query the device for ice_ring_container specific ITR values. This is 305867fe64d7SBrett Creeley * done per ice_ring_container because each q_vector can have 1 or more rings 305967fe64d7SBrett Creeley * and all of said ring(s) will have the same ITR values. 306067fe64d7SBrett Creeley * 306167fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 306267fe64d7SBrett Creeley */ 306367fe64d7SBrett Creeley static int 306467fe64d7SBrett Creeley ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, 306567fe64d7SBrett Creeley struct ice_ring_container *rc) 306667fe64d7SBrett Creeley { 3067b9c8bb06SBrett Creeley struct ice_pf *pf; 3068b9c8bb06SBrett Creeley 3069b9c8bb06SBrett Creeley if (!rc->ring) 3070b9c8bb06SBrett Creeley return -EINVAL; 3071b9c8bb06SBrett Creeley 3072b9c8bb06SBrett Creeley pf = rc->ring->vsi->back; 307367fe64d7SBrett Creeley 307467fe64d7SBrett Creeley switch (c_type) { 307567fe64d7SBrett Creeley case ICE_RX_CONTAINER: 307667fe64d7SBrett Creeley ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 307767fe64d7SBrett Creeley ec->rx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 3078b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high = rc->ring->q_vector->intrl; 307967fe64d7SBrett Creeley break; 308067fe64d7SBrett Creeley case ICE_TX_CONTAINER: 308167fe64d7SBrett Creeley ec->use_adaptive_tx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 308267fe64d7SBrett Creeley ec->tx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 308367fe64d7SBrett Creeley break; 308467fe64d7SBrett Creeley default: 308567fe64d7SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid c_type %d\n", c_type); 308667fe64d7SBrett Creeley return -EINVAL; 308767fe64d7SBrett Creeley } 308867fe64d7SBrett Creeley 308967fe64d7SBrett Creeley return 0; 309067fe64d7SBrett Creeley } 309167fe64d7SBrett Creeley 309267fe64d7SBrett Creeley /** 3093e40c899aSBrett Creeley * ice_get_q_coalesce - get a queue's ITR/INTRL (coalesce) settings 3094e40c899aSBrett Creeley * @vsi: VSI associated to the queue for getting ITR/INTRL (coalesce) settings 3095e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 3096e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 3097e40c899aSBrett Creeley * 3098e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 3099e40c899aSBrett Creeley * 1. Getting Tx or Rx ITR/INTRL (coalesce) settings failed. 3100e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 3101e40c899aSBrett Creeley */ 3102e40c899aSBrett Creeley static int 3103e40c899aSBrett Creeley ice_get_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 3104e40c899aSBrett Creeley { 3105e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 3106e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 3107e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 3108e40c899aSBrett Creeley return -EINVAL; 3109e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 3110e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 3111e40c899aSBrett Creeley return -EINVAL; 3112e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 3113e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 3114e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 3115e40c899aSBrett Creeley return -EINVAL; 3116e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 3117e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 3118e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 3119e40c899aSBrett Creeley return -EINVAL; 3120e40c899aSBrett Creeley } else { 3121e40c899aSBrett Creeley return -EINVAL; 3122e40c899aSBrett Creeley } 3123e40c899aSBrett Creeley 3124e40c899aSBrett Creeley return 0; 3125e40c899aSBrett Creeley } 3126e40c899aSBrett Creeley 3127e40c899aSBrett Creeley /** 312867fe64d7SBrett Creeley * __ice_get_coalesce - get ITR/INTRL values for the device 312967fe64d7SBrett Creeley * @netdev: pointer to the netdev associated with this query 313067fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 313167fe64d7SBrett Creeley * @q_num: queue number to get the coalesce settings for 3132e40c899aSBrett Creeley * 3133e40c899aSBrett Creeley * If the caller passes in a negative q_num then we return coalesce settings 3134e40c899aSBrett Creeley * based on queue number 0, else use the actual q_num passed in. 313567fe64d7SBrett Creeley */ 313667fe64d7SBrett Creeley static int 313767fe64d7SBrett Creeley __ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 313867fe64d7SBrett Creeley int q_num) 313967fe64d7SBrett Creeley { 314067fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 314167fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 314267fe64d7SBrett Creeley 3143e40c899aSBrett Creeley if (q_num < 0) 3144e40c899aSBrett Creeley q_num = 0; 314567fe64d7SBrett Creeley 3146e40c899aSBrett Creeley if (ice_get_q_coalesce(vsi, ec, q_num)) 314767fe64d7SBrett Creeley return -EINVAL; 314867fe64d7SBrett Creeley 314967fe64d7SBrett Creeley if (q_num < vsi->num_txq) 315067fe64d7SBrett Creeley ec->tx_max_coalesced_frames_irq = vsi->work_lmt; 315167fe64d7SBrett Creeley 315267fe64d7SBrett Creeley if (q_num < vsi->num_rxq) 315367fe64d7SBrett Creeley ec->rx_max_coalesced_frames_irq = vsi->work_lmt; 315467fe64d7SBrett Creeley 315567fe64d7SBrett Creeley return 0; 315667fe64d7SBrett Creeley } 315767fe64d7SBrett Creeley 315867fe64d7SBrett Creeley static int 315967fe64d7SBrett Creeley ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 316067fe64d7SBrett Creeley { 316167fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, -1); 316267fe64d7SBrett Creeley } 316367fe64d7SBrett Creeley 3164c8b7abddSBruce Allan static int 3165c8b7abddSBruce Allan ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num, 316667fe64d7SBrett Creeley struct ethtool_coalesce *ec) 316767fe64d7SBrett Creeley { 316867fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, q_num); 316967fe64d7SBrett Creeley } 317067fe64d7SBrett Creeley 317167fe64d7SBrett Creeley /** 317267fe64d7SBrett Creeley * ice_set_rc_coalesce - set ITR values for specific ring container 3173f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 317467fe64d7SBrett Creeley * @ec: ethtool structure from user to update ITR settings 317567fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 317667fe64d7SBrett Creeley * @vsi: VSI associated to the ring container 317767fe64d7SBrett Creeley * 317867fe64d7SBrett Creeley * Set specific ITR values. This is done per ice_ring_container because each 317967fe64d7SBrett Creeley * q_vector can have 1 or more rings and all of said ring(s) will have the same 318067fe64d7SBrett Creeley * ITR values. 318167fe64d7SBrett Creeley * 318267fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 318367fe64d7SBrett Creeley */ 318467fe64d7SBrett Creeley static int 318567fe64d7SBrett Creeley ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec, 318667fe64d7SBrett Creeley struct ice_ring_container *rc, struct ice_vsi *vsi) 318767fe64d7SBrett Creeley { 318867fe64d7SBrett Creeley struct ice_pf *pf = vsi->back; 318967fe64d7SBrett Creeley u16 itr_setting; 319067fe64d7SBrett Creeley 319167fe64d7SBrett Creeley if (!rc->ring) 319267fe64d7SBrett Creeley return -EINVAL; 319367fe64d7SBrett Creeley 319467fe64d7SBrett Creeley itr_setting = rc->itr_setting & ~ICE_ITR_DYNAMIC; 319567fe64d7SBrett Creeley 319667fe64d7SBrett Creeley switch (c_type) { 319767fe64d7SBrett Creeley case ICE_RX_CONTAINER: 3198b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high > ICE_MAX_INTRL || 3199b9c8bb06SBrett Creeley (ec->rx_coalesce_usecs_high && 3200b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high < pf->hw.intrl_gran)) { 3201b9c8bb06SBrett Creeley netdev_info(vsi->netdev, 3202b9c8bb06SBrett Creeley "Invalid value, rx-usecs-high valid values are 0 (disabled), %d-%d\n", 3203b9c8bb06SBrett Creeley pf->hw.intrl_gran, ICE_MAX_INTRL); 3204b9c8bb06SBrett Creeley return -EINVAL; 3205b9c8bb06SBrett Creeley } 3206b9c8bb06SBrett Creeley 3207b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high != rc->ring->q_vector->intrl) { 3208b9c8bb06SBrett Creeley rc->ring->q_vector->intrl = ec->rx_coalesce_usecs_high; 3209cbe66bfeSBrett Creeley wr32(&pf->hw, GLINT_RATE(rc->ring->q_vector->reg_idx), 3210b9c8bb06SBrett Creeley ice_intrl_usec_to_reg(ec->rx_coalesce_usecs_high, 3211b9c8bb06SBrett Creeley pf->hw.intrl_gran)); 3212b9c8bb06SBrett Creeley } 3213b9c8bb06SBrett Creeley 321467fe64d7SBrett Creeley if (ec->rx_coalesce_usecs != itr_setting && 321567fe64d7SBrett Creeley ec->use_adaptive_rx_coalesce) { 321667fe64d7SBrett Creeley netdev_info(vsi->netdev, 321767fe64d7SBrett Creeley "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n"); 321867fe64d7SBrett Creeley return -EINVAL; 321967fe64d7SBrett Creeley } 322067fe64d7SBrett Creeley 322167fe64d7SBrett Creeley if (ec->rx_coalesce_usecs > ICE_ITR_MAX) { 322267fe64d7SBrett Creeley netdev_info(vsi->netdev, 322367fe64d7SBrett Creeley "Invalid value, rx-usecs range is 0-%d\n", 322467fe64d7SBrett Creeley ICE_ITR_MAX); 322567fe64d7SBrett Creeley return -EINVAL; 322667fe64d7SBrett Creeley } 322767fe64d7SBrett Creeley 322867fe64d7SBrett Creeley if (ec->use_adaptive_rx_coalesce) { 322967fe64d7SBrett Creeley rc->itr_setting |= ICE_ITR_DYNAMIC; 323067fe64d7SBrett Creeley } else { 323167fe64d7SBrett Creeley rc->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs); 323267fe64d7SBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 323367fe64d7SBrett Creeley } 323467fe64d7SBrett Creeley break; 323567fe64d7SBrett Creeley case ICE_TX_CONTAINER: 3236b9c8bb06SBrett Creeley if (ec->tx_coalesce_usecs_high) { 3237b9c8bb06SBrett Creeley netdev_info(vsi->netdev, 3238b9c8bb06SBrett Creeley "setting tx-usecs-high is not supported\n"); 3239b9c8bb06SBrett Creeley return -EINVAL; 3240b9c8bb06SBrett Creeley } 3241b9c8bb06SBrett Creeley 324267fe64d7SBrett Creeley if (ec->tx_coalesce_usecs != itr_setting && 324367fe64d7SBrett Creeley ec->use_adaptive_tx_coalesce) { 324467fe64d7SBrett Creeley netdev_info(vsi->netdev, 324567fe64d7SBrett Creeley "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n"); 324667fe64d7SBrett Creeley return -EINVAL; 324767fe64d7SBrett Creeley } 324867fe64d7SBrett Creeley 324967fe64d7SBrett Creeley if (ec->tx_coalesce_usecs > ICE_ITR_MAX) { 325067fe64d7SBrett Creeley netdev_info(vsi->netdev, 325167fe64d7SBrett Creeley "Invalid value, tx-usecs range is 0-%d\n", 325267fe64d7SBrett Creeley ICE_ITR_MAX); 325367fe64d7SBrett Creeley return -EINVAL; 325467fe64d7SBrett Creeley } 325567fe64d7SBrett Creeley 325667fe64d7SBrett Creeley if (ec->use_adaptive_tx_coalesce) { 325767fe64d7SBrett Creeley rc->itr_setting |= ICE_ITR_DYNAMIC; 325867fe64d7SBrett Creeley } else { 325967fe64d7SBrett Creeley rc->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs); 326067fe64d7SBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 326167fe64d7SBrett Creeley } 326267fe64d7SBrett Creeley break; 326367fe64d7SBrett Creeley default: 326467fe64d7SBrett Creeley dev_dbg(&pf->pdev->dev, "Invalid container type %d\n", c_type); 326567fe64d7SBrett Creeley return -EINVAL; 326667fe64d7SBrett Creeley } 326767fe64d7SBrett Creeley 326867fe64d7SBrett Creeley return 0; 326967fe64d7SBrett Creeley } 327067fe64d7SBrett Creeley 3271e40c899aSBrett Creeley /** 3272e40c899aSBrett Creeley * ice_set_q_coalesce - set a queue's ITR/INTRL (coalesce) settings 3273e40c899aSBrett Creeley * @vsi: VSI associated to the queue that need updating 3274e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 3275e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 3276e40c899aSBrett Creeley * 3277e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 3278e40c899aSBrett Creeley * 1. Setting Tx or Rx ITR/INTRL (coalesce) settings failed. 3279e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 3280e40c899aSBrett Creeley */ 3281e40c899aSBrett Creeley static int 3282e40c899aSBrett Creeley ice_set_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 3283e40c899aSBrett Creeley { 3284e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 3285e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 3286e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 3287e40c899aSBrett Creeley vsi)) 3288e40c899aSBrett Creeley return -EINVAL; 3289e40c899aSBrett Creeley 3290e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 3291e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 3292e40c899aSBrett Creeley vsi)) 3293e40c899aSBrett Creeley return -EINVAL; 3294e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 3295e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 3296e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 3297e40c899aSBrett Creeley vsi)) 3298e40c899aSBrett Creeley return -EINVAL; 3299e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 3300e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 3301e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 3302e40c899aSBrett Creeley vsi)) 3303e40c899aSBrett Creeley return -EINVAL; 3304e40c899aSBrett Creeley } else { 3305e40c899aSBrett Creeley return -EINVAL; 3306e40c899aSBrett Creeley } 3307e40c899aSBrett Creeley 3308e40c899aSBrett Creeley return 0; 3309e40c899aSBrett Creeley } 3310e40c899aSBrett Creeley 3311e40c899aSBrett Creeley /** 3312e40c899aSBrett Creeley * __ice_set_coalesce - set ITR/INTRL values for the device 3313e40c899aSBrett Creeley * @netdev: pointer to the netdev associated with this query 3314e40c899aSBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 3315e40c899aSBrett Creeley * @q_num: queue number to get the coalesce settings for 3316e40c899aSBrett Creeley * 3317e40c899aSBrett Creeley * If the caller passes in a negative q_num then we set the coalesce settings 3318e40c899aSBrett Creeley * for all Tx/Rx queues, else use the actual q_num passed in. 3319e40c899aSBrett Creeley */ 332067fe64d7SBrett Creeley static int 332167fe64d7SBrett Creeley __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 332267fe64d7SBrett Creeley int q_num) 332367fe64d7SBrett Creeley { 332467fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 332567fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 332667fe64d7SBrett Creeley 332767fe64d7SBrett Creeley if (q_num < 0) { 332867fe64d7SBrett Creeley int i; 332967fe64d7SBrett Creeley 333067fe64d7SBrett Creeley ice_for_each_q_vector(vsi, i) { 3331e40c899aSBrett Creeley if (ice_set_q_coalesce(vsi, ec, i)) 333267fe64d7SBrett Creeley return -EINVAL; 333367fe64d7SBrett Creeley } 333467fe64d7SBrett Creeley goto set_work_lmt; 333567fe64d7SBrett Creeley } 333667fe64d7SBrett Creeley 3337e40c899aSBrett Creeley if (ice_set_q_coalesce(vsi, ec, q_num)) 333867fe64d7SBrett Creeley return -EINVAL; 333967fe64d7SBrett Creeley 334067fe64d7SBrett Creeley set_work_lmt: 3341e40c899aSBrett Creeley 334267fe64d7SBrett Creeley if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) 334367fe64d7SBrett Creeley vsi->work_lmt = max(ec->tx_max_coalesced_frames_irq, 334467fe64d7SBrett Creeley ec->rx_max_coalesced_frames_irq); 334567fe64d7SBrett Creeley 334667fe64d7SBrett Creeley return 0; 334767fe64d7SBrett Creeley } 334867fe64d7SBrett Creeley 334967fe64d7SBrett Creeley static int 335067fe64d7SBrett Creeley ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 335167fe64d7SBrett Creeley { 335267fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, -1); 335367fe64d7SBrett Creeley } 335467fe64d7SBrett Creeley 3355c8b7abddSBruce Allan static int 3356c8b7abddSBruce Allan ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num, 335767fe64d7SBrett Creeley struct ethtool_coalesce *ec) 335867fe64d7SBrett Creeley { 335967fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, q_num); 336067fe64d7SBrett Creeley } 336167fe64d7SBrett Creeley 3362fcea6f3dSAnirudh Venkataramanan static const struct ethtool_ops ice_ethtool_ops = { 3363fcea6f3dSAnirudh Venkataramanan .get_link_ksettings = ice_get_link_ksettings, 336448cb27f2SChinh Cao .set_link_ksettings = ice_set_link_ksettings, 3365fcea6f3dSAnirudh Venkataramanan .get_drvinfo = ice_get_drvinfo, 3366fcea6f3dSAnirudh Venkataramanan .get_regs_len = ice_get_regs_len, 3367fcea6f3dSAnirudh Venkataramanan .get_regs = ice_get_regs, 3368fcea6f3dSAnirudh Venkataramanan .get_msglevel = ice_get_msglevel, 3369fcea6f3dSAnirudh Venkataramanan .set_msglevel = ice_set_msglevel, 33700e674aebSAnirudh Venkataramanan .self_test = ice_self_test, 3371fcea6f3dSAnirudh Venkataramanan .get_link = ethtool_op_get_link, 33724c98ab55SBruce Allan .get_eeprom_len = ice_get_eeprom_len, 33734c98ab55SBruce Allan .get_eeprom = ice_get_eeprom, 337467fe64d7SBrett Creeley .get_coalesce = ice_get_coalesce, 337567fe64d7SBrett Creeley .set_coalesce = ice_set_coalesce, 3376fcea6f3dSAnirudh Venkataramanan .get_strings = ice_get_strings, 33778e151d50SAnirudh Venkataramanan .set_phys_id = ice_set_phys_id, 3378fcea6f3dSAnirudh Venkataramanan .get_ethtool_stats = ice_get_ethtool_stats, 3379ab4ab73fSBruce Allan .get_priv_flags = ice_get_priv_flags, 3380ab4ab73fSBruce Allan .set_priv_flags = ice_set_priv_flags, 3381fcea6f3dSAnirudh Venkataramanan .get_sset_count = ice_get_sset_count, 3382fcea6f3dSAnirudh Venkataramanan .get_rxnfc = ice_get_rxnfc, 3383fcea6f3dSAnirudh Venkataramanan .get_ringparam = ice_get_ringparam, 3384fcea6f3dSAnirudh Venkataramanan .set_ringparam = ice_set_ringparam, 3385fcea6f3dSAnirudh Venkataramanan .nway_reset = ice_nway_reset, 3386fcea6f3dSAnirudh Venkataramanan .get_pauseparam = ice_get_pauseparam, 3387fcea6f3dSAnirudh Venkataramanan .set_pauseparam = ice_set_pauseparam, 3388fcea6f3dSAnirudh Venkataramanan .get_rxfh_key_size = ice_get_rxfh_key_size, 3389fcea6f3dSAnirudh Venkataramanan .get_rxfh_indir_size = ice_get_rxfh_indir_size, 3390fcea6f3dSAnirudh Venkataramanan .get_rxfh = ice_get_rxfh, 3391fcea6f3dSAnirudh Venkataramanan .set_rxfh = ice_set_rxfh, 3392a8939784STony Nguyen .get_ts_info = ethtool_op_get_ts_info, 339367fe64d7SBrett Creeley .get_per_queue_coalesce = ice_get_per_q_coalesce, 339467fe64d7SBrett Creeley .set_per_queue_coalesce = ice_set_per_q_coalesce, 3395f776b3acSPaul Greenwalt .get_fecparam = ice_get_fecparam, 3396f776b3acSPaul Greenwalt .set_fecparam = ice_set_fecparam, 3397fcea6f3dSAnirudh Venkataramanan }; 3398fcea6f3dSAnirudh Venkataramanan 3399fcea6f3dSAnirudh Venkataramanan /** 3400fcea6f3dSAnirudh Venkataramanan * ice_set_ethtool_ops - setup netdev ethtool ops 3401fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3402fcea6f3dSAnirudh Venkataramanan * 3403fcea6f3dSAnirudh Venkataramanan * setup netdev ethtool ops with ice specific ops 3404fcea6f3dSAnirudh Venkataramanan */ 3405fcea6f3dSAnirudh Venkataramanan void ice_set_ethtool_ops(struct net_device *netdev) 3406fcea6f3dSAnirudh Venkataramanan { 3407fcea6f3dSAnirudh Venkataramanan netdev->ethtool_ops = &ice_ethtool_ops; 3408fcea6f3dSAnirudh Venkataramanan } 3409