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" 76876fb64SMd Fahad Iqbal Polash #include "ice_flow.h" 81b8f15b6SMichal Swiatkowski #include "ice_fltr.h" 93a257a14SAnirudh Venkataramanan #include "ice_lib.h" 103a257a14SAnirudh Venkataramanan #include "ice_dcb_lib.h" 11fcea6f3dSAnirudh Venkataramanan 12fcea6f3dSAnirudh Venkataramanan struct ice_stats { 13fcea6f3dSAnirudh Venkataramanan char stat_string[ETH_GSTRING_LEN]; 14fcea6f3dSAnirudh Venkataramanan int sizeof_stat; 15fcea6f3dSAnirudh Venkataramanan int stat_offset; 16fcea6f3dSAnirudh Venkataramanan }; 17fcea6f3dSAnirudh Venkataramanan 18fcea6f3dSAnirudh Venkataramanan #define ICE_STAT(_type, _name, _stat) { \ 19fcea6f3dSAnirudh Venkataramanan .stat_string = _name, \ 20c593642cSPankaj Bharadiya .sizeof_stat = sizeof_field(_type, _stat), \ 21fcea6f3dSAnirudh Venkataramanan .stat_offset = offsetof(_type, _stat) \ 22fcea6f3dSAnirudh Venkataramanan } 23fcea6f3dSAnirudh Venkataramanan 24fcea6f3dSAnirudh Venkataramanan #define ICE_VSI_STAT(_name, _stat) \ 25fcea6f3dSAnirudh Venkataramanan ICE_STAT(struct ice_vsi, _name, _stat) 26fcea6f3dSAnirudh Venkataramanan #define ICE_PF_STAT(_name, _stat) \ 27fcea6f3dSAnirudh Venkataramanan ICE_STAT(struct ice_pf, _name, _stat) 28fcea6f3dSAnirudh Venkataramanan 29fcea6f3dSAnirudh Venkataramanan static int ice_q_stats_len(struct net_device *netdev) 30fcea6f3dSAnirudh Venkataramanan { 31fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 32fcea6f3dSAnirudh Venkataramanan 33f8ba7db8SJacob Keller return ((np->vsi->alloc_txq + np->vsi->alloc_rxq) * 34fcea6f3dSAnirudh Venkataramanan (sizeof(struct ice_q_stats) / sizeof(u64))); 35fcea6f3dSAnirudh Venkataramanan } 36fcea6f3dSAnirudh Venkataramanan 37fcea6f3dSAnirudh Venkataramanan #define ICE_PF_STATS_LEN ARRAY_SIZE(ice_gstrings_pf_stats) 38fcea6f3dSAnirudh Venkataramanan #define ICE_VSI_STATS_LEN ARRAY_SIZE(ice_gstrings_vsi_stats) 39fcea6f3dSAnirudh Venkataramanan 404b0fdcebSAnirudh Venkataramanan #define ICE_PFC_STATS_LEN ( \ 41c593642cSPankaj Bharadiya (sizeof_field(struct ice_pf, stats.priority_xoff_rx) + \ 42c593642cSPankaj Bharadiya sizeof_field(struct ice_pf, stats.priority_xon_rx) + \ 43c593642cSPankaj Bharadiya sizeof_field(struct ice_pf, stats.priority_xoff_tx) + \ 44c593642cSPankaj Bharadiya sizeof_field(struct ice_pf, stats.priority_xon_tx)) \ 454b0fdcebSAnirudh Venkataramanan / sizeof(u64)) 464b0fdcebSAnirudh Venkataramanan #define ICE_ALL_STATS_LEN(n) (ICE_PF_STATS_LEN + ICE_PFC_STATS_LEN + \ 474b0fdcebSAnirudh Venkataramanan ICE_VSI_STATS_LEN + ice_q_stats_len(n)) 48fcea6f3dSAnirudh Venkataramanan 49fcea6f3dSAnirudh Venkataramanan static const struct ice_stats ice_gstrings_vsi_stats[] = { 50fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_unicast", eth_stats.rx_unicast), 5155e062baSRichard Rodriguez ICE_VSI_STAT("tx_unicast", eth_stats.tx_unicast), 52fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_multicast", eth_stats.rx_multicast), 5355e062baSRichard Rodriguez ICE_VSI_STAT("tx_multicast", eth_stats.tx_multicast), 54fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_broadcast", eth_stats.rx_broadcast), 5555e062baSRichard Rodriguez ICE_VSI_STAT("tx_broadcast", eth_stats.tx_broadcast), 56fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_bytes", eth_stats.rx_bytes), 5755e062baSRichard Rodriguez ICE_VSI_STAT("tx_bytes", eth_stats.tx_bytes), 5855e062baSRichard Rodriguez ICE_VSI_STAT("rx_dropped", eth_stats.rx_discards), 59fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol), 60fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_alloc_fail", rx_buf_failed), 61fcea6f3dSAnirudh Venkataramanan ICE_VSI_STAT("rx_pg_alloc_fail", rx_page_failed), 6255e062baSRichard Rodriguez ICE_VSI_STAT("tx_errors", eth_stats.tx_errors), 6355e062baSRichard Rodriguez ICE_VSI_STAT("tx_linearize", tx_linearize), 64fcea6f3dSAnirudh Venkataramanan }; 65fcea6f3dSAnirudh Venkataramanan 660e674aebSAnirudh Venkataramanan enum ice_ethtool_test_id { 670e674aebSAnirudh Venkataramanan ICE_ETH_TEST_REG = 0, 680e674aebSAnirudh Venkataramanan ICE_ETH_TEST_EEPROM, 690e674aebSAnirudh Venkataramanan ICE_ETH_TEST_INTR, 700e674aebSAnirudh Venkataramanan ICE_ETH_TEST_LOOP, 710e674aebSAnirudh Venkataramanan ICE_ETH_TEST_LINK, 720e674aebSAnirudh Venkataramanan }; 730e674aebSAnirudh Venkataramanan 740e674aebSAnirudh Venkataramanan static const char ice_gstrings_test[][ETH_GSTRING_LEN] = { 750e674aebSAnirudh Venkataramanan "Register test (offline)", 760e674aebSAnirudh Venkataramanan "EEPROM test (offline)", 770e674aebSAnirudh Venkataramanan "Interrupt test (offline)", 780e674aebSAnirudh Venkataramanan "Loopback test (offline)", 790e674aebSAnirudh Venkataramanan "Link test (on/offline)", 800e674aebSAnirudh Venkataramanan }; 810e674aebSAnirudh Venkataramanan 820e674aebSAnirudh Venkataramanan #define ICE_TEST_LEN (sizeof(ice_gstrings_test) / ETH_GSTRING_LEN) 830e674aebSAnirudh Venkataramanan 84fcea6f3dSAnirudh Venkataramanan /* These PF_STATs might look like duplicates of some NETDEV_STATs, 85fcea6f3dSAnirudh Venkataramanan * but they aren't. This device is capable of supporting multiple 86fcea6f3dSAnirudh Venkataramanan * VSIs/netdevs on a single PF. The NETDEV_STATs are for individual 87fcea6f3dSAnirudh Venkataramanan * netdevs whereas the PF_STATs are for the physical function that's 88fcea6f3dSAnirudh Venkataramanan * hosting these netdevs. 89fcea6f3dSAnirudh Venkataramanan * 90fcea6f3dSAnirudh Venkataramanan * The PF_STATs are appended to the netdev stats only when ethtool -S 91fcea6f3dSAnirudh Venkataramanan * is queried on the base PF netdev. 92fcea6f3dSAnirudh Venkataramanan */ 9355aa141eSBruce Allan static const struct ice_stats ice_gstrings_pf_stats[] = { 9455e062baSRichard Rodriguez ICE_PF_STAT("rx_bytes.nic", stats.eth.rx_bytes), 9555e062baSRichard Rodriguez ICE_PF_STAT("tx_bytes.nic", stats.eth.tx_bytes), 9655e062baSRichard Rodriguez ICE_PF_STAT("rx_unicast.nic", stats.eth.rx_unicast), 9755e062baSRichard Rodriguez ICE_PF_STAT("tx_unicast.nic", stats.eth.tx_unicast), 9855e062baSRichard Rodriguez ICE_PF_STAT("rx_multicast.nic", stats.eth.rx_multicast), 9955e062baSRichard Rodriguez ICE_PF_STAT("tx_multicast.nic", stats.eth.tx_multicast), 10055e062baSRichard Rodriguez ICE_PF_STAT("rx_broadcast.nic", stats.eth.rx_broadcast), 10155e062baSRichard Rodriguez ICE_PF_STAT("tx_broadcast.nic", stats.eth.tx_broadcast), 10255e062baSRichard Rodriguez ICE_PF_STAT("tx_errors.nic", stats.eth.tx_errors), 10355e062baSRichard Rodriguez ICE_PF_STAT("rx_size_64.nic", stats.rx_size_64), 10455e062baSRichard Rodriguez ICE_PF_STAT("tx_size_64.nic", stats.tx_size_64), 10555e062baSRichard Rodriguez ICE_PF_STAT("rx_size_127.nic", stats.rx_size_127), 10655e062baSRichard Rodriguez ICE_PF_STAT("tx_size_127.nic", stats.tx_size_127), 10755e062baSRichard Rodriguez ICE_PF_STAT("rx_size_255.nic", stats.rx_size_255), 10855e062baSRichard Rodriguez ICE_PF_STAT("tx_size_255.nic", stats.tx_size_255), 10955e062baSRichard Rodriguez ICE_PF_STAT("rx_size_511.nic", stats.rx_size_511), 11055e062baSRichard Rodriguez ICE_PF_STAT("tx_size_511.nic", stats.tx_size_511), 11155e062baSRichard Rodriguez ICE_PF_STAT("rx_size_1023.nic", stats.rx_size_1023), 11255e062baSRichard Rodriguez ICE_PF_STAT("tx_size_1023.nic", stats.tx_size_1023), 11355e062baSRichard Rodriguez ICE_PF_STAT("rx_size_1522.nic", stats.rx_size_1522), 11455e062baSRichard Rodriguez ICE_PF_STAT("tx_size_1522.nic", stats.tx_size_1522), 11555e062baSRichard Rodriguez ICE_PF_STAT("rx_size_big.nic", stats.rx_size_big), 11655e062baSRichard Rodriguez ICE_PF_STAT("tx_size_big.nic", stats.tx_size_big), 11755e062baSRichard Rodriguez ICE_PF_STAT("link_xon_rx.nic", stats.link_xon_rx), 11855e062baSRichard Rodriguez ICE_PF_STAT("link_xon_tx.nic", stats.link_xon_tx), 11955e062baSRichard Rodriguez ICE_PF_STAT("link_xoff_rx.nic", stats.link_xoff_rx), 12055e062baSRichard Rodriguez ICE_PF_STAT("link_xoff_tx.nic", stats.link_xoff_tx), 12155e062baSRichard Rodriguez ICE_PF_STAT("tx_dropped_link_down.nic", stats.tx_dropped_link_down), 12255e062baSRichard Rodriguez ICE_PF_STAT("rx_undersize.nic", stats.rx_undersize), 12355e062baSRichard Rodriguez ICE_PF_STAT("rx_fragments.nic", stats.rx_fragments), 12455e062baSRichard Rodriguez ICE_PF_STAT("rx_oversize.nic", stats.rx_oversize), 12555e062baSRichard Rodriguez ICE_PF_STAT("rx_jabber.nic", stats.rx_jabber), 12655e062baSRichard Rodriguez ICE_PF_STAT("rx_csum_bad.nic", hw_csum_rx_error), 12755e062baSRichard Rodriguez ICE_PF_STAT("rx_length_errors.nic", stats.rx_len_errors), 12855e062baSRichard Rodriguez ICE_PF_STAT("rx_dropped.nic", stats.eth.rx_discards), 12955e062baSRichard Rodriguez ICE_PF_STAT("rx_crc_errors.nic", stats.crc_errors), 13055e062baSRichard Rodriguez ICE_PF_STAT("illegal_bytes.nic", stats.illegal_bytes), 13155e062baSRichard Rodriguez ICE_PF_STAT("mac_local_faults.nic", stats.mac_local_faults), 13255e062baSRichard Rodriguez ICE_PF_STAT("mac_remote_faults.nic", stats.mac_remote_faults), 1334ab95646SHenry Tieman ICE_PF_STAT("fdir_sb_match.nic", stats.fd_sb_match), 1344ab95646SHenry Tieman ICE_PF_STAT("fdir_sb_status.nic", stats.fd_sb_status), 135fcea6f3dSAnirudh Venkataramanan }; 136fcea6f3dSAnirudh Venkataramanan 13755aa141eSBruce Allan static const u32 ice_regs_dump_list[] = { 138fcea6f3dSAnirudh Venkataramanan PFGEN_STATE, 139fcea6f3dSAnirudh Venkataramanan PRTGEN_STATUS, 140fcea6f3dSAnirudh Venkataramanan QRX_CTRL(0), 141fcea6f3dSAnirudh Venkataramanan QINT_TQCTL(0), 142fcea6f3dSAnirudh Venkataramanan QINT_RQCTL(0), 143fcea6f3dSAnirudh Venkataramanan PFINT_OICR_ENA, 144fcea6f3dSAnirudh Venkataramanan QRX_ITR(0), 1450e674aebSAnirudh Venkataramanan PF0INT_ITR_0(0), 1460e674aebSAnirudh Venkataramanan PF0INT_ITR_1(0), 1470e674aebSAnirudh Venkataramanan PF0INT_ITR_2(0), 148fcea6f3dSAnirudh Venkataramanan }; 149fcea6f3dSAnirudh Venkataramanan 150ab4ab73fSBruce Allan struct ice_priv_flag { 151ab4ab73fSBruce Allan char name[ETH_GSTRING_LEN]; 152ab4ab73fSBruce Allan u32 bitno; /* bit position in pf->flags */ 153ab4ab73fSBruce Allan }; 154ab4ab73fSBruce Allan 155ab4ab73fSBruce Allan #define ICE_PRIV_FLAG(_name, _bitno) { \ 156ab4ab73fSBruce Allan .name = _name, \ 157ab4ab73fSBruce Allan .bitno = _bitno, \ 158ab4ab73fSBruce Allan } 159ab4ab73fSBruce Allan 160ab4ab73fSBruce Allan static const struct ice_priv_flag ice_gstrings_priv_flags[] = { 161ab4ab73fSBruce Allan ICE_PRIV_FLAG("link-down-on-close", ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA), 16284a118abSDave Ertman ICE_PRIV_FLAG("fw-lldp-agent", ICE_FLAG_FW_LLDP_AGENT), 16301b5e89aSBrett Creeley ICE_PRIV_FLAG("vf-true-promisc-support", 16401b5e89aSBrett Creeley ICE_FLAG_VF_TRUE_PROMISC_ENA), 1659d5c5a52SPaul Greenwalt ICE_PRIV_FLAG("mdd-auto-reset-vf", ICE_FLAG_MDD_AUTO_RESET_VF), 1667237f5b0SMaciej Fijalkowski ICE_PRIV_FLAG("legacy-rx", ICE_FLAG_LEGACY_RX), 167ab4ab73fSBruce Allan }; 168ab4ab73fSBruce Allan 169ab4ab73fSBruce Allan #define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags) 170ab4ab73fSBruce Allan 171fcea6f3dSAnirudh Venkataramanan static void 172fcea6f3dSAnirudh Venkataramanan ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) 173fcea6f3dSAnirudh Venkataramanan { 174fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 175fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 176fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 177fbf1e1f6SBruce Allan struct ice_hw *hw = &pf->hw; 178d4e87444SJacob Keller struct ice_orom_info *orom; 179d4e87444SJacob Keller struct ice_nvm_info *nvm; 180d4e87444SJacob Keller 181d4e87444SJacob Keller nvm = &hw->nvm; 182d4e87444SJacob Keller orom = &nvm->orom; 183fcea6f3dSAnirudh Venkataramanan 184c88ba3fbSBruce Allan strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); 185c88ba3fbSBruce Allan strscpy(drvinfo->version, ice_drv_ver, sizeof(drvinfo->version)); 186fbf1e1f6SBruce Allan 187fbf1e1f6SBruce Allan /* Display NVM version (from which the firmware version can be 188fbf1e1f6SBruce Allan * determined) which contains more pertinent information. 189fbf1e1f6SBruce Allan */ 190fbf1e1f6SBruce Allan snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 191d4e87444SJacob Keller "%x.%02x 0x%x %d.%d.%d", nvm->major_ver, nvm->minor_ver, 192d4e87444SJacob Keller nvm->eetrack, orom->major, orom->build, orom->patch); 193fbf1e1f6SBruce Allan 194c88ba3fbSBruce Allan strscpy(drvinfo->bus_info, pci_name(pf->pdev), 195fcea6f3dSAnirudh Venkataramanan sizeof(drvinfo->bus_info)); 196ab4ab73fSBruce Allan drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE; 197fcea6f3dSAnirudh Venkataramanan } 198fcea6f3dSAnirudh Venkataramanan 199fcea6f3dSAnirudh Venkataramanan static int ice_get_regs_len(struct net_device __always_unused *netdev) 200fcea6f3dSAnirudh Venkataramanan { 201cba5957dSAnirudh Venkataramanan return sizeof(ice_regs_dump_list); 202fcea6f3dSAnirudh Venkataramanan } 203fcea6f3dSAnirudh Venkataramanan 204fcea6f3dSAnirudh Venkataramanan static void 205fcea6f3dSAnirudh Venkataramanan ice_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) 206fcea6f3dSAnirudh Venkataramanan { 207fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 208fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 209fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 210fcea6f3dSAnirudh Venkataramanan u32 *regs_buf = (u32 *)p; 211fcea6f3dSAnirudh Venkataramanan int i; 212fcea6f3dSAnirudh Venkataramanan 213fcea6f3dSAnirudh Venkataramanan regs->version = 1; 214fcea6f3dSAnirudh Venkataramanan 215cba5957dSAnirudh Venkataramanan for (i = 0; i < ARRAY_SIZE(ice_regs_dump_list); ++i) 216fcea6f3dSAnirudh Venkataramanan regs_buf[i] = rd32(hw, ice_regs_dump_list[i]); 217fcea6f3dSAnirudh Venkataramanan } 218fcea6f3dSAnirudh Venkataramanan 219fcea6f3dSAnirudh Venkataramanan static u32 ice_get_msglevel(struct net_device *netdev) 220fcea6f3dSAnirudh Venkataramanan { 221fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 222fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 223fcea6f3dSAnirudh Venkataramanan 224fcea6f3dSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 225fcea6f3dSAnirudh Venkataramanan if (pf->hw.debug_mask) 226fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "hw debug_mask: 0x%llX\n", 227fcea6f3dSAnirudh Venkataramanan pf->hw.debug_mask); 228fcea6f3dSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 229fcea6f3dSAnirudh Venkataramanan 230fcea6f3dSAnirudh Venkataramanan return pf->msg_enable; 231fcea6f3dSAnirudh Venkataramanan } 232fcea6f3dSAnirudh Venkataramanan 233fcea6f3dSAnirudh Venkataramanan static void ice_set_msglevel(struct net_device *netdev, u32 data) 234fcea6f3dSAnirudh Venkataramanan { 235fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 236fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 237fcea6f3dSAnirudh Venkataramanan 238fcea6f3dSAnirudh Venkataramanan #ifndef CONFIG_DYNAMIC_DEBUG 239fcea6f3dSAnirudh Venkataramanan if (ICE_DBG_USER & data) 240fcea6f3dSAnirudh Venkataramanan pf->hw.debug_mask = data; 241fcea6f3dSAnirudh Venkataramanan else 242fcea6f3dSAnirudh Venkataramanan pf->msg_enable = data; 243fcea6f3dSAnirudh Venkataramanan #else 244fcea6f3dSAnirudh Venkataramanan pf->msg_enable = data; 245fcea6f3dSAnirudh Venkataramanan #endif /* !CONFIG_DYNAMIC_DEBUG */ 246fcea6f3dSAnirudh Venkataramanan } 247fcea6f3dSAnirudh Venkataramanan 2484c98ab55SBruce Allan static int ice_get_eeprom_len(struct net_device *netdev) 2494c98ab55SBruce Allan { 2504c98ab55SBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 2514c98ab55SBruce Allan struct ice_pf *pf = np->vsi->back; 2524c98ab55SBruce Allan 25384a24798SJesse Brandeburg return (int)pf->hw.nvm.flash_size; 2544c98ab55SBruce Allan } 2554c98ab55SBruce Allan 2564c98ab55SBruce Allan static int 2574c98ab55SBruce Allan ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, 2584c98ab55SBruce Allan u8 *bytes) 2594c98ab55SBruce Allan { 2604c98ab55SBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 2614c98ab55SBruce Allan struct ice_vsi *vsi = np->vsi; 2624c98ab55SBruce Allan struct ice_pf *pf = vsi->back; 2634c98ab55SBruce Allan struct ice_hw *hw = &pf->hw; 2644c98ab55SBruce Allan enum ice_status status; 2654c98ab55SBruce Allan struct device *dev; 2664c98ab55SBruce Allan int ret = 0; 26784a24798SJesse Brandeburg u8 *buf; 2684c98ab55SBruce Allan 2694015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 2704c98ab55SBruce Allan 2714c98ab55SBruce Allan eeprom->magic = hw->vendor_id | (hw->device_id << 16); 27284a24798SJesse Brandeburg netdev_dbg(netdev, "GEEPROM cmd 0x%08x, offset 0x%08x, len 0x%08x\n", 27384a24798SJesse Brandeburg eeprom->cmd, eeprom->offset, eeprom->len); 2744c98ab55SBruce Allan 27584a24798SJesse Brandeburg buf = kzalloc(eeprom->len, GFP_KERNEL); 2764c98ab55SBruce Allan if (!buf) 2774c98ab55SBruce Allan return -ENOMEM; 2784c98ab55SBruce Allan 27984a24798SJesse Brandeburg status = ice_acquire_nvm(hw, ICE_RES_READ); 2804c98ab55SBruce Allan if (status) { 2810fee3577SLihong Yang dev_err(dev, "ice_acquire_nvm failed, err %s aq_err %s\n", 2820fee3577SLihong Yang ice_stat_str(status), 2830fee3577SLihong Yang ice_aq_str(hw->adminq.sq_last_status)); 2844c98ab55SBruce Allan ret = -EIO; 2854c98ab55SBruce Allan goto out; 2864c98ab55SBruce Allan } 2874c98ab55SBruce Allan 28884a24798SJesse Brandeburg status = ice_read_flat_nvm(hw, eeprom->offset, &eeprom->len, buf, 28984a24798SJesse Brandeburg false); 29084a24798SJesse Brandeburg if (status) { 2910fee3577SLihong Yang dev_err(dev, "ice_read_flat_nvm failed, err %s aq_err %s\n", 2920fee3577SLihong Yang ice_stat_str(status), 2930fee3577SLihong Yang ice_aq_str(hw->adminq.sq_last_status)); 29484a24798SJesse Brandeburg ret = -EIO; 29584a24798SJesse Brandeburg goto release; 29684a24798SJesse Brandeburg } 29784a24798SJesse Brandeburg 29884a24798SJesse Brandeburg memcpy(bytes, buf, eeprom->len); 29984a24798SJesse Brandeburg release: 30084a24798SJesse Brandeburg ice_release_nvm(hw); 3014c98ab55SBruce Allan out: 30284a24798SJesse Brandeburg kfree(buf); 3034c98ab55SBruce Allan return ret; 3044c98ab55SBruce Allan } 3054c98ab55SBruce Allan 3060e674aebSAnirudh Venkataramanan /** 3070e674aebSAnirudh Venkataramanan * ice_active_vfs - check if there are any active VFs 3080e674aebSAnirudh Venkataramanan * @pf: board private structure 3090e674aebSAnirudh Venkataramanan * 3100e674aebSAnirudh Venkataramanan * Returns true if an active VF is found, otherwise returns false 3110e674aebSAnirudh Venkataramanan */ 3120e674aebSAnirudh Venkataramanan static bool ice_active_vfs(struct ice_pf *pf) 3130e674aebSAnirudh Venkataramanan { 3140e674aebSAnirudh Venkataramanan int i; 3150e674aebSAnirudh Venkataramanan 316005881bcSBrett Creeley ice_for_each_vf(pf, i) { 317005881bcSBrett Creeley struct ice_vf *vf = &pf->vf[i]; 318005881bcSBrett Creeley 3190e674aebSAnirudh Venkataramanan if (test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) 3200e674aebSAnirudh Venkataramanan return true; 321005881bcSBrett Creeley } 322005881bcSBrett Creeley 3230e674aebSAnirudh Venkataramanan return false; 3240e674aebSAnirudh Venkataramanan } 3250e674aebSAnirudh Venkataramanan 3260e674aebSAnirudh Venkataramanan /** 3270e674aebSAnirudh Venkataramanan * ice_link_test - perform a link test on a given net_device 3280e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 3290e674aebSAnirudh Venkataramanan * 3300e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 3310e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 3320e674aebSAnirudh Venkataramanan */ 3330e674aebSAnirudh Venkataramanan static u64 ice_link_test(struct net_device *netdev) 3340e674aebSAnirudh Venkataramanan { 3350e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3360e674aebSAnirudh Venkataramanan enum ice_status status; 3370e674aebSAnirudh Venkataramanan bool link_up = false; 3380e674aebSAnirudh Venkataramanan 3390e674aebSAnirudh Venkataramanan netdev_info(netdev, "link test\n"); 3400e674aebSAnirudh Venkataramanan status = ice_get_link_status(np->vsi->port_info, &link_up); 3410e674aebSAnirudh Venkataramanan if (status) { 3420fee3577SLihong Yang netdev_err(netdev, "link query error, status = %s\n", 3430fee3577SLihong Yang ice_stat_str(status)); 3440e674aebSAnirudh Venkataramanan return 1; 3450e674aebSAnirudh Venkataramanan } 3460e674aebSAnirudh Venkataramanan 3470e674aebSAnirudh Venkataramanan if (!link_up) 3480e674aebSAnirudh Venkataramanan return 2; 3490e674aebSAnirudh Venkataramanan 3500e674aebSAnirudh Venkataramanan return 0; 3510e674aebSAnirudh Venkataramanan } 3520e674aebSAnirudh Venkataramanan 3530e674aebSAnirudh Venkataramanan /** 3540e674aebSAnirudh Venkataramanan * ice_eeprom_test - perform an EEPROM test on a given net_device 3550e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 3560e674aebSAnirudh Venkataramanan * 3570e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 3580e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 3590e674aebSAnirudh Venkataramanan */ 3600e674aebSAnirudh Venkataramanan static u64 ice_eeprom_test(struct net_device *netdev) 3610e674aebSAnirudh Venkataramanan { 3620e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3630e674aebSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 3640e674aebSAnirudh Venkataramanan 3650e674aebSAnirudh Venkataramanan netdev_info(netdev, "EEPROM test\n"); 3660e674aebSAnirudh Venkataramanan return !!(ice_nvm_validate_checksum(&pf->hw)); 3670e674aebSAnirudh Venkataramanan } 3680e674aebSAnirudh Venkataramanan 3690e674aebSAnirudh Venkataramanan /** 3700e674aebSAnirudh Venkataramanan * ice_reg_pattern_test 3710e674aebSAnirudh Venkataramanan * @hw: pointer to the HW struct 3720e674aebSAnirudh Venkataramanan * @reg: reg to be tested 3730e674aebSAnirudh Venkataramanan * @mask: bits to be touched 3740e674aebSAnirudh Venkataramanan */ 3750e674aebSAnirudh Venkataramanan static int ice_reg_pattern_test(struct ice_hw *hw, u32 reg, u32 mask) 3760e674aebSAnirudh Venkataramanan { 3770e674aebSAnirudh Venkataramanan struct ice_pf *pf = (struct ice_pf *)hw->back; 3784015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 3790e674aebSAnirudh Venkataramanan static const u32 patterns[] = { 3800e674aebSAnirudh Venkataramanan 0x5A5A5A5A, 0xA5A5A5A5, 3810e674aebSAnirudh Venkataramanan 0x00000000, 0xFFFFFFFF 3820e674aebSAnirudh Venkataramanan }; 3830e674aebSAnirudh Venkataramanan u32 val, orig_val; 3840e674aebSAnirudh Venkataramanan int i; 3850e674aebSAnirudh Venkataramanan 3860e674aebSAnirudh Venkataramanan orig_val = rd32(hw, reg); 3870e674aebSAnirudh Venkataramanan for (i = 0; i < ARRAY_SIZE(patterns); ++i) { 3880e674aebSAnirudh Venkataramanan u32 pattern = patterns[i] & mask; 3890e674aebSAnirudh Venkataramanan 3900e674aebSAnirudh Venkataramanan wr32(hw, reg, pattern); 3910e674aebSAnirudh Venkataramanan val = rd32(hw, reg); 3920e674aebSAnirudh Venkataramanan if (val == pattern) 3930e674aebSAnirudh Venkataramanan continue; 39419cce2c6SAnirudh Venkataramanan dev_err(dev, "%s: reg pattern test failed - reg 0x%08x pat 0x%08x val 0x%08x\n" 3950e674aebSAnirudh Venkataramanan , __func__, reg, pattern, val); 3960e674aebSAnirudh Venkataramanan return 1; 3970e674aebSAnirudh Venkataramanan } 3980e674aebSAnirudh Venkataramanan 3990e674aebSAnirudh Venkataramanan wr32(hw, reg, orig_val); 4000e674aebSAnirudh Venkataramanan val = rd32(hw, reg); 4010e674aebSAnirudh Venkataramanan if (val != orig_val) { 40219cce2c6SAnirudh Venkataramanan dev_err(dev, "%s: reg restore test failed - reg 0x%08x orig 0x%08x val 0x%08x\n" 4030e674aebSAnirudh Venkataramanan , __func__, reg, orig_val, val); 4040e674aebSAnirudh Venkataramanan return 1; 4050e674aebSAnirudh Venkataramanan } 4060e674aebSAnirudh Venkataramanan 4070e674aebSAnirudh Venkataramanan return 0; 4080e674aebSAnirudh Venkataramanan } 4090e674aebSAnirudh Venkataramanan 4100e674aebSAnirudh Venkataramanan /** 4110e674aebSAnirudh Venkataramanan * ice_reg_test - perform a register test on a given net_device 4120e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 4130e674aebSAnirudh Venkataramanan * 4140e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 4150e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 4160e674aebSAnirudh Venkataramanan */ 4170e674aebSAnirudh Venkataramanan static u64 ice_reg_test(struct net_device *netdev) 4180e674aebSAnirudh Venkataramanan { 4190e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 4200e674aebSAnirudh Venkataramanan struct ice_hw *hw = np->vsi->port_info->hw; 4210e674aebSAnirudh Venkataramanan u32 int_elements = hw->func_caps.common_cap.num_msix_vectors ? 4220e674aebSAnirudh Venkataramanan hw->func_caps.common_cap.num_msix_vectors - 1 : 1; 4230e674aebSAnirudh Venkataramanan struct ice_diag_reg_test_info { 4240e674aebSAnirudh Venkataramanan u32 address; 4250e674aebSAnirudh Venkataramanan u32 mask; 4260e674aebSAnirudh Venkataramanan u32 elem_num; 4270e674aebSAnirudh Venkataramanan u32 elem_size; 4280e674aebSAnirudh Venkataramanan } ice_reg_list[] = { 4290e674aebSAnirudh Venkataramanan {GLINT_ITR(0, 0), 0x00000fff, int_elements, 4300e674aebSAnirudh Venkataramanan GLINT_ITR(0, 1) - GLINT_ITR(0, 0)}, 4310e674aebSAnirudh Venkataramanan {GLINT_ITR(1, 0), 0x00000fff, int_elements, 4320e674aebSAnirudh Venkataramanan GLINT_ITR(1, 1) - GLINT_ITR(1, 0)}, 4330e674aebSAnirudh Venkataramanan {GLINT_ITR(0, 0), 0x00000fff, int_elements, 4340e674aebSAnirudh Venkataramanan GLINT_ITR(2, 1) - GLINT_ITR(2, 0)}, 4350e674aebSAnirudh Venkataramanan {GLINT_CTL, 0xffff0001, 1, 0} 4360e674aebSAnirudh Venkataramanan }; 4370e674aebSAnirudh Venkataramanan int i; 4380e674aebSAnirudh Venkataramanan 4390e674aebSAnirudh Venkataramanan netdev_dbg(netdev, "Register test\n"); 4400e674aebSAnirudh Venkataramanan for (i = 0; i < ARRAY_SIZE(ice_reg_list); ++i) { 4410e674aebSAnirudh Venkataramanan u32 j; 4420e674aebSAnirudh Venkataramanan 4430e674aebSAnirudh Venkataramanan for (j = 0; j < ice_reg_list[i].elem_num; ++j) { 4440e674aebSAnirudh Venkataramanan u32 mask = ice_reg_list[i].mask; 4450e674aebSAnirudh Venkataramanan u32 reg = ice_reg_list[i].address + 4460e674aebSAnirudh Venkataramanan (j * ice_reg_list[i].elem_size); 4470e674aebSAnirudh Venkataramanan 4480e674aebSAnirudh Venkataramanan /* bail on failure (non-zero return) */ 4490e674aebSAnirudh Venkataramanan if (ice_reg_pattern_test(hw, reg, mask)) 4500e674aebSAnirudh Venkataramanan return 1; 4510e674aebSAnirudh Venkataramanan } 4520e674aebSAnirudh Venkataramanan } 4530e674aebSAnirudh Venkataramanan 4540e674aebSAnirudh Venkataramanan return 0; 4550e674aebSAnirudh Venkataramanan } 4560e674aebSAnirudh Venkataramanan 4570e674aebSAnirudh Venkataramanan /** 4580e674aebSAnirudh Venkataramanan * ice_lbtest_prepare_rings - configure Tx/Rx test rings 4590e674aebSAnirudh Venkataramanan * @vsi: pointer to the VSI structure 4600e674aebSAnirudh Venkataramanan * 4610e674aebSAnirudh Venkataramanan * Function configures rings of a VSI for loopback test without 4620e674aebSAnirudh Venkataramanan * enabling interrupts or informing the kernel about new queues. 4630e674aebSAnirudh Venkataramanan * 4640e674aebSAnirudh Venkataramanan * Returns 0 on success, negative on failure. 4650e674aebSAnirudh Venkataramanan */ 4660e674aebSAnirudh Venkataramanan static int ice_lbtest_prepare_rings(struct ice_vsi *vsi) 4670e674aebSAnirudh Venkataramanan { 4680e674aebSAnirudh Venkataramanan int status; 4690e674aebSAnirudh Venkataramanan 4700e674aebSAnirudh Venkataramanan status = ice_vsi_setup_tx_rings(vsi); 4710e674aebSAnirudh Venkataramanan if (status) 4720e674aebSAnirudh Venkataramanan goto err_setup_tx_ring; 4730e674aebSAnirudh Venkataramanan 4740e674aebSAnirudh Venkataramanan status = ice_vsi_setup_rx_rings(vsi); 4750e674aebSAnirudh Venkataramanan if (status) 4760e674aebSAnirudh Venkataramanan goto err_setup_rx_ring; 4770e674aebSAnirudh Venkataramanan 4780e674aebSAnirudh Venkataramanan status = ice_vsi_cfg(vsi); 4790e674aebSAnirudh Venkataramanan if (status) 4800e674aebSAnirudh Venkataramanan goto err_setup_rx_ring; 4810e674aebSAnirudh Venkataramanan 48213a6233bSBrett Creeley status = ice_vsi_start_all_rx_rings(vsi); 4830e674aebSAnirudh Venkataramanan if (status) 4840e674aebSAnirudh Venkataramanan goto err_start_rx_ring; 4850e674aebSAnirudh Venkataramanan 4860e674aebSAnirudh Venkataramanan return status; 4870e674aebSAnirudh Venkataramanan 4880e674aebSAnirudh Venkataramanan err_start_rx_ring: 4890e674aebSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 4900e674aebSAnirudh Venkataramanan err_setup_rx_ring: 4910e674aebSAnirudh Venkataramanan ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); 4920e674aebSAnirudh Venkataramanan err_setup_tx_ring: 4930e674aebSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 4940e674aebSAnirudh Venkataramanan 4950e674aebSAnirudh Venkataramanan return status; 4960e674aebSAnirudh Venkataramanan } 4970e674aebSAnirudh Venkataramanan 4980e674aebSAnirudh Venkataramanan /** 4990e674aebSAnirudh Venkataramanan * ice_lbtest_disable_rings - disable Tx/Rx test rings after loopback test 5000e674aebSAnirudh Venkataramanan * @vsi: pointer to the VSI structure 5010e674aebSAnirudh Venkataramanan * 5020e674aebSAnirudh Venkataramanan * Function stops and frees VSI rings after a loopback test. 5030e674aebSAnirudh Venkataramanan * Returns 0 on success, negative on failure. 5040e674aebSAnirudh Venkataramanan */ 5050e674aebSAnirudh Venkataramanan static int ice_lbtest_disable_rings(struct ice_vsi *vsi) 5060e674aebSAnirudh Venkataramanan { 5070e674aebSAnirudh Venkataramanan int status; 5080e674aebSAnirudh Venkataramanan 5090e674aebSAnirudh Venkataramanan status = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0); 5100e674aebSAnirudh Venkataramanan if (status) 5110e674aebSAnirudh Venkataramanan netdev_err(vsi->netdev, "Failed to stop Tx rings, VSI %d error %d\n", 5120e674aebSAnirudh Venkataramanan vsi->vsi_num, status); 5130e674aebSAnirudh Venkataramanan 51413a6233bSBrett Creeley status = ice_vsi_stop_all_rx_rings(vsi); 5150e674aebSAnirudh Venkataramanan if (status) 5160e674aebSAnirudh Venkataramanan netdev_err(vsi->netdev, "Failed to stop Rx rings, VSI %d error %d\n", 5170e674aebSAnirudh Venkataramanan vsi->vsi_num, status); 5180e674aebSAnirudh Venkataramanan 5190e674aebSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 5200e674aebSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 5210e674aebSAnirudh Venkataramanan 5220e674aebSAnirudh Venkataramanan return status; 5230e674aebSAnirudh Venkataramanan } 5240e674aebSAnirudh Venkataramanan 5250e674aebSAnirudh Venkataramanan /** 5260e674aebSAnirudh Venkataramanan * ice_lbtest_create_frame - create test packet 5270e674aebSAnirudh Venkataramanan * @pf: pointer to the PF structure 5280e674aebSAnirudh Venkataramanan * @ret_data: allocated frame buffer 5290e674aebSAnirudh Venkataramanan * @size: size of the packet data 5300e674aebSAnirudh Venkataramanan * 5310e674aebSAnirudh Venkataramanan * Function allocates a frame with a test pattern on specific offsets. 5320e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 5330e674aebSAnirudh Venkataramanan */ 5340e674aebSAnirudh Venkataramanan static int ice_lbtest_create_frame(struct ice_pf *pf, u8 **ret_data, u16 size) 5350e674aebSAnirudh Venkataramanan { 5360e674aebSAnirudh Venkataramanan u8 *data; 5370e674aebSAnirudh Venkataramanan 5380e674aebSAnirudh Venkataramanan if (!pf) 5390e674aebSAnirudh Venkataramanan return -EINVAL; 5400e674aebSAnirudh Venkataramanan 5414015d11eSBrett Creeley data = devm_kzalloc(ice_pf_to_dev(pf), size, GFP_KERNEL); 5420e674aebSAnirudh Venkataramanan if (!data) 5430e674aebSAnirudh Venkataramanan return -ENOMEM; 5440e674aebSAnirudh Venkataramanan 5450e674aebSAnirudh Venkataramanan /* Since the ethernet test frame should always be at least 5460e674aebSAnirudh Venkataramanan * 64 bytes long, fill some octets in the payload with test data. 5470e674aebSAnirudh Venkataramanan */ 5480e674aebSAnirudh Venkataramanan memset(data, 0xFF, size); 5490e674aebSAnirudh Venkataramanan data[32] = 0xDE; 5500e674aebSAnirudh Venkataramanan data[42] = 0xAD; 5510e674aebSAnirudh Venkataramanan data[44] = 0xBE; 5520e674aebSAnirudh Venkataramanan data[46] = 0xEF; 5530e674aebSAnirudh Venkataramanan 5540e674aebSAnirudh Venkataramanan *ret_data = data; 5550e674aebSAnirudh Venkataramanan 5560e674aebSAnirudh Venkataramanan return 0; 5570e674aebSAnirudh Venkataramanan } 5580e674aebSAnirudh Venkataramanan 5590e674aebSAnirudh Venkataramanan /** 5600e674aebSAnirudh Venkataramanan * ice_lbtest_check_frame - verify received loopback frame 5610e674aebSAnirudh Venkataramanan * @frame: pointer to the raw packet data 5620e674aebSAnirudh Venkataramanan * 5630e674aebSAnirudh Venkataramanan * Function verifies received test frame with a pattern. 5640e674aebSAnirudh Venkataramanan * Returns true if frame matches the pattern, false otherwise. 5650e674aebSAnirudh Venkataramanan */ 5660e674aebSAnirudh Venkataramanan static bool ice_lbtest_check_frame(u8 *frame) 5670e674aebSAnirudh Venkataramanan { 5680e674aebSAnirudh Venkataramanan /* Validate bytes of a frame under offsets chosen earlier */ 5690e674aebSAnirudh Venkataramanan if (frame[32] == 0xDE && 5700e674aebSAnirudh Venkataramanan frame[42] == 0xAD && 5710e674aebSAnirudh Venkataramanan frame[44] == 0xBE && 5720e674aebSAnirudh Venkataramanan frame[46] == 0xEF && 5730e674aebSAnirudh Venkataramanan frame[48] == 0xFF) 5740e674aebSAnirudh Venkataramanan return true; 5750e674aebSAnirudh Venkataramanan 5760e674aebSAnirudh Venkataramanan return false; 5770e674aebSAnirudh Venkataramanan } 5780e674aebSAnirudh Venkataramanan 5790e674aebSAnirudh Venkataramanan /** 5800e674aebSAnirudh Venkataramanan * ice_diag_send - send test frames to the test ring 5810e674aebSAnirudh Venkataramanan * @tx_ring: pointer to the transmit ring 5820e674aebSAnirudh Venkataramanan * @data: pointer to the raw packet data 5830e674aebSAnirudh Venkataramanan * @size: size of the packet to send 5840e674aebSAnirudh Venkataramanan * 5850e674aebSAnirudh Venkataramanan * Function sends loopback packets on a test Tx ring. 5860e674aebSAnirudh Venkataramanan */ 5870e674aebSAnirudh Venkataramanan static int ice_diag_send(struct ice_ring *tx_ring, u8 *data, u16 size) 5880e674aebSAnirudh Venkataramanan { 5890e674aebSAnirudh Venkataramanan struct ice_tx_desc *tx_desc; 5900e674aebSAnirudh Venkataramanan struct ice_tx_buf *tx_buf; 5910e674aebSAnirudh Venkataramanan dma_addr_t dma; 5920e674aebSAnirudh Venkataramanan u64 td_cmd; 5930e674aebSAnirudh Venkataramanan 5940e674aebSAnirudh Venkataramanan tx_desc = ICE_TX_DESC(tx_ring, tx_ring->next_to_use); 5950e674aebSAnirudh Venkataramanan tx_buf = &tx_ring->tx_buf[tx_ring->next_to_use]; 5960e674aebSAnirudh Venkataramanan 5970e674aebSAnirudh Venkataramanan dma = dma_map_single(tx_ring->dev, data, size, DMA_TO_DEVICE); 5980e674aebSAnirudh Venkataramanan if (dma_mapping_error(tx_ring->dev, dma)) 5990e674aebSAnirudh Venkataramanan return -EINVAL; 6000e674aebSAnirudh Venkataramanan 6010e674aebSAnirudh Venkataramanan tx_desc->buf_addr = cpu_to_le64(dma); 6020e674aebSAnirudh Venkataramanan 6030e674aebSAnirudh Venkataramanan /* These flags are required for a descriptor to be pushed out */ 6040e674aebSAnirudh Venkataramanan td_cmd = (u64)(ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS); 6050e674aebSAnirudh Venkataramanan tx_desc->cmd_type_offset_bsz = 6060e674aebSAnirudh Venkataramanan cpu_to_le64(ICE_TX_DESC_DTYPE_DATA | 6070e674aebSAnirudh Venkataramanan (td_cmd << ICE_TXD_QW1_CMD_S) | 6080e674aebSAnirudh Venkataramanan ((u64)0 << ICE_TXD_QW1_OFFSET_S) | 6090e674aebSAnirudh Venkataramanan ((u64)size << ICE_TXD_QW1_TX_BUF_SZ_S) | 6100e674aebSAnirudh Venkataramanan ((u64)0 << ICE_TXD_QW1_L2TAG1_S)); 6110e674aebSAnirudh Venkataramanan 6120e674aebSAnirudh Venkataramanan tx_buf->next_to_watch = tx_desc; 6130e674aebSAnirudh Venkataramanan 6140e674aebSAnirudh Venkataramanan /* Force memory write to complete before letting h/w know 6150e674aebSAnirudh Venkataramanan * there are new descriptors to fetch. 6160e674aebSAnirudh Venkataramanan */ 6170e674aebSAnirudh Venkataramanan wmb(); 6180e674aebSAnirudh Venkataramanan 6190e674aebSAnirudh Venkataramanan tx_ring->next_to_use++; 6200e674aebSAnirudh Venkataramanan if (tx_ring->next_to_use >= tx_ring->count) 6210e674aebSAnirudh Venkataramanan tx_ring->next_to_use = 0; 6220e674aebSAnirudh Venkataramanan 6230e674aebSAnirudh Venkataramanan writel_relaxed(tx_ring->next_to_use, tx_ring->tail); 6240e674aebSAnirudh Venkataramanan 6250e674aebSAnirudh Venkataramanan /* Wait until the packets get transmitted to the receive queue. */ 6260e674aebSAnirudh Venkataramanan usleep_range(1000, 2000); 6270e674aebSAnirudh Venkataramanan dma_unmap_single(tx_ring->dev, dma, size, DMA_TO_DEVICE); 6280e674aebSAnirudh Venkataramanan 6290e674aebSAnirudh Venkataramanan return 0; 6300e674aebSAnirudh Venkataramanan } 6310e674aebSAnirudh Venkataramanan 6320e674aebSAnirudh Venkataramanan #define ICE_LB_FRAME_SIZE 64 6330e674aebSAnirudh Venkataramanan /** 6340e674aebSAnirudh Venkataramanan * ice_lbtest_receive_frames - receive and verify test frames 6350e674aebSAnirudh Venkataramanan * @rx_ring: pointer to the receive ring 6360e674aebSAnirudh Venkataramanan * 6370e674aebSAnirudh Venkataramanan * Function receives loopback packets and verify their correctness. 6380e674aebSAnirudh Venkataramanan * Returns number of received valid frames. 6390e674aebSAnirudh Venkataramanan */ 6400e674aebSAnirudh Venkataramanan static int ice_lbtest_receive_frames(struct ice_ring *rx_ring) 6410e674aebSAnirudh Venkataramanan { 6420e674aebSAnirudh Venkataramanan struct ice_rx_buf *rx_buf; 6430e674aebSAnirudh Venkataramanan int valid_frames, i; 6440e674aebSAnirudh Venkataramanan u8 *received_buf; 6450e674aebSAnirudh Venkataramanan 6460e674aebSAnirudh Venkataramanan valid_frames = 0; 6470e674aebSAnirudh Venkataramanan 6480e674aebSAnirudh Venkataramanan for (i = 0; i < rx_ring->count; i++) { 6490e674aebSAnirudh Venkataramanan union ice_32b_rx_flex_desc *rx_desc; 6500e674aebSAnirudh Venkataramanan 6510e674aebSAnirudh Venkataramanan rx_desc = ICE_RX_DESC(rx_ring, i); 6520e674aebSAnirudh Venkataramanan 6530e674aebSAnirudh Venkataramanan if (!(rx_desc->wb.status_error0 & 6540e674aebSAnirudh Venkataramanan cpu_to_le16(ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS))) 6550e674aebSAnirudh Venkataramanan continue; 6560e674aebSAnirudh Venkataramanan 6570e674aebSAnirudh Venkataramanan rx_buf = &rx_ring->rx_buf[i]; 65859bb0808SMaciej Fijalkowski received_buf = page_address(rx_buf->page) + rx_buf->page_offset; 6590e674aebSAnirudh Venkataramanan 6600e674aebSAnirudh Venkataramanan if (ice_lbtest_check_frame(received_buf)) 6610e674aebSAnirudh Venkataramanan valid_frames++; 6620e674aebSAnirudh Venkataramanan } 6630e674aebSAnirudh Venkataramanan 6640e674aebSAnirudh Venkataramanan return valid_frames; 6650e674aebSAnirudh Venkataramanan } 6660e674aebSAnirudh Venkataramanan 6670e674aebSAnirudh Venkataramanan /** 6680e674aebSAnirudh Venkataramanan * ice_loopback_test - perform a loopback test on a given net_device 6690e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 6700e674aebSAnirudh Venkataramanan * 6710e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 6720e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 6730e674aebSAnirudh Venkataramanan */ 6740e674aebSAnirudh Venkataramanan static u64 ice_loopback_test(struct net_device *netdev) 6750e674aebSAnirudh Venkataramanan { 6760e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 6770e674aebSAnirudh Venkataramanan struct ice_vsi *orig_vsi = np->vsi, *test_vsi; 6780e674aebSAnirudh Venkataramanan struct ice_pf *pf = orig_vsi->back; 6790e674aebSAnirudh Venkataramanan struct ice_ring *tx_ring, *rx_ring; 6800e674aebSAnirudh Venkataramanan u8 broadcast[ETH_ALEN], ret = 0; 6810e674aebSAnirudh Venkataramanan int num_frames, valid_frames; 6824015d11eSBrett Creeley struct device *dev; 6830e674aebSAnirudh Venkataramanan u8 *tx_frame; 6840e674aebSAnirudh Venkataramanan int i; 6850e674aebSAnirudh Venkataramanan 6864015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 6870e674aebSAnirudh Venkataramanan netdev_info(netdev, "loopback test\n"); 6880e674aebSAnirudh Venkataramanan 6890e674aebSAnirudh Venkataramanan test_vsi = ice_lb_vsi_setup(pf, pf->hw.port_info); 6900e674aebSAnirudh Venkataramanan if (!test_vsi) { 691af23635aSJesse Brandeburg netdev_err(netdev, "Failed to create a VSI for the loopback test\n"); 6920e674aebSAnirudh Venkataramanan return 1; 6930e674aebSAnirudh Venkataramanan } 6940e674aebSAnirudh Venkataramanan 6950e674aebSAnirudh Venkataramanan test_vsi->netdev = netdev; 6960e674aebSAnirudh Venkataramanan tx_ring = test_vsi->tx_rings[0]; 6970e674aebSAnirudh Venkataramanan rx_ring = test_vsi->rx_rings[0]; 6980e674aebSAnirudh Venkataramanan 6990e674aebSAnirudh Venkataramanan if (ice_lbtest_prepare_rings(test_vsi)) { 7000e674aebSAnirudh Venkataramanan ret = 2; 7010e674aebSAnirudh Venkataramanan goto lbtest_vsi_close; 7020e674aebSAnirudh Venkataramanan } 7030e674aebSAnirudh Venkataramanan 7040e674aebSAnirudh Venkataramanan if (ice_alloc_rx_bufs(rx_ring, rx_ring->count)) { 7050e674aebSAnirudh Venkataramanan ret = 3; 7060e674aebSAnirudh Venkataramanan goto lbtest_rings_dis; 7070e674aebSAnirudh Venkataramanan } 7080e674aebSAnirudh Venkataramanan 7090e674aebSAnirudh Venkataramanan /* Enable MAC loopback in firmware */ 7100e674aebSAnirudh Venkataramanan if (ice_aq_set_mac_loopback(&pf->hw, true, NULL)) { 7110e674aebSAnirudh Venkataramanan ret = 4; 7120e674aebSAnirudh Venkataramanan goto lbtest_mac_dis; 7130e674aebSAnirudh Venkataramanan } 7140e674aebSAnirudh Venkataramanan 7150e674aebSAnirudh Venkataramanan /* Test VSI needs to receive broadcast packets */ 7160e674aebSAnirudh Venkataramanan eth_broadcast_addr(broadcast); 7171b8f15b6SMichal Swiatkowski if (ice_fltr_add_mac(test_vsi, broadcast, ICE_FWD_TO_VSI)) { 7180e674aebSAnirudh Venkataramanan ret = 5; 7190e674aebSAnirudh Venkataramanan goto lbtest_mac_dis; 7200e674aebSAnirudh Venkataramanan } 7210e674aebSAnirudh Venkataramanan 7220e674aebSAnirudh Venkataramanan if (ice_lbtest_create_frame(pf, &tx_frame, ICE_LB_FRAME_SIZE)) { 7230e674aebSAnirudh Venkataramanan ret = 7; 7240e674aebSAnirudh Venkataramanan goto remove_mac_filters; 7250e674aebSAnirudh Venkataramanan } 7260e674aebSAnirudh Venkataramanan 7270e674aebSAnirudh Venkataramanan num_frames = min_t(int, tx_ring->count, 32); 7280e674aebSAnirudh Venkataramanan for (i = 0; i < num_frames; i++) { 7290e674aebSAnirudh Venkataramanan if (ice_diag_send(tx_ring, tx_frame, ICE_LB_FRAME_SIZE)) { 7300e674aebSAnirudh Venkataramanan ret = 8; 7310e674aebSAnirudh Venkataramanan goto lbtest_free_frame; 7320e674aebSAnirudh Venkataramanan } 7330e674aebSAnirudh Venkataramanan } 7340e674aebSAnirudh Venkataramanan 7350e674aebSAnirudh Venkataramanan valid_frames = ice_lbtest_receive_frames(rx_ring); 7360e674aebSAnirudh Venkataramanan if (!valid_frames) 7370e674aebSAnirudh Venkataramanan ret = 9; 7380e674aebSAnirudh Venkataramanan else if (valid_frames != num_frames) 7390e674aebSAnirudh Venkataramanan ret = 10; 7400e674aebSAnirudh Venkataramanan 7410e674aebSAnirudh Venkataramanan lbtest_free_frame: 7424015d11eSBrett Creeley devm_kfree(dev, tx_frame); 7430e674aebSAnirudh Venkataramanan remove_mac_filters: 7441b8f15b6SMichal Swiatkowski if (ice_fltr_remove_mac(test_vsi, broadcast, ICE_FWD_TO_VSI)) 745af23635aSJesse Brandeburg netdev_err(netdev, "Could not remove MAC filter for the test VSI\n"); 7460e674aebSAnirudh Venkataramanan lbtest_mac_dis: 7470e674aebSAnirudh Venkataramanan /* Disable MAC loopback after the test is completed. */ 7480e674aebSAnirudh Venkataramanan if (ice_aq_set_mac_loopback(&pf->hw, false, NULL)) 7490e674aebSAnirudh Venkataramanan netdev_err(netdev, "Could not disable MAC loopback\n"); 7500e674aebSAnirudh Venkataramanan lbtest_rings_dis: 7510e674aebSAnirudh Venkataramanan if (ice_lbtest_disable_rings(test_vsi)) 7520e674aebSAnirudh Venkataramanan netdev_err(netdev, "Could not disable test rings\n"); 7530e674aebSAnirudh Venkataramanan lbtest_vsi_close: 7540e674aebSAnirudh Venkataramanan test_vsi->netdev = NULL; 7550e674aebSAnirudh Venkataramanan if (ice_vsi_release(test_vsi)) 756af23635aSJesse Brandeburg netdev_err(netdev, "Failed to remove the test VSI\n"); 7570e674aebSAnirudh Venkataramanan 7580e674aebSAnirudh Venkataramanan return ret; 7590e674aebSAnirudh Venkataramanan } 7600e674aebSAnirudh Venkataramanan 7610e674aebSAnirudh Venkataramanan /** 7620e674aebSAnirudh Venkataramanan * ice_intr_test - perform an interrupt test on a given net_device 7630e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 7640e674aebSAnirudh Venkataramanan * 7650e674aebSAnirudh Venkataramanan * This function performs one of the self-tests required by ethtool. 7660e674aebSAnirudh Venkataramanan * Returns 0 on success, non-zero on failure. 7670e674aebSAnirudh Venkataramanan */ 7680e674aebSAnirudh Venkataramanan static u64 ice_intr_test(struct net_device *netdev) 7690e674aebSAnirudh Venkataramanan { 7700e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 7710e674aebSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 7720e674aebSAnirudh Venkataramanan u16 swic_old = pf->sw_int_count; 7730e674aebSAnirudh Venkataramanan 7740e674aebSAnirudh Venkataramanan netdev_info(netdev, "interrupt test\n"); 7750e674aebSAnirudh Venkataramanan 776cbe66bfeSBrett Creeley wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_idx), 7770e674aebSAnirudh Venkataramanan GLINT_DYN_CTL_SW_ITR_INDX_M | 7780e674aebSAnirudh Venkataramanan GLINT_DYN_CTL_INTENA_MSK_M | 7790e674aebSAnirudh Venkataramanan GLINT_DYN_CTL_SWINT_TRIG_M); 7800e674aebSAnirudh Venkataramanan 7810e674aebSAnirudh Venkataramanan usleep_range(1000, 2000); 7820e674aebSAnirudh Venkataramanan return (swic_old == pf->sw_int_count); 7830e674aebSAnirudh Venkataramanan } 7840e674aebSAnirudh Venkataramanan 7850e674aebSAnirudh Venkataramanan /** 7860e674aebSAnirudh Venkataramanan * ice_self_test - handler function for performing a self-test by ethtool 7870e674aebSAnirudh Venkataramanan * @netdev: network interface device structure 7880e674aebSAnirudh Venkataramanan * @eth_test: ethtool_test structure 7890e674aebSAnirudh Venkataramanan * @data: required by ethtool.self_test 7900e674aebSAnirudh Venkataramanan * 7910e674aebSAnirudh Venkataramanan * This function is called after invoking 'ethtool -t devname' command where 7920e674aebSAnirudh Venkataramanan * devname is the name of the network device on which ethtool should operate. 7930e674aebSAnirudh Venkataramanan * It performs a set of self-tests to check if a device works properly. 7940e674aebSAnirudh Venkataramanan */ 7950e674aebSAnirudh Venkataramanan static void 7960e674aebSAnirudh Venkataramanan ice_self_test(struct net_device *netdev, struct ethtool_test *eth_test, 7970e674aebSAnirudh Venkataramanan u64 *data) 7980e674aebSAnirudh Venkataramanan { 7990e674aebSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 8000e674aebSAnirudh Venkataramanan bool if_running = netif_running(netdev); 8010e674aebSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 8024015d11eSBrett Creeley struct device *dev; 8034015d11eSBrett Creeley 8044015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 8050e674aebSAnirudh Venkataramanan 8060e674aebSAnirudh Venkataramanan if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 8070e674aebSAnirudh Venkataramanan netdev_info(netdev, "offline testing starting\n"); 8080e674aebSAnirudh Venkataramanan 8090e674aebSAnirudh Venkataramanan set_bit(__ICE_TESTING, pf->state); 8100e674aebSAnirudh Venkataramanan 8110e674aebSAnirudh Venkataramanan if (ice_active_vfs(pf)) { 81219cce2c6SAnirudh Venkataramanan dev_warn(dev, "Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\n"); 8130e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG] = 1; 8140e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] = 1; 8150e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] = 1; 8160e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] = 1; 8170e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LINK] = 1; 8180e674aebSAnirudh Venkataramanan eth_test->flags |= ETH_TEST_FL_FAILED; 8190e674aebSAnirudh Venkataramanan clear_bit(__ICE_TESTING, pf->state); 8200e674aebSAnirudh Venkataramanan goto skip_ol_tests; 8210e674aebSAnirudh Venkataramanan } 8220e674aebSAnirudh Venkataramanan /* If the device is online then take it offline */ 8230e674aebSAnirudh Venkataramanan if (if_running) 8240e674aebSAnirudh Venkataramanan /* indicate we're in test mode */ 8250e674aebSAnirudh Venkataramanan ice_stop(netdev); 8260e674aebSAnirudh Venkataramanan 8270e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LINK] = ice_link_test(netdev); 8280e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] = ice_eeprom_test(netdev); 8290e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] = ice_intr_test(netdev); 8300e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] = ice_loopback_test(netdev); 8310e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG] = ice_reg_test(netdev); 8320e674aebSAnirudh Venkataramanan 8330e674aebSAnirudh Venkataramanan if (data[ICE_ETH_TEST_LINK] || 8340e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] || 8350e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] || 8360e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] || 8370e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG]) 8380e674aebSAnirudh Venkataramanan eth_test->flags |= ETH_TEST_FL_FAILED; 8390e674aebSAnirudh Venkataramanan 8400e674aebSAnirudh Venkataramanan clear_bit(__ICE_TESTING, pf->state); 8410e674aebSAnirudh Venkataramanan 8420e674aebSAnirudh Venkataramanan if (if_running) { 8430e674aebSAnirudh Venkataramanan int status = ice_open(netdev); 8440e674aebSAnirudh Venkataramanan 8450e674aebSAnirudh Venkataramanan if (status) { 846af23635aSJesse Brandeburg dev_err(dev, "Could not open device %s, err %d\n", 8470e674aebSAnirudh Venkataramanan pf->int_name, status); 8480e674aebSAnirudh Venkataramanan } 8490e674aebSAnirudh Venkataramanan } 8500e674aebSAnirudh Venkataramanan } else { 8510e674aebSAnirudh Venkataramanan /* Online tests */ 8520e674aebSAnirudh Venkataramanan netdev_info(netdev, "online testing starting\n"); 8530e674aebSAnirudh Venkataramanan 8540e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LINK] = ice_link_test(netdev); 8550e674aebSAnirudh Venkataramanan if (data[ICE_ETH_TEST_LINK]) 8560e674aebSAnirudh Venkataramanan eth_test->flags |= ETH_TEST_FL_FAILED; 8570e674aebSAnirudh Venkataramanan 8580e674aebSAnirudh Venkataramanan /* Offline only tests, not run in online; pass by default */ 8590e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_REG] = 0; 8600e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_EEPROM] = 0; 8610e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_INTR] = 0; 8620e674aebSAnirudh Venkataramanan data[ICE_ETH_TEST_LOOP] = 0; 8630e674aebSAnirudh Venkataramanan } 8640e674aebSAnirudh Venkataramanan 8650e674aebSAnirudh Venkataramanan skip_ol_tests: 8660e674aebSAnirudh Venkataramanan netdev_info(netdev, "testing finished\n"); 8670e674aebSAnirudh Venkataramanan } 8680e674aebSAnirudh Venkataramanan 869fcea6f3dSAnirudh Venkataramanan static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data) 870fcea6f3dSAnirudh Venkataramanan { 871fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 872fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 873fcea6f3dSAnirudh Venkataramanan char *p = (char *)data; 874fcea6f3dSAnirudh Venkataramanan unsigned int i; 875fcea6f3dSAnirudh Venkataramanan 876fcea6f3dSAnirudh Venkataramanan switch (stringset) { 877fcea6f3dSAnirudh Venkataramanan case ETH_SS_STATS: 878fcea6f3dSAnirudh Venkataramanan for (i = 0; i < ICE_VSI_STATS_LEN; i++) { 879fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, "%s", 880fcea6f3dSAnirudh Venkataramanan ice_gstrings_vsi_stats[i].stat_string); 881fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 882fcea6f3dSAnirudh Venkataramanan } 883fcea6f3dSAnirudh Venkataramanan 884f8ba7db8SJacob Keller ice_for_each_alloc_txq(vsi, i) { 885fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 88655e062baSRichard Rodriguez "tx_queue_%u_packets", i); 887fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 88855e062baSRichard Rodriguez snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i); 889fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 890fcea6f3dSAnirudh Venkataramanan } 891fcea6f3dSAnirudh Venkataramanan 892f8ba7db8SJacob Keller ice_for_each_alloc_rxq(vsi, i) { 893fcea6f3dSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 89455e062baSRichard Rodriguez "rx_queue_%u_packets", i); 895fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 89655e062baSRichard Rodriguez snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i); 897fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 898fcea6f3dSAnirudh Venkataramanan } 899fcea6f3dSAnirudh Venkataramanan 900fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 901fcea6f3dSAnirudh Venkataramanan return; 902fcea6f3dSAnirudh Venkataramanan 903fcea6f3dSAnirudh Venkataramanan for (i = 0; i < ICE_PF_STATS_LEN; i++) { 9041fa6e138SJesse Brandeburg snprintf(p, ETH_GSTRING_LEN, "%s", 905fcea6f3dSAnirudh Venkataramanan ice_gstrings_pf_stats[i].stat_string); 906fcea6f3dSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 907fcea6f3dSAnirudh Venkataramanan } 908fcea6f3dSAnirudh Venkataramanan 9094b0fdcebSAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 9104b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 91155e062baSRichard Rodriguez "tx_priority_%u_xon.nic", i); 9124b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9134b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 91455e062baSRichard Rodriguez "tx_priority_%u_xoff.nic", i); 9154b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9164b0fdcebSAnirudh Venkataramanan } 9174b0fdcebSAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 9184b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 91955e062baSRichard Rodriguez "rx_priority_%u_xon.nic", i); 9204b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9214b0fdcebSAnirudh Venkataramanan snprintf(p, ETH_GSTRING_LEN, 92255e062baSRichard Rodriguez "rx_priority_%u_xoff.nic", i); 9234b0fdcebSAnirudh Venkataramanan p += ETH_GSTRING_LEN; 9244b0fdcebSAnirudh Venkataramanan } 925fcea6f3dSAnirudh Venkataramanan break; 9260e674aebSAnirudh Venkataramanan case ETH_SS_TEST: 9270e674aebSAnirudh Venkataramanan memcpy(data, ice_gstrings_test, ICE_TEST_LEN * ETH_GSTRING_LEN); 9280e674aebSAnirudh Venkataramanan break; 929ab4ab73fSBruce Allan case ETH_SS_PRIV_FLAGS: 930ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 931ab4ab73fSBruce Allan snprintf(p, ETH_GSTRING_LEN, "%s", 932ab4ab73fSBruce Allan ice_gstrings_priv_flags[i].name); 933ab4ab73fSBruce Allan p += ETH_GSTRING_LEN; 934ab4ab73fSBruce Allan } 935ab4ab73fSBruce Allan break; 936fcea6f3dSAnirudh Venkataramanan default: 937fcea6f3dSAnirudh Venkataramanan break; 938fcea6f3dSAnirudh Venkataramanan } 939fcea6f3dSAnirudh Venkataramanan } 940fcea6f3dSAnirudh Venkataramanan 9418e151d50SAnirudh Venkataramanan static int 9428e151d50SAnirudh Venkataramanan ice_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) 9438e151d50SAnirudh Venkataramanan { 9448e151d50SAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 9458e151d50SAnirudh Venkataramanan bool led_active; 9468e151d50SAnirudh Venkataramanan 9478e151d50SAnirudh Venkataramanan switch (state) { 9488e151d50SAnirudh Venkataramanan case ETHTOOL_ID_ACTIVE: 9498e151d50SAnirudh Venkataramanan led_active = true; 9508e151d50SAnirudh Venkataramanan break; 9518e151d50SAnirudh Venkataramanan case ETHTOOL_ID_INACTIVE: 9528e151d50SAnirudh Venkataramanan led_active = false; 9538e151d50SAnirudh Venkataramanan break; 9548e151d50SAnirudh Venkataramanan default: 9558e151d50SAnirudh Venkataramanan return -EINVAL; 9568e151d50SAnirudh Venkataramanan } 9578e151d50SAnirudh Venkataramanan 9588e151d50SAnirudh Venkataramanan if (ice_aq_set_port_id_led(np->vsi->port_info, !led_active, NULL)) 9598e151d50SAnirudh Venkataramanan return -EIO; 9608e151d50SAnirudh Venkataramanan 9618e151d50SAnirudh Venkataramanan return 0; 9628e151d50SAnirudh Venkataramanan } 9638e151d50SAnirudh Venkataramanan 964ab4ab73fSBruce Allan /** 965f776b3acSPaul Greenwalt * ice_set_fec_cfg - Set link FEC options 966f776b3acSPaul Greenwalt * @netdev: network interface device structure 967f776b3acSPaul Greenwalt * @req_fec: FEC mode to configure 968f776b3acSPaul Greenwalt */ 969f776b3acSPaul Greenwalt static int ice_set_fec_cfg(struct net_device *netdev, enum ice_fec_mode req_fec) 970f776b3acSPaul Greenwalt { 971f776b3acSPaul Greenwalt struct ice_netdev_priv *np = netdev_priv(netdev); 972f776b3acSPaul Greenwalt struct ice_aqc_set_phy_cfg_data config = { 0 }; 973f776b3acSPaul Greenwalt struct ice_aqc_get_phy_caps_data *caps; 974f776b3acSPaul Greenwalt struct ice_vsi *vsi = np->vsi; 975f776b3acSPaul Greenwalt u8 sw_cfg_caps, sw_cfg_fec; 976f776b3acSPaul Greenwalt struct ice_port_info *pi; 977f776b3acSPaul Greenwalt enum ice_status status; 978f776b3acSPaul Greenwalt int err = 0; 979f776b3acSPaul Greenwalt 980f776b3acSPaul Greenwalt pi = vsi->port_info; 981f776b3acSPaul Greenwalt if (!pi) 982f776b3acSPaul Greenwalt return -EOPNOTSUPP; 983f776b3acSPaul Greenwalt 984f776b3acSPaul Greenwalt /* Changing the FEC parameters is not supported if not the PF VSI */ 985f776b3acSPaul Greenwalt if (vsi->type != ICE_VSI_PF) { 986f776b3acSPaul Greenwalt netdev_info(netdev, "Changing FEC parameters only supported for PF VSI\n"); 987f776b3acSPaul Greenwalt return -EOPNOTSUPP; 988f776b3acSPaul Greenwalt } 989f776b3acSPaul Greenwalt 990f776b3acSPaul Greenwalt /* Get last SW configuration */ 9919efe35d0STony Nguyen caps = kzalloc(sizeof(*caps), GFP_KERNEL); 992f776b3acSPaul Greenwalt if (!caps) 993f776b3acSPaul Greenwalt return -ENOMEM; 994f776b3acSPaul Greenwalt 995f776b3acSPaul Greenwalt status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, 996f776b3acSPaul Greenwalt caps, NULL); 997f776b3acSPaul Greenwalt if (status) { 998f776b3acSPaul Greenwalt err = -EAGAIN; 999f776b3acSPaul Greenwalt goto done; 1000f776b3acSPaul Greenwalt } 1001f776b3acSPaul Greenwalt 1002f776b3acSPaul Greenwalt /* Copy SW configuration returned from PHY caps to PHY config */ 1003f776b3acSPaul Greenwalt ice_copy_phy_caps_to_cfg(caps, &config); 1004f776b3acSPaul Greenwalt sw_cfg_caps = caps->caps; 1005f776b3acSPaul Greenwalt sw_cfg_fec = caps->link_fec_options; 1006f776b3acSPaul Greenwalt 1007f776b3acSPaul Greenwalt /* Get toloplogy caps, then copy PHY FEC topoloy caps to PHY config */ 1008f776b3acSPaul Greenwalt memset(caps, 0, sizeof(*caps)); 1009f776b3acSPaul Greenwalt 1010f776b3acSPaul Greenwalt status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, 1011f776b3acSPaul Greenwalt caps, NULL); 1012f776b3acSPaul Greenwalt if (status) { 1013f776b3acSPaul Greenwalt err = -EAGAIN; 1014f776b3acSPaul Greenwalt goto done; 1015f776b3acSPaul Greenwalt } 1016f776b3acSPaul Greenwalt 1017f776b3acSPaul Greenwalt config.caps |= (caps->caps & ICE_AQC_PHY_EN_AUTO_FEC); 1018f776b3acSPaul Greenwalt config.link_fec_opt = caps->link_fec_options; 1019f776b3acSPaul Greenwalt 1020f776b3acSPaul Greenwalt ice_cfg_phy_fec(&config, req_fec); 1021f776b3acSPaul Greenwalt 1022f776b3acSPaul Greenwalt /* If FEC mode has changed, then set PHY configuration and enable AN. */ 1023f776b3acSPaul Greenwalt if ((config.caps & ICE_AQ_PHY_ENA_AUTO_FEC) != 1024f776b3acSPaul Greenwalt (sw_cfg_caps & ICE_AQC_PHY_EN_AUTO_FEC) || 1025f776b3acSPaul Greenwalt config.link_fec_opt != sw_cfg_fec) { 1026f776b3acSPaul Greenwalt if (caps->caps & ICE_AQC_PHY_AN_MODE) 1027f776b3acSPaul Greenwalt config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 1028f776b3acSPaul Greenwalt 1029f776b3acSPaul Greenwalt status = ice_aq_set_phy_cfg(pi->hw, pi->lport, &config, NULL); 1030f776b3acSPaul Greenwalt 1031f776b3acSPaul Greenwalt if (status) 1032f776b3acSPaul Greenwalt err = -EAGAIN; 1033f776b3acSPaul Greenwalt } 1034f776b3acSPaul Greenwalt 1035f776b3acSPaul Greenwalt done: 10369efe35d0STony Nguyen kfree(caps); 1037f776b3acSPaul Greenwalt return err; 1038f776b3acSPaul Greenwalt } 1039f776b3acSPaul Greenwalt 1040f776b3acSPaul Greenwalt /** 1041f776b3acSPaul Greenwalt * ice_set_fecparam - Set FEC link options 1042f776b3acSPaul Greenwalt * @netdev: network interface device structure 1043f776b3acSPaul Greenwalt * @fecparam: Ethtool structure to retrieve FEC parameters 1044f776b3acSPaul Greenwalt */ 1045f776b3acSPaul Greenwalt static int 1046f776b3acSPaul Greenwalt ice_set_fecparam(struct net_device *netdev, struct ethtool_fecparam *fecparam) 1047f776b3acSPaul Greenwalt { 1048f776b3acSPaul Greenwalt struct ice_netdev_priv *np = netdev_priv(netdev); 1049f776b3acSPaul Greenwalt struct ice_vsi *vsi = np->vsi; 1050f776b3acSPaul Greenwalt enum ice_fec_mode fec; 1051f776b3acSPaul Greenwalt 1052f776b3acSPaul Greenwalt switch (fecparam->fec) { 1053f776b3acSPaul Greenwalt case ETHTOOL_FEC_AUTO: 1054f776b3acSPaul Greenwalt fec = ICE_FEC_AUTO; 1055f776b3acSPaul Greenwalt break; 1056f776b3acSPaul Greenwalt case ETHTOOL_FEC_RS: 1057f776b3acSPaul Greenwalt fec = ICE_FEC_RS; 1058f776b3acSPaul Greenwalt break; 1059f776b3acSPaul Greenwalt case ETHTOOL_FEC_BASER: 1060f776b3acSPaul Greenwalt fec = ICE_FEC_BASER; 1061f776b3acSPaul Greenwalt break; 1062f776b3acSPaul Greenwalt case ETHTOOL_FEC_OFF: 1063f776b3acSPaul Greenwalt case ETHTOOL_FEC_NONE: 1064f776b3acSPaul Greenwalt fec = ICE_FEC_NONE; 1065f776b3acSPaul Greenwalt break; 1066f776b3acSPaul Greenwalt default: 10679a946843SAnirudh Venkataramanan dev_warn(ice_pf_to_dev(vsi->back), "Unsupported FEC mode: %d\n", 1068f776b3acSPaul Greenwalt fecparam->fec); 1069f776b3acSPaul Greenwalt return -EINVAL; 1070f776b3acSPaul Greenwalt } 1071f776b3acSPaul Greenwalt 1072f776b3acSPaul Greenwalt return ice_set_fec_cfg(netdev, fec); 1073f776b3acSPaul Greenwalt } 1074f776b3acSPaul Greenwalt 1075f776b3acSPaul Greenwalt /** 1076f776b3acSPaul Greenwalt * ice_get_fecparam - Get link FEC options 1077f776b3acSPaul Greenwalt * @netdev: network interface device structure 1078f776b3acSPaul Greenwalt * @fecparam: Ethtool structure to retrieve FEC parameters 1079f776b3acSPaul Greenwalt */ 1080f776b3acSPaul Greenwalt static int 1081f776b3acSPaul Greenwalt ice_get_fecparam(struct net_device *netdev, struct ethtool_fecparam *fecparam) 1082f776b3acSPaul Greenwalt { 1083f776b3acSPaul Greenwalt struct ice_netdev_priv *np = netdev_priv(netdev); 1084f776b3acSPaul Greenwalt struct ice_aqc_get_phy_caps_data *caps; 1085f776b3acSPaul Greenwalt struct ice_link_status *link_info; 1086f776b3acSPaul Greenwalt struct ice_vsi *vsi = np->vsi; 1087f776b3acSPaul Greenwalt struct ice_port_info *pi; 1088f776b3acSPaul Greenwalt enum ice_status status; 1089f776b3acSPaul Greenwalt int err = 0; 1090f776b3acSPaul Greenwalt 1091f776b3acSPaul Greenwalt pi = vsi->port_info; 1092f776b3acSPaul Greenwalt 1093f776b3acSPaul Greenwalt if (!pi) 1094f776b3acSPaul Greenwalt return -EOPNOTSUPP; 1095f776b3acSPaul Greenwalt link_info = &pi->phy.link_info; 1096f776b3acSPaul Greenwalt 1097f776b3acSPaul Greenwalt /* Set FEC mode based on negotiated link info */ 1098f776b3acSPaul Greenwalt switch (link_info->fec_info) { 1099f776b3acSPaul Greenwalt case ICE_AQ_LINK_25G_KR_FEC_EN: 1100f776b3acSPaul Greenwalt fecparam->active_fec = ETHTOOL_FEC_BASER; 1101f776b3acSPaul Greenwalt break; 1102f776b3acSPaul Greenwalt case ICE_AQ_LINK_25G_RS_528_FEC_EN: 1103f776b3acSPaul Greenwalt case ICE_AQ_LINK_25G_RS_544_FEC_EN: 1104f776b3acSPaul Greenwalt fecparam->active_fec = ETHTOOL_FEC_RS; 1105f776b3acSPaul Greenwalt break; 1106f776b3acSPaul Greenwalt default: 1107f776b3acSPaul Greenwalt fecparam->active_fec = ETHTOOL_FEC_OFF; 1108f776b3acSPaul Greenwalt break; 1109f776b3acSPaul Greenwalt } 1110f776b3acSPaul Greenwalt 11119efe35d0STony Nguyen caps = kzalloc(sizeof(*caps), GFP_KERNEL); 1112f776b3acSPaul Greenwalt if (!caps) 1113f776b3acSPaul Greenwalt return -ENOMEM; 1114f776b3acSPaul Greenwalt 1115f776b3acSPaul Greenwalt status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP, 1116f776b3acSPaul Greenwalt caps, NULL); 1117f776b3acSPaul Greenwalt if (status) { 1118f776b3acSPaul Greenwalt err = -EAGAIN; 1119f776b3acSPaul Greenwalt goto done; 1120f776b3acSPaul Greenwalt } 1121f776b3acSPaul Greenwalt 1122f776b3acSPaul Greenwalt /* Set supported/configured FEC modes based on PHY capability */ 1123f776b3acSPaul Greenwalt if (caps->caps & ICE_AQC_PHY_EN_AUTO_FEC) 1124f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_AUTO; 1125f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN || 1126f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ || 1127f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN || 1128f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_REQ) 1129f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_BASER; 1130f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_528_REQ || 1131f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_544_REQ || 1132f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN) 1133f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_RS; 1134f776b3acSPaul Greenwalt if (caps->link_fec_options == 0) 1135f776b3acSPaul Greenwalt fecparam->fec |= ETHTOOL_FEC_OFF; 1136f776b3acSPaul Greenwalt 1137f776b3acSPaul Greenwalt done: 11389efe35d0STony Nguyen kfree(caps); 1139f776b3acSPaul Greenwalt return err; 1140f776b3acSPaul Greenwalt } 1141f776b3acSPaul Greenwalt 1142f776b3acSPaul Greenwalt /** 114335e93561SDave Ertman * ice_nway_reset - restart autonegotiation 114435e93561SDave Ertman * @netdev: network interface device structure 114535e93561SDave Ertman */ 114635e93561SDave Ertman static int ice_nway_reset(struct net_device *netdev) 114735e93561SDave Ertman { 114835e93561SDave Ertman struct ice_netdev_priv *np = netdev_priv(netdev); 114935e93561SDave Ertman struct ice_vsi *vsi = np->vsi; 115035e93561SDave Ertman struct ice_port_info *pi; 115135e93561SDave Ertman enum ice_status status; 115235e93561SDave Ertman 115335e93561SDave Ertman pi = vsi->port_info; 115435e93561SDave Ertman /* If VSI state is up, then restart autoneg with link up */ 115535e93561SDave Ertman if (!test_bit(__ICE_DOWN, vsi->back->state)) 115635e93561SDave Ertman status = ice_aq_set_link_restart_an(pi, true, NULL); 115735e93561SDave Ertman else 115835e93561SDave Ertman status = ice_aq_set_link_restart_an(pi, false, NULL); 115935e93561SDave Ertman 116035e93561SDave Ertman if (status) { 11610fee3577SLihong Yang netdev_info(netdev, "link restart failed, err %s aq_err %s\n", 11620fee3577SLihong Yang ice_stat_str(status), 11630fee3577SLihong Yang ice_aq_str(pi->hw->adminq.sq_last_status)); 116435e93561SDave Ertman return -EIO; 116535e93561SDave Ertman } 116635e93561SDave Ertman 116735e93561SDave Ertman return 0; 116835e93561SDave Ertman } 116935e93561SDave Ertman 117035e93561SDave Ertman /** 1171ab4ab73fSBruce Allan * ice_get_priv_flags - report device private flags 1172ab4ab73fSBruce Allan * @netdev: network interface device structure 1173ab4ab73fSBruce Allan * 1174ab4ab73fSBruce Allan * The get string set count and the string set should be matched for each 1175ab4ab73fSBruce Allan * flag returned. Add new strings for each flag to the ice_gstrings_priv_flags 1176ab4ab73fSBruce Allan * array. 1177ab4ab73fSBruce Allan * 1178ab4ab73fSBruce Allan * Returns a u32 bitmap of flags. 1179ab4ab73fSBruce Allan */ 1180ab4ab73fSBruce Allan static u32 ice_get_priv_flags(struct net_device *netdev) 1181ab4ab73fSBruce Allan { 1182ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 1183ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 1184ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 1185ab4ab73fSBruce Allan u32 i, ret_flags = 0; 1186ab4ab73fSBruce Allan 1187ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 1188ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 1189ab4ab73fSBruce Allan 1190ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 1191ab4ab73fSBruce Allan 1192ab4ab73fSBruce Allan if (test_bit(priv_flag->bitno, pf->flags)) 1193ab4ab73fSBruce Allan ret_flags |= BIT(i); 1194ab4ab73fSBruce Allan } 1195ab4ab73fSBruce Allan 1196ab4ab73fSBruce Allan return ret_flags; 1197ab4ab73fSBruce Allan } 1198ab4ab73fSBruce Allan 1199ab4ab73fSBruce Allan /** 1200ab4ab73fSBruce Allan * ice_set_priv_flags - set private flags 1201ab4ab73fSBruce Allan * @netdev: network interface device structure 1202ab4ab73fSBruce Allan * @flags: bit flags to be set 1203ab4ab73fSBruce Allan */ 1204ab4ab73fSBruce Allan static int ice_set_priv_flags(struct net_device *netdev, u32 flags) 1205ab4ab73fSBruce Allan { 1206ab4ab73fSBruce Allan struct ice_netdev_priv *np = netdev_priv(netdev); 12073a257a14SAnirudh Venkataramanan DECLARE_BITMAP(change_flags, ICE_PF_FLAGS_NBITS); 12083a257a14SAnirudh Venkataramanan DECLARE_BITMAP(orig_flags, ICE_PF_FLAGS_NBITS); 1209ab4ab73fSBruce Allan struct ice_vsi *vsi = np->vsi; 1210ab4ab73fSBruce Allan struct ice_pf *pf = vsi->back; 12114015d11eSBrett Creeley struct device *dev; 12123a257a14SAnirudh Venkataramanan int ret = 0; 1213ab4ab73fSBruce Allan u32 i; 1214ab4ab73fSBruce Allan 1215ab4ab73fSBruce Allan if (flags > BIT(ICE_PRIV_FLAG_ARRAY_SIZE)) 1216ab4ab73fSBruce Allan return -EINVAL; 1217ab4ab73fSBruce Allan 12184015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 12193a257a14SAnirudh Venkataramanan set_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 12203a257a14SAnirudh Venkataramanan 12213a257a14SAnirudh Venkataramanan bitmap_copy(orig_flags, pf->flags, ICE_PF_FLAGS_NBITS); 1222ab4ab73fSBruce Allan for (i = 0; i < ICE_PRIV_FLAG_ARRAY_SIZE; i++) { 1223ab4ab73fSBruce Allan const struct ice_priv_flag *priv_flag; 1224ab4ab73fSBruce Allan 1225ab4ab73fSBruce Allan priv_flag = &ice_gstrings_priv_flags[i]; 1226ab4ab73fSBruce Allan 1227ab4ab73fSBruce Allan if (flags & BIT(i)) 1228ab4ab73fSBruce Allan set_bit(priv_flag->bitno, pf->flags); 1229ab4ab73fSBruce Allan else 1230ab4ab73fSBruce Allan clear_bit(priv_flag->bitno, pf->flags); 1231ab4ab73fSBruce Allan } 1232ab4ab73fSBruce Allan 12333a257a14SAnirudh Venkataramanan bitmap_xor(change_flags, pf->flags, orig_flags, ICE_PF_FLAGS_NBITS); 12343a257a14SAnirudh Venkataramanan 123584a118abSDave Ertman if (test_bit(ICE_FLAG_FW_LLDP_AGENT, change_flags)) { 123684a118abSDave Ertman if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) { 12373a257a14SAnirudh Venkataramanan enum ice_status status; 12383a257a14SAnirudh Venkataramanan 12392e0e6228SDave Ertman /* Disable FW LLDP engine */ 1240ea300f41SDave Ertman status = ice_cfg_lldp_mib_change(&pf->hw, false); 1241ea300f41SDave Ertman 12423a257a14SAnirudh Venkataramanan /* If unregistering for LLDP events fails, this is 12433a257a14SAnirudh Venkataramanan * not an error state, as there shouldn't be any 12443a257a14SAnirudh Venkataramanan * events to respond to. 12453a257a14SAnirudh Venkataramanan */ 12463a257a14SAnirudh Venkataramanan if (status) 124719cce2c6SAnirudh Venkataramanan dev_info(dev, "Failed to unreg for LLDP events\n"); 12483a257a14SAnirudh Venkataramanan 12493a257a14SAnirudh Venkataramanan /* The AQ call to stop the FW LLDP agent will generate 12503a257a14SAnirudh Venkataramanan * an error if the agent is already stopped. 12513a257a14SAnirudh Venkataramanan */ 125231eafa40SAnirudh Venkataramanan status = ice_aq_stop_lldp(&pf->hw, true, true, NULL); 12533a257a14SAnirudh Venkataramanan if (status) 12544015d11eSBrett Creeley dev_warn(dev, "Fail to stop LLDP agent\n"); 12553a257a14SAnirudh Venkataramanan /* Use case for having the FW LLDP agent stopped 12563a257a14SAnirudh Venkataramanan * will likely not need DCB, so failure to init is 12573a257a14SAnirudh Venkataramanan * not a concern of ethtool 12583a257a14SAnirudh Venkataramanan */ 1259e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 12603a257a14SAnirudh Venkataramanan if (status) 12614015d11eSBrett Creeley dev_warn(dev, "Fail to init DCB\n"); 12623a257a14SAnirudh Venkataramanan } else { 12633a257a14SAnirudh Venkataramanan enum ice_status status; 12643a257a14SAnirudh Venkataramanan bool dcbx_agent_status; 12653a257a14SAnirudh Venkataramanan 12663a257a14SAnirudh Venkataramanan /* AQ command to start FW LLDP agent will return an 12673a257a14SAnirudh Venkataramanan * error if the agent is already started 12683a257a14SAnirudh Venkataramanan */ 126931eafa40SAnirudh Venkataramanan status = ice_aq_start_lldp(&pf->hw, true, NULL); 12703a257a14SAnirudh Venkataramanan if (status) 12714015d11eSBrett Creeley dev_warn(dev, "Fail to start LLDP Agent\n"); 12723a257a14SAnirudh Venkataramanan 12732f2da36eSAnirudh Venkataramanan /* AQ command to start FW DCBX agent will fail if 12743a257a14SAnirudh Venkataramanan * the agent is already started 12753a257a14SAnirudh Venkataramanan */ 12763a257a14SAnirudh Venkataramanan status = ice_aq_start_stop_dcbx(&pf->hw, true, 12773a257a14SAnirudh Venkataramanan &dcbx_agent_status, 12783a257a14SAnirudh Venkataramanan NULL); 12793a257a14SAnirudh Venkataramanan if (status) 12804015d11eSBrett Creeley dev_dbg(dev, "Failed to start FW DCBX\n"); 12813a257a14SAnirudh Venkataramanan 12824015d11eSBrett Creeley dev_info(dev, "FW DCBX agent is %s\n", 12833a257a14SAnirudh Venkataramanan dcbx_agent_status ? "ACTIVE" : "DISABLED"); 12843a257a14SAnirudh Venkataramanan 12853a257a14SAnirudh Venkataramanan /* Failure to configure MIB change or init DCB is not 12863a257a14SAnirudh Venkataramanan * relevant to ethtool. Print notification that 12873a257a14SAnirudh Venkataramanan * registration/init failed but do not return error 12883a257a14SAnirudh Venkataramanan * state to ethtool 12893a257a14SAnirudh Venkataramanan */ 1290e223eaecSDave Ertman status = ice_init_pf_dcb(pf, true); 12913a257a14SAnirudh Venkataramanan if (status) 12924015d11eSBrett Creeley dev_dbg(dev, "Fail to init DCB\n"); 12932e0e6228SDave Ertman 12942e0e6228SDave Ertman /* Remove rule to direct LLDP packets to default VSI. 12952e0e6228SDave Ertman * The FW LLDP engine will now be consuming them. 12962e0e6228SDave Ertman */ 12972e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, false); 1298ea300f41SDave Ertman 1299ea300f41SDave Ertman /* Register for MIB change events */ 1300ea300f41SDave Ertman status = ice_cfg_lldp_mib_change(&pf->hw, true); 1301ea300f41SDave Ertman if (status) 130219cce2c6SAnirudh Venkataramanan dev_dbg(dev, "Fail to enable MIB change events\n"); 130335e93561SDave Ertman 130435e93561SDave Ertman ice_nway_reset(netdev); 13053a257a14SAnirudh Venkataramanan } 13063a257a14SAnirudh Venkataramanan } 13077237f5b0SMaciej Fijalkowski if (test_bit(ICE_FLAG_LEGACY_RX, change_flags)) { 13087237f5b0SMaciej Fijalkowski /* down and up VSI so that changes of Rx cfg are reflected. */ 13097237f5b0SMaciej Fijalkowski ice_down(vsi); 13107237f5b0SMaciej Fijalkowski ice_up(vsi); 13117237f5b0SMaciej Fijalkowski } 131201b5e89aSBrett Creeley /* don't allow modification of this flag when a single VF is in 131301b5e89aSBrett Creeley * promiscuous mode because it's not supported 131401b5e89aSBrett Creeley */ 131501b5e89aSBrett Creeley if (test_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, change_flags) && 131601b5e89aSBrett Creeley ice_is_any_vf_in_promisc(pf)) { 131701b5e89aSBrett Creeley dev_err(dev, "Changing vf-true-promisc-support flag while VF(s) are in promiscuous mode not supported\n"); 131801b5e89aSBrett Creeley /* toggle bit back to previous state */ 131901b5e89aSBrett Creeley change_bit(ICE_FLAG_VF_TRUE_PROMISC_ENA, pf->flags); 132001b5e89aSBrett Creeley ret = -EAGAIN; 132101b5e89aSBrett Creeley } 13223a257a14SAnirudh Venkataramanan clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags); 13233a257a14SAnirudh Venkataramanan return ret; 1324ab4ab73fSBruce Allan } 1325ab4ab73fSBruce Allan 1326fcea6f3dSAnirudh Venkataramanan static int ice_get_sset_count(struct net_device *netdev, int sset) 1327fcea6f3dSAnirudh Venkataramanan { 1328fcea6f3dSAnirudh Venkataramanan switch (sset) { 1329fcea6f3dSAnirudh Venkataramanan case ETH_SS_STATS: 1330f8ba7db8SJacob Keller /* The number (and order) of strings reported *must* remain 1331f8ba7db8SJacob Keller * constant for a given netdevice. This function must not 1332f8ba7db8SJacob Keller * report a different number based on run time parameters 1333f8ba7db8SJacob Keller * (such as the number of queues in use, or the setting of 1334f8ba7db8SJacob Keller * a private ethtool flag). This is due to the nature of the 1335f8ba7db8SJacob Keller * ethtool stats API. 1336f8ba7db8SJacob Keller * 1337f8ba7db8SJacob Keller * Userspace programs such as ethtool must make 3 separate 1338f8ba7db8SJacob Keller * ioctl requests, one for size, one for the strings, and 1339f8ba7db8SJacob Keller * finally one for the stats. Since these cross into 1340f8ba7db8SJacob Keller * userspace, changes to the number or size could result in 1341f8ba7db8SJacob Keller * undefined memory access or incorrect string<->value 1342f8ba7db8SJacob Keller * correlations for statistics. 1343f8ba7db8SJacob Keller * 1344f8ba7db8SJacob Keller * Even if it appears to be safe, changes to the size or 1345f8ba7db8SJacob Keller * order of strings will suffer from race conditions and are 1346f8ba7db8SJacob Keller * not safe. 1347f8ba7db8SJacob Keller */ 1348fcea6f3dSAnirudh Venkataramanan return ICE_ALL_STATS_LEN(netdev); 13490e674aebSAnirudh Venkataramanan case ETH_SS_TEST: 13500e674aebSAnirudh Venkataramanan return ICE_TEST_LEN; 1351ab4ab73fSBruce Allan case ETH_SS_PRIV_FLAGS: 1352ab4ab73fSBruce Allan return ICE_PRIV_FLAG_ARRAY_SIZE; 1353fcea6f3dSAnirudh Venkataramanan default: 1354fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 1355fcea6f3dSAnirudh Venkataramanan } 1356fcea6f3dSAnirudh Venkataramanan } 1357fcea6f3dSAnirudh Venkataramanan 1358fcea6f3dSAnirudh Venkataramanan static void 1359fcea6f3dSAnirudh Venkataramanan ice_get_ethtool_stats(struct net_device *netdev, 1360fcea6f3dSAnirudh Venkataramanan struct ethtool_stats __always_unused *stats, u64 *data) 1361fcea6f3dSAnirudh Venkataramanan { 1362fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1363fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1364fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1365fcea6f3dSAnirudh Venkataramanan struct ice_ring *ring; 13665a4a8673SBruce Allan unsigned int j; 1367fcea6f3dSAnirudh Venkataramanan int i = 0; 1368fcea6f3dSAnirudh Venkataramanan char *p; 1369fcea6f3dSAnirudh Venkataramanan 13705a4a8673SBruce Allan ice_update_pf_stats(pf); 13715a4a8673SBruce Allan ice_update_vsi_stats(vsi); 13725a4a8673SBruce Allan 1373fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_VSI_STATS_LEN; j++) { 1374fcea6f3dSAnirudh Venkataramanan p = (char *)vsi + ice_gstrings_vsi_stats[j].stat_offset; 1375fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_vsi_stats[j].sizeof_stat == 1376fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 1377fcea6f3dSAnirudh Venkataramanan } 1378fcea6f3dSAnirudh Venkataramanan 1379fcea6f3dSAnirudh Venkataramanan /* populate per queue stats */ 1380fcea6f3dSAnirudh Venkataramanan rcu_read_lock(); 1381fcea6f3dSAnirudh Venkataramanan 1382f8ba7db8SJacob Keller ice_for_each_alloc_txq(vsi, j) { 1383fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->tx_rings[j]); 1384f8ba7db8SJacob Keller if (ring) { 1385fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 1386fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 1387f8ba7db8SJacob Keller } else { 1388f8ba7db8SJacob Keller data[i++] = 0; 1389f8ba7db8SJacob Keller data[i++] = 0; 1390f8ba7db8SJacob Keller } 1391fcea6f3dSAnirudh Venkataramanan } 1392fcea6f3dSAnirudh Venkataramanan 1393f8ba7db8SJacob Keller ice_for_each_alloc_rxq(vsi, j) { 1394fcea6f3dSAnirudh Venkataramanan ring = READ_ONCE(vsi->rx_rings[j]); 1395f8ba7db8SJacob Keller if (ring) { 1396fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.pkts; 1397fcea6f3dSAnirudh Venkataramanan data[i++] = ring->stats.bytes; 1398f8ba7db8SJacob Keller } else { 1399f8ba7db8SJacob Keller data[i++] = 0; 1400f8ba7db8SJacob Keller data[i++] = 0; 1401f8ba7db8SJacob Keller } 1402fcea6f3dSAnirudh Venkataramanan } 1403fcea6f3dSAnirudh Venkataramanan 1404fcea6f3dSAnirudh Venkataramanan rcu_read_unlock(); 1405fcea6f3dSAnirudh Venkataramanan 1406fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 1407fcea6f3dSAnirudh Venkataramanan return; 1408fcea6f3dSAnirudh Venkataramanan 1409fcea6f3dSAnirudh Venkataramanan for (j = 0; j < ICE_PF_STATS_LEN; j++) { 1410fcea6f3dSAnirudh Venkataramanan p = (char *)pf + ice_gstrings_pf_stats[j].stat_offset; 1411fcea6f3dSAnirudh Venkataramanan data[i++] = (ice_gstrings_pf_stats[j].sizeof_stat == 1412fcea6f3dSAnirudh Venkataramanan sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 1413fcea6f3dSAnirudh Venkataramanan } 14144b0fdcebSAnirudh Venkataramanan 14154b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 14164b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_tx[j]; 14174b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_tx[j]; 14184b0fdcebSAnirudh Venkataramanan } 14194b0fdcebSAnirudh Venkataramanan 14204b0fdcebSAnirudh Venkataramanan for (j = 0; j < ICE_MAX_USER_PRIORITY; j++) { 14214b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xon_rx[j]; 14224b0fdcebSAnirudh Venkataramanan data[i++] = pf->stats.priority_xoff_rx[j]; 14234b0fdcebSAnirudh Venkataramanan } 1424fcea6f3dSAnirudh Venkataramanan } 1425fcea6f3dSAnirudh Venkataramanan 142648cb27f2SChinh Cao /** 142748cb27f2SChinh Cao * ice_phy_type_to_ethtool - convert the phy_types to ethtool link modes 142848cb27f2SChinh Cao * @netdev: network interface device structure 142948cb27f2SChinh Cao * @ks: ethtool link ksettings struct to fill out 143048cb27f2SChinh Cao */ 1431aef74145SAnirudh Venkataramanan static void 1432aef74145SAnirudh Venkataramanan ice_phy_type_to_ethtool(struct net_device *netdev, 1433fcea6f3dSAnirudh Venkataramanan struct ethtool_link_ksettings *ks) 1434fcea6f3dSAnirudh Venkataramanan { 1435fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 1436fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 1437aef74145SAnirudh Venkataramanan bool need_add_adv_mode = false; 1438fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 1439aef74145SAnirudh Venkataramanan u64 phy_types_high; 144048cb27f2SChinh Cao u64 phy_types_low; 1441fcea6f3dSAnirudh Venkataramanan 1442fcea6f3dSAnirudh Venkataramanan hw_link_info = &vsi->port_info->phy.link_info; 144348cb27f2SChinh Cao phy_types_low = vsi->port_info->phy.phy_type_low; 1444aef74145SAnirudh Venkataramanan phy_types_high = vsi->port_info->phy.phy_type_high; 1445fcea6f3dSAnirudh Venkataramanan 144648cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 144748cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 144848cb27f2SChinh Cao 144948cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 145048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_100M_SGMII) { 145148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 145248cb27f2SChinh Cao 100baseT_Full); 14539ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14549ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100MB) 145548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 145648cb27f2SChinh Cao 100baseT_Full); 145748cb27f2SChinh Cao } 145848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 145948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1G_SGMII) { 146048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 146148cb27f2SChinh Cao 1000baseT_Full); 14629ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14639ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 146448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 146548cb27f2SChinh Cao 1000baseT_Full); 146648cb27f2SChinh Cao } 146748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX) { 146848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 146948cb27f2SChinh Cao 1000baseKX_Full); 14709ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14719ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 147248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 147348cb27f2SChinh Cao 1000baseKX_Full); 147448cb27f2SChinh Cao } 147548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_SX || 147648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_LX) { 147748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 147848cb27f2SChinh Cao 1000baseX_Full); 14799ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14809ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_1000MB) 148148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 148248cb27f2SChinh Cao 1000baseX_Full); 148348cb27f2SChinh Cao } 148448cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T) { 148548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 148648cb27f2SChinh Cao 2500baseT_Full); 14879ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14889ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 148948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 149048cb27f2SChinh Cao 2500baseT_Full); 149148cb27f2SChinh Cao } 149248cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_X || 149348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX) { 149448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 149548cb27f2SChinh Cao 2500baseX_Full); 14969ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 14979ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_2500MB) 149848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 149948cb27f2SChinh Cao 2500baseX_Full); 150048cb27f2SChinh Cao } 150148cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 150248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR) { 150348cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 150448cb27f2SChinh Cao 5000baseT_Full); 15059ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15069ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_5GB) 150748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 150848cb27f2SChinh Cao 5000baseT_Full); 150948cb27f2SChinh Cao } 151048cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 151148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_DA || 151248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_AOC_ACC || 151348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10G_SFI_C2C) { 1514fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1515fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 15169ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15179ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 1518fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1519fcea6f3dSAnirudh Venkataramanan 10000baseT_Full); 152048cb27f2SChinh Cao } 152148cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1) { 152248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 152348cb27f2SChinh Cao 10000baseKR_Full); 15249ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15259ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 152648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 152748cb27f2SChinh Cao 10000baseKR_Full); 152848cb27f2SChinh Cao } 152948cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_SR) { 153048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 153148cb27f2SChinh Cao 10000baseSR_Full); 15329ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15339ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 153448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 153548cb27f2SChinh Cao 10000baseSR_Full); 153648cb27f2SChinh Cao } 153748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_LR) { 153848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 153948cb27f2SChinh Cao 10000baseLR_Full); 15409ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15419ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_10GB) 154248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 154348cb27f2SChinh Cao 10000baseLR_Full); 154448cb27f2SChinh Cao } 154548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 154648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 154748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 154848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 154948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_AOC_ACC || 155048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25G_AUI_C2C) { 155148cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 155248cb27f2SChinh Cao 25000baseCR_Full); 15539ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15549ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 155548cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 155648cb27f2SChinh Cao 25000baseCR_Full); 155748cb27f2SChinh Cao } 155848cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_SR || 155948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_LR) { 156048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 156148cb27f2SChinh Cao 25000baseSR_Full); 15629ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15639ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 156448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 156548cb27f2SChinh Cao 25000baseSR_Full); 156648cb27f2SChinh Cao } 156748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 156848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 156948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1) { 157048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 157148cb27f2SChinh Cao 25000baseKR_Full); 15729ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15739ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_25GB) 157448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 157548cb27f2SChinh Cao 25000baseKR_Full); 157648cb27f2SChinh Cao } 157748cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 157848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 157948cb27f2SChinh Cao 40000baseKR4_Full); 15809ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15819ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 158248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 158348cb27f2SChinh Cao 40000baseKR4_Full); 158448cb27f2SChinh Cao } 158548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 158648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI_AOC_ACC || 158748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40G_XLAUI) { 158848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 158948cb27f2SChinh Cao 40000baseCR4_Full); 15909ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15919ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 159248cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 159348cb27f2SChinh Cao 40000baseCR4_Full); 159448cb27f2SChinh Cao } 159548cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_SR4) { 159648cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 159748cb27f2SChinh Cao 40000baseSR4_Full); 15989ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 15999ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 160048cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 160148cb27f2SChinh Cao 40000baseSR4_Full); 160248cb27f2SChinh Cao } 160348cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_LR4) { 160448cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 160548cb27f2SChinh Cao 40000baseLR4_Full); 16069ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16079ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_40GB) 160848cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 160948cb27f2SChinh Cao 40000baseLR4_Full); 161048cb27f2SChinh Cao } 1611aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 1612aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC || 1613aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_LAUI2 || 1614aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC || 1615aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI2 || 1616aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 1617aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR || 1618aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC || 1619aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50G_AUI1) { 1620aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1621aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 16229ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16239ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1624aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1625aef74145SAnirudh Venkataramanan 50000baseCR2_Full); 1626aef74145SAnirudh Venkataramanan } 1627aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 1628aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 1629aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1630aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 16319ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16329ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1633aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1634aef74145SAnirudh Venkataramanan 50000baseKR2_Full); 1635aef74145SAnirudh Venkataramanan } 1636aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_SR2 || 1637aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR2 || 1638aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_FR || 1639aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_LR) { 1640aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1641aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 16429ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16439ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_50GB) 1644aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1645aef74145SAnirudh Venkataramanan 50000baseSR2_Full); 1646aef74145SAnirudh Venkataramanan } 1647aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 1648aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC || 1649aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_CAUI4 || 1650aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC || 1651aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100G_AUI4 || 1652aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4 || 1653aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2 || 1654aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC || 1655aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_CAUI2 || 1656aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC || 1657aef74145SAnirudh Venkataramanan phy_types_high & ICE_PHY_TYPE_HIGH_100G_AUI2) { 1658aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1659aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 16609ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16619ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1662aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1663aef74145SAnirudh Venkataramanan } 1664aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1665aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1666aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1667aef74145SAnirudh Venkataramanan 100000baseCR4_Full); 1668aef74145SAnirudh Venkataramanan } 1669aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR4 || 1670aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_SR2) { 1671aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1672aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 16739ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16749ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1675aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1676aef74145SAnirudh Venkataramanan } 1677aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1678aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1679aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1680aef74145SAnirudh Venkataramanan 100000baseSR4_Full); 1681aef74145SAnirudh Venkataramanan } 1682aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_LR4 || 1683aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_DR) { 1684aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1685aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 16869ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 16879ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1688aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1689aef74145SAnirudh Venkataramanan } 1690aef74145SAnirudh Venkataramanan if (need_add_adv_mode) { 1691aef74145SAnirudh Venkataramanan need_add_adv_mode = false; 1692aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1693aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full); 1694aef74145SAnirudh Venkataramanan } 1695aef74145SAnirudh Venkataramanan if (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_high & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) { 1698aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1699aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 17009ccb062cSTony Nguyen if (!hw_link_info->req_speeds || 17019ccb062cSTony Nguyen hw_link_info->req_speeds & ICE_AQ_LINK_SPEED_100GB) 1702aef74145SAnirudh Venkataramanan need_add_adv_mode = true; 1703aef74145SAnirudh Venkataramanan } 1704aef74145SAnirudh Venkataramanan if (need_add_adv_mode) 1705aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1706aef74145SAnirudh Venkataramanan 100000baseKR4_Full); 1707fcea6f3dSAnirudh Venkataramanan 170848cb27f2SChinh Cao /* Autoneg PHY types */ 170948cb27f2SChinh Cao if (phy_types_low & ICE_PHY_TYPE_LOW_100BASE_TX || 171048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_T || 171148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_1000BASE_KX || 171248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_T || 171348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_2500BASE_KX || 171448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_T || 171548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_5GBASE_KR || 171648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_T || 171748cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_10GBASE_KR_CR1 || 171848cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_T || 171948cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR || 172048cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR_S || 172148cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_CR1 || 172248cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR || 172348cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR_S || 172448cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_25GBASE_KR1 || 172548cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_CR4 || 172648cb27f2SChinh Cao phy_types_low & ICE_PHY_TYPE_LOW_40GBASE_KR4) { 172748cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, supported, 172848cb27f2SChinh Cao Autoneg); 172948cb27f2SChinh Cao ethtool_link_ksettings_add_link_mode(ks, advertising, 173048cb27f2SChinh Cao Autoneg); 173148cb27f2SChinh Cao } 1732aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CR2 || 1733aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR2 || 1734aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_CP || 1735aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) { 1736aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1737aef74145SAnirudh Venkataramanan Autoneg); 1738aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1739aef74145SAnirudh Venkataramanan Autoneg); 1740aef74145SAnirudh Venkataramanan } 1741aef74145SAnirudh Venkataramanan if (phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CR4 || 1742aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR4 || 1743aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4 || 1744aef74145SAnirudh Venkataramanan phy_types_low & ICE_PHY_TYPE_LOW_100GBASE_CP2) { 1745aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, 1746aef74145SAnirudh Venkataramanan Autoneg); 1747aef74145SAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1748aef74145SAnirudh Venkataramanan Autoneg); 1749aef74145SAnirudh Venkataramanan } 175048cb27f2SChinh Cao } 175148cb27f2SChinh Cao 175248cb27f2SChinh Cao #define TEST_SET_BITS_TIMEOUT 50 175348cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MAX 2000 175448cb27f2SChinh Cao #define TEST_SET_BITS_SLEEP_MIN 1000 175548cb27f2SChinh Cao 175648cb27f2SChinh Cao /** 175748cb27f2SChinh Cao * ice_get_settings_link_up - Get Link settings for when link is up 175848cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 175948cb27f2SChinh Cao * @netdev: network interface device structure 176048cb27f2SChinh Cao */ 1761aef74145SAnirudh Venkataramanan static void 1762aef74145SAnirudh Venkataramanan ice_get_settings_link_up(struct ethtool_link_ksettings *ks, 176348cb27f2SChinh Cao struct net_device *netdev) 176448cb27f2SChinh Cao { 176548cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 17665a056cd7SPaul Greenwalt struct ice_port_info *pi = np->vsi->port_info; 176748cb27f2SChinh Cao struct ice_link_status *link_info; 176848cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 176948cb27f2SChinh Cao 177048cb27f2SChinh Cao link_info = &vsi->port_info->phy.link_info; 177148cb27f2SChinh Cao 1772ad9a87beSPaul Greenwalt /* Get supported and advertised settings from PHY ability with media */ 1773ad9a87beSPaul Greenwalt ice_phy_type_to_ethtool(netdev, ks); 177448cb27f2SChinh Cao 177548cb27f2SChinh Cao switch (link_info->link_speed) { 1776aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_100GB: 1777aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_100000; 1778aef74145SAnirudh Venkataramanan break; 1779aef74145SAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_50GB: 1780aef74145SAnirudh Venkataramanan ks->base.speed = SPEED_50000; 1781aef74145SAnirudh Venkataramanan break; 178248cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_40GB: 178348cb27f2SChinh Cao ks->base.speed = SPEED_40000; 1784fcea6f3dSAnirudh Venkataramanan break; 1785fcea6f3dSAnirudh Venkataramanan case ICE_AQ_LINK_SPEED_25GB: 1786fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_25000; 1787fcea6f3dSAnirudh Venkataramanan break; 178848cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_20GB: 178948cb27f2SChinh Cao ks->base.speed = SPEED_20000; 179048cb27f2SChinh Cao break; 179148cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_10GB: 179248cb27f2SChinh Cao ks->base.speed = SPEED_10000; 179348cb27f2SChinh Cao break; 179448cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_5GB: 179548cb27f2SChinh Cao ks->base.speed = SPEED_5000; 179648cb27f2SChinh Cao break; 179748cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_2500MB: 179848cb27f2SChinh Cao ks->base.speed = SPEED_2500; 179948cb27f2SChinh Cao break; 180048cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_1000MB: 180148cb27f2SChinh Cao ks->base.speed = SPEED_1000; 180248cb27f2SChinh Cao break; 180348cb27f2SChinh Cao case ICE_AQ_LINK_SPEED_100MB: 180448cb27f2SChinh Cao ks->base.speed = SPEED_100; 1805fcea6f3dSAnirudh Venkataramanan break; 1806fcea6f3dSAnirudh Venkataramanan default: 180719cce2c6SAnirudh Venkataramanan netdev_info(netdev, "WARNING: Unrecognized link_speed (0x%x).\n", 180848cb27f2SChinh Cao link_info->link_speed); 1809fcea6f3dSAnirudh Venkataramanan break; 1810fcea6f3dSAnirudh Venkataramanan } 1811fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_FULL; 18125a056cd7SPaul Greenwalt 18135a056cd7SPaul Greenwalt if (link_info->an_info & ICE_AQ_AN_COMPLETED) 18145a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, lp_advertising, 18155a056cd7SPaul Greenwalt Autoneg); 18165a056cd7SPaul Greenwalt 18175a056cd7SPaul Greenwalt /* Set flow control negotiated Rx/Tx pause */ 18185a056cd7SPaul Greenwalt switch (pi->fc.current_mode) { 18195a056cd7SPaul Greenwalt case ICE_FC_FULL: 18205a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, lp_advertising, Pause); 18215a056cd7SPaul Greenwalt break; 18225a056cd7SPaul Greenwalt case ICE_FC_TX_PAUSE: 18235a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, lp_advertising, Pause); 18245a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, lp_advertising, 18255a056cd7SPaul Greenwalt Asym_Pause); 18265a056cd7SPaul Greenwalt break; 18275a056cd7SPaul Greenwalt case ICE_FC_RX_PAUSE: 18285a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, lp_advertising, 18295a056cd7SPaul Greenwalt Asym_Pause); 18305a056cd7SPaul Greenwalt break; 18315a056cd7SPaul Greenwalt case ICE_FC_PFC: 18325a056cd7SPaul Greenwalt default: 18335a056cd7SPaul Greenwalt ethtool_link_ksettings_del_link_mode(ks, lp_advertising, Pause); 18345a056cd7SPaul Greenwalt ethtool_link_ksettings_del_link_mode(ks, lp_advertising, 18355a056cd7SPaul Greenwalt Asym_Pause); 18365a056cd7SPaul Greenwalt break; 18375a056cd7SPaul Greenwalt } 183848cb27f2SChinh Cao } 183948cb27f2SChinh Cao 184048cb27f2SChinh Cao /** 184148cb27f2SChinh Cao * ice_get_settings_link_down - Get the Link settings when link is down 184248cb27f2SChinh Cao * @ks: ethtool ksettings to fill in 184348cb27f2SChinh Cao * @netdev: network interface device structure 184448cb27f2SChinh Cao * 184548cb27f2SChinh Cao * Reports link settings that can be determined when link is down 184648cb27f2SChinh Cao */ 184748cb27f2SChinh Cao static void 184848cb27f2SChinh Cao ice_get_settings_link_down(struct ethtool_link_ksettings *ks, 1849a03499d6STony Nguyen struct net_device *netdev) 185048cb27f2SChinh Cao { 185148cb27f2SChinh Cao /* link is down and the driver needs to fall back on 1852f9867df6SAnirudh Venkataramanan * supported PHY types to figure out what info to display 185348cb27f2SChinh Cao */ 185448cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, ks); 185548cb27f2SChinh Cao 185648cb27f2SChinh Cao /* With no link, speed and duplex are unknown */ 1857fcea6f3dSAnirudh Venkataramanan ks->base.speed = SPEED_UNKNOWN; 1858fcea6f3dSAnirudh Venkataramanan ks->base.duplex = DUPLEX_UNKNOWN; 1859fcea6f3dSAnirudh Venkataramanan } 1860fcea6f3dSAnirudh Venkataramanan 186148cb27f2SChinh Cao /** 186248cb27f2SChinh Cao * ice_get_link_ksettings - Get Link Speed and Duplex settings 186348cb27f2SChinh Cao * @netdev: network interface device structure 186448cb27f2SChinh Cao * @ks: ethtool ksettings 186548cb27f2SChinh Cao * 186648cb27f2SChinh Cao * Reports speed/duplex settings based on media_type 186748cb27f2SChinh Cao */ 1868c8b7abddSBruce Allan static int 1869c8b7abddSBruce Allan ice_get_link_ksettings(struct net_device *netdev, 187048cb27f2SChinh Cao struct ethtool_link_ksettings *ks) 187148cb27f2SChinh Cao { 187248cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 1873f776b3acSPaul Greenwalt struct ice_aqc_get_phy_caps_data *caps; 187448cb27f2SChinh Cao struct ice_link_status *hw_link_info; 187548cb27f2SChinh Cao struct ice_vsi *vsi = np->vsi; 18765a056cd7SPaul Greenwalt enum ice_status status; 18775a056cd7SPaul Greenwalt int err = 0; 187848cb27f2SChinh Cao 187948cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, supported); 188048cb27f2SChinh Cao ethtool_link_ksettings_zero_link_mode(ks, advertising); 18815a056cd7SPaul Greenwalt ethtool_link_ksettings_zero_link_mode(ks, lp_advertising); 188248cb27f2SChinh Cao hw_link_info = &vsi->port_info->phy.link_info; 188348cb27f2SChinh Cao 188448cb27f2SChinh Cao /* set speed and duplex */ 188548cb27f2SChinh Cao if (hw_link_info->link_info & ICE_AQ_LINK_UP) 188648cb27f2SChinh Cao ice_get_settings_link_up(ks, netdev); 188748cb27f2SChinh Cao else 188848cb27f2SChinh Cao ice_get_settings_link_down(ks, netdev); 188948cb27f2SChinh Cao 1890fcea6f3dSAnirudh Venkataramanan /* set autoneg settings */ 189148cb27f2SChinh Cao ks->base.autoneg = (hw_link_info->an_info & ICE_AQ_AN_COMPLETED) ? 189248cb27f2SChinh Cao AUTONEG_ENABLE : AUTONEG_DISABLE; 1893fcea6f3dSAnirudh Venkataramanan 1894fcea6f3dSAnirudh Venkataramanan /* set media type settings */ 1895fcea6f3dSAnirudh Venkataramanan switch (vsi->port_info->phy.media_type) { 1896fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_FIBER: 1897fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 1898fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_FIBRE; 1899fcea6f3dSAnirudh Venkataramanan break; 1900fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BASET: 1901fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, TP); 1902fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, TP); 1903fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_TP; 1904fcea6f3dSAnirudh Venkataramanan break; 1905fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_BACKPLANE: 1906fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); 1907fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Backplane); 1908fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); 1909fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1910fcea6f3dSAnirudh Venkataramanan Backplane); 1911fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_NONE; 1912fcea6f3dSAnirudh Venkataramanan break; 1913fcea6f3dSAnirudh Venkataramanan case ICE_MEDIA_DA: 1914fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); 1915fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE); 1916fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_DA; 1917fcea6f3dSAnirudh Venkataramanan break; 1918fcea6f3dSAnirudh Venkataramanan default: 1919fcea6f3dSAnirudh Venkataramanan ks->base.port = PORT_OTHER; 1920fcea6f3dSAnirudh Venkataramanan break; 1921fcea6f3dSAnirudh Venkataramanan } 1922fcea6f3dSAnirudh Venkataramanan 1923fcea6f3dSAnirudh Venkataramanan /* flow control is symmetric and always supported */ 1924fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, supported, Pause); 1925fcea6f3dSAnirudh Venkataramanan 19269efe35d0STony Nguyen caps = kzalloc(sizeof(*caps), GFP_KERNEL); 19275a056cd7SPaul Greenwalt if (!caps) 19285a056cd7SPaul Greenwalt return -ENOMEM; 19295a056cd7SPaul Greenwalt 19305a056cd7SPaul Greenwalt status = ice_aq_get_phy_caps(vsi->port_info, false, 19315a056cd7SPaul Greenwalt ICE_AQC_REPORT_SW_CFG, caps, NULL); 19325a056cd7SPaul Greenwalt if (status) { 19335a056cd7SPaul Greenwalt err = -EIO; 19345a056cd7SPaul Greenwalt goto done; 19355a056cd7SPaul Greenwalt } 19365a056cd7SPaul Greenwalt 19375a056cd7SPaul Greenwalt /* Set the advertised flow control based on the PHY capability */ 19385a056cd7SPaul Greenwalt if ((caps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) && 19395a056cd7SPaul Greenwalt (caps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE)) { 1940fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 1941fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_add_link_mode(ks, advertising, 1942fcea6f3dSAnirudh Venkataramanan Asym_Pause); 19435a056cd7SPaul Greenwalt } else if (caps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) { 19445a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, 19455a056cd7SPaul Greenwalt Asym_Pause); 19465a056cd7SPaul Greenwalt } else if (caps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) { 19475a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); 19485a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, 19495a056cd7SPaul Greenwalt Asym_Pause); 19505a056cd7SPaul Greenwalt } else { 1951fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, Pause); 1952fcea6f3dSAnirudh Venkataramanan ethtool_link_ksettings_del_link_mode(ks, advertising, 1953fcea6f3dSAnirudh Venkataramanan Asym_Pause); 1954fcea6f3dSAnirudh Venkataramanan } 1955fcea6f3dSAnirudh Venkataramanan 1956f776b3acSPaul Greenwalt /* Set advertised FEC modes based on PHY capability */ 1957f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_NONE); 1958f776b3acSPaul Greenwalt 1959f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ || 1960f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_REQ) 1961f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, 1962f776b3acSPaul Greenwalt FEC_BASER); 1963f776b3acSPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_528_REQ || 1964f776b3acSPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_544_REQ) 1965f776b3acSPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS); 1966f776b3acSPaul Greenwalt 19675a056cd7SPaul Greenwalt status = ice_aq_get_phy_caps(vsi->port_info, false, 19685a056cd7SPaul Greenwalt ICE_AQC_REPORT_TOPO_CAP, caps, NULL); 19695a056cd7SPaul Greenwalt if (status) { 19705a056cd7SPaul Greenwalt err = -EIO; 19715a056cd7SPaul Greenwalt goto done; 19725a056cd7SPaul Greenwalt } 19735a056cd7SPaul Greenwalt 19745a056cd7SPaul Greenwalt /* Set supported FEC modes based on PHY capability */ 19755a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, supported, FEC_NONE); 19765a056cd7SPaul Greenwalt 19775a056cd7SPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_EN || 19785a056cd7SPaul Greenwalt caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_CLAUSE74_EN) 19795a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER); 19805a056cd7SPaul Greenwalt if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_CLAUSE91_EN) 19815a056cd7SPaul Greenwalt ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS); 19825a056cd7SPaul Greenwalt 1983f776b3acSPaul Greenwalt done: 19849efe35d0STony Nguyen kfree(caps); 19855a056cd7SPaul Greenwalt return err; 1986fcea6f3dSAnirudh Venkataramanan } 1987fcea6f3dSAnirudh Venkataramanan 1988fcea6f3dSAnirudh Venkataramanan /** 198948cb27f2SChinh Cao * ice_ksettings_find_adv_link_speed - Find advertising link speed 199048cb27f2SChinh Cao * @ks: ethtool ksettings 199148cb27f2SChinh Cao */ 199248cb27f2SChinh Cao static u16 199348cb27f2SChinh Cao ice_ksettings_find_adv_link_speed(const struct ethtool_link_ksettings *ks) 199448cb27f2SChinh Cao { 199548cb27f2SChinh Cao u16 adv_link_speed = 0; 199648cb27f2SChinh Cao 199748cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 199848cb27f2SChinh Cao 100baseT_Full)) 199948cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_100MB; 200048cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 200148cb27f2SChinh Cao 1000baseX_Full)) 200248cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 200348cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 200448cb27f2SChinh Cao 1000baseT_Full) || 200548cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 200648cb27f2SChinh Cao 1000baseKX_Full)) 200748cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_1000MB; 200848cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 200948cb27f2SChinh Cao 2500baseT_Full)) 201048cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 201148cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 201248cb27f2SChinh Cao 2500baseX_Full)) 201348cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_2500MB; 201448cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 201548cb27f2SChinh Cao 5000baseT_Full)) 201648cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_5GB; 201748cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 201848cb27f2SChinh Cao 10000baseT_Full) || 201948cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 202048cb27f2SChinh Cao 10000baseKR_Full)) 202148cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 202248cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 202348cb27f2SChinh Cao 10000baseSR_Full) || 202448cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 202548cb27f2SChinh Cao 10000baseLR_Full)) 202648cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_10GB; 202748cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 202848cb27f2SChinh Cao 25000baseCR_Full) || 202948cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 203048cb27f2SChinh Cao 25000baseSR_Full) || 203148cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 203248cb27f2SChinh Cao 25000baseKR_Full)) 203348cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_25GB; 203448cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, advertising, 203548cb27f2SChinh Cao 40000baseCR4_Full) || 203648cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 203748cb27f2SChinh Cao 40000baseSR4_Full) || 203848cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 203948cb27f2SChinh Cao 40000baseLR4_Full) || 204048cb27f2SChinh Cao ethtool_link_ksettings_test_link_mode(ks, advertising, 204148cb27f2SChinh Cao 40000baseKR4_Full)) 204248cb27f2SChinh Cao adv_link_speed |= ICE_AQ_LINK_SPEED_40GB; 2043aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2044aef74145SAnirudh Venkataramanan 50000baseCR2_Full) || 2045aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2046aef74145SAnirudh Venkataramanan 50000baseKR2_Full)) 2047aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 2048aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2049aef74145SAnirudh Venkataramanan 50000baseSR2_Full)) 2050aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_50GB; 2051aef74145SAnirudh Venkataramanan if (ethtool_link_ksettings_test_link_mode(ks, advertising, 2052aef74145SAnirudh Venkataramanan 100000baseCR4_Full) || 2053aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2054aef74145SAnirudh Venkataramanan 100000baseSR4_Full) || 2055aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2056aef74145SAnirudh Venkataramanan 100000baseLR4_ER4_Full) || 2057aef74145SAnirudh Venkataramanan ethtool_link_ksettings_test_link_mode(ks, advertising, 2058aef74145SAnirudh Venkataramanan 100000baseKR4_Full)) 2059aef74145SAnirudh Venkataramanan adv_link_speed |= ICE_AQ_LINK_SPEED_100GB; 206048cb27f2SChinh Cao 206148cb27f2SChinh Cao return adv_link_speed; 206248cb27f2SChinh Cao } 206348cb27f2SChinh Cao 206448cb27f2SChinh Cao /** 206548cb27f2SChinh Cao * ice_setup_autoneg 206648cb27f2SChinh Cao * @p: port info 206748cb27f2SChinh Cao * @ks: ethtool_link_ksettings 206848cb27f2SChinh Cao * @config: configuration that will be sent down to FW 206948cb27f2SChinh Cao * @autoneg_enabled: autonegotiation is enabled or not 207048cb27f2SChinh Cao * @autoneg_changed: will there a change in autonegotiation 207148cb27f2SChinh Cao * @netdev: network interface device structure 207248cb27f2SChinh Cao * 207348cb27f2SChinh Cao * Setup PHY autonegotiation feature 207448cb27f2SChinh Cao */ 207548cb27f2SChinh Cao static int 207648cb27f2SChinh Cao ice_setup_autoneg(struct ice_port_info *p, struct ethtool_link_ksettings *ks, 207748cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data *config, 207848cb27f2SChinh Cao u8 autoneg_enabled, u8 *autoneg_changed, 207948cb27f2SChinh Cao struct net_device *netdev) 208048cb27f2SChinh Cao { 208148cb27f2SChinh Cao int err = 0; 208248cb27f2SChinh Cao 208348cb27f2SChinh Cao *autoneg_changed = 0; 208448cb27f2SChinh Cao 208548cb27f2SChinh Cao /* Check autoneg */ 208648cb27f2SChinh Cao if (autoneg_enabled == AUTONEG_ENABLE) { 208748cb27f2SChinh Cao /* If autoneg was not already enabled */ 208848cb27f2SChinh Cao if (!(p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED)) { 208948cb27f2SChinh Cao /* If autoneg is not supported, return error */ 209048cb27f2SChinh Cao if (!ethtool_link_ksettings_test_link_mode(ks, 209148cb27f2SChinh Cao supported, 209248cb27f2SChinh Cao Autoneg)) { 209348cb27f2SChinh Cao netdev_info(netdev, "Autoneg not supported on this phy.\n"); 209448cb27f2SChinh Cao err = -EINVAL; 209548cb27f2SChinh Cao } else { 209648cb27f2SChinh Cao /* Autoneg is allowed to change */ 209748cb27f2SChinh Cao config->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 209848cb27f2SChinh Cao *autoneg_changed = 1; 209948cb27f2SChinh Cao } 210048cb27f2SChinh Cao } 210148cb27f2SChinh Cao } else { 210248cb27f2SChinh Cao /* If autoneg is currently enabled */ 210348cb27f2SChinh Cao if (p->phy.link_info.an_info & ICE_AQ_AN_COMPLETED) { 2104f9867df6SAnirudh Venkataramanan /* If autoneg is supported 10GBASE_T is the only PHY 210548cb27f2SChinh Cao * that can disable it, so otherwise return error 210648cb27f2SChinh Cao */ 210748cb27f2SChinh Cao if (ethtool_link_ksettings_test_link_mode(ks, 210848cb27f2SChinh Cao supported, 210948cb27f2SChinh Cao Autoneg)) { 211048cb27f2SChinh Cao netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); 211148cb27f2SChinh Cao err = -EINVAL; 211248cb27f2SChinh Cao } else { 211348cb27f2SChinh Cao /* Autoneg is allowed to change */ 211448cb27f2SChinh Cao config->caps &= ~ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 211548cb27f2SChinh Cao *autoneg_changed = 1; 211648cb27f2SChinh Cao } 211748cb27f2SChinh Cao } 211848cb27f2SChinh Cao } 211948cb27f2SChinh Cao 212048cb27f2SChinh Cao return err; 212148cb27f2SChinh Cao } 212248cb27f2SChinh Cao 212348cb27f2SChinh Cao /** 212448cb27f2SChinh Cao * ice_set_link_ksettings - Set Speed and Duplex 212548cb27f2SChinh Cao * @netdev: network interface device structure 212648cb27f2SChinh Cao * @ks: ethtool ksettings 212748cb27f2SChinh Cao * 212848cb27f2SChinh Cao * Set speed/duplex per media_types advertised/forced 212948cb27f2SChinh Cao */ 2130aef74145SAnirudh Venkataramanan static int 2131aef74145SAnirudh Venkataramanan ice_set_link_ksettings(struct net_device *netdev, 213248cb27f2SChinh Cao const struct ethtool_link_ksettings *ks) 213348cb27f2SChinh Cao { 213448cb27f2SChinh Cao u8 autoneg, timeout = TEST_SET_BITS_TIMEOUT, lport = 0; 213548cb27f2SChinh Cao struct ice_netdev_priv *np = netdev_priv(netdev); 213648cb27f2SChinh Cao struct ethtool_link_ksettings safe_ks, copy_ks; 213748cb27f2SChinh Cao struct ice_aqc_get_phy_caps_data *abilities; 213848cb27f2SChinh Cao u16 adv_link_speed, curr_link_speed, idx; 213948cb27f2SChinh Cao struct ice_aqc_set_phy_cfg_data config; 214048cb27f2SChinh Cao struct ice_pf *pf = np->vsi->back; 214148cb27f2SChinh Cao struct ice_port_info *p; 214248cb27f2SChinh Cao u8 autoneg_changed = 0; 214348cb27f2SChinh Cao enum ice_status status; 2144aef74145SAnirudh Venkataramanan u64 phy_type_high; 214548cb27f2SChinh Cao u64 phy_type_low; 214648cb27f2SChinh Cao int err = 0; 214748cb27f2SChinh Cao bool linkup; 214848cb27f2SChinh Cao 214948cb27f2SChinh Cao p = np->vsi->port_info; 215048cb27f2SChinh Cao 215148cb27f2SChinh Cao if (!p) 215248cb27f2SChinh Cao return -EOPNOTSUPP; 215348cb27f2SChinh Cao 2154f9867df6SAnirudh Venkataramanan /* Check if this is LAN VSI */ 215580ed404aSBrett Creeley ice_for_each_vsi(pf, idx) 215648cb27f2SChinh Cao if (pf->vsi[idx]->type == ICE_VSI_PF) { 215748cb27f2SChinh Cao if (np->vsi != pf->vsi[idx]) 215848cb27f2SChinh Cao return -EOPNOTSUPP; 215948cb27f2SChinh Cao break; 216048cb27f2SChinh Cao } 216148cb27f2SChinh Cao 216248cb27f2SChinh Cao if (p->phy.media_type != ICE_MEDIA_BASET && 216348cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_FIBER && 216448cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_BACKPLANE && 216548cb27f2SChinh Cao p->phy.media_type != ICE_MEDIA_DA && 216648cb27f2SChinh Cao p->phy.link_info.link_info & ICE_AQ_LINK_UP) 216748cb27f2SChinh Cao return -EOPNOTSUPP; 216848cb27f2SChinh Cao 216948cb27f2SChinh Cao /* copy the ksettings to copy_ks to avoid modifying the original */ 2170c6dfd690SBruce Allan memcpy(©_ks, ks, sizeof(copy_ks)); 217148cb27f2SChinh Cao 217248cb27f2SChinh Cao /* save autoneg out of ksettings */ 217348cb27f2SChinh Cao autoneg = copy_ks.base.autoneg; 217448cb27f2SChinh Cao 217548cb27f2SChinh Cao memset(&safe_ks, 0, sizeof(safe_ks)); 217648cb27f2SChinh Cao 217748cb27f2SChinh Cao /* Get link modes supported by hardware.*/ 217848cb27f2SChinh Cao ice_phy_type_to_ethtool(netdev, &safe_ks); 217948cb27f2SChinh Cao 218048cb27f2SChinh Cao /* and check against modes requested by user. 218148cb27f2SChinh Cao * Return an error if unsupported mode was set. 218248cb27f2SChinh Cao */ 218348cb27f2SChinh Cao if (!bitmap_subset(copy_ks.link_modes.advertising, 218448cb27f2SChinh Cao safe_ks.link_modes.supported, 218548cb27f2SChinh Cao __ETHTOOL_LINK_MODE_MASK_NBITS)) 218648cb27f2SChinh Cao return -EINVAL; 218748cb27f2SChinh Cao 218848cb27f2SChinh Cao /* get our own copy of the bits to check against */ 2189c6dfd690SBruce Allan memset(&safe_ks, 0, sizeof(safe_ks)); 219048cb27f2SChinh Cao safe_ks.base.cmd = copy_ks.base.cmd; 219148cb27f2SChinh Cao safe_ks.base.link_mode_masks_nwords = 219248cb27f2SChinh Cao copy_ks.base.link_mode_masks_nwords; 219348cb27f2SChinh Cao ice_get_link_ksettings(netdev, &safe_ks); 219448cb27f2SChinh Cao 219548cb27f2SChinh Cao /* set autoneg back to what it currently is */ 219648cb27f2SChinh Cao copy_ks.base.autoneg = safe_ks.base.autoneg; 219748cb27f2SChinh Cao /* we don't compare the speed */ 219848cb27f2SChinh Cao copy_ks.base.speed = safe_ks.base.speed; 219948cb27f2SChinh Cao 220048cb27f2SChinh Cao /* If copy_ks.base and safe_ks.base are not the same now, then they are 220148cb27f2SChinh Cao * trying to set something that we do not support. 220248cb27f2SChinh Cao */ 2203c6dfd690SBruce Allan if (memcmp(©_ks.base, &safe_ks.base, sizeof(copy_ks.base))) 220448cb27f2SChinh Cao return -EOPNOTSUPP; 220548cb27f2SChinh Cao 220648cb27f2SChinh Cao while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 220748cb27f2SChinh Cao timeout--; 220848cb27f2SChinh Cao if (!timeout) 220948cb27f2SChinh Cao return -EBUSY; 221048cb27f2SChinh Cao usleep_range(TEST_SET_BITS_SLEEP_MIN, TEST_SET_BITS_SLEEP_MAX); 221148cb27f2SChinh Cao } 221248cb27f2SChinh Cao 22139efe35d0STony Nguyen abilities = kzalloc(sizeof(*abilities), GFP_KERNEL); 221448cb27f2SChinh Cao if (!abilities) 221548cb27f2SChinh Cao return -ENOMEM; 221648cb27f2SChinh Cao 2217f9867df6SAnirudh Venkataramanan /* Get the current PHY config */ 221848cb27f2SChinh Cao status = ice_aq_get_phy_caps(p, false, ICE_AQC_REPORT_SW_CFG, abilities, 221948cb27f2SChinh Cao NULL); 222048cb27f2SChinh Cao if (status) { 222148cb27f2SChinh Cao err = -EAGAIN; 222248cb27f2SChinh Cao goto done; 222348cb27f2SChinh Cao } 222448cb27f2SChinh Cao 222548cb27f2SChinh Cao /* Copy abilities to config in case autoneg is not set below */ 2226c6dfd690SBruce Allan memset(&config, 0, sizeof(config)); 222748cb27f2SChinh Cao config.caps = abilities->caps & ~ICE_AQC_PHY_AN_MODE; 222848cb27f2SChinh Cao if (abilities->caps & ICE_AQC_PHY_AN_MODE) 222948cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT; 223048cb27f2SChinh Cao 223148cb27f2SChinh Cao /* Check autoneg */ 223248cb27f2SChinh Cao err = ice_setup_autoneg(p, &safe_ks, &config, autoneg, &autoneg_changed, 223348cb27f2SChinh Cao netdev); 223448cb27f2SChinh Cao 223548cb27f2SChinh Cao if (err) 223648cb27f2SChinh Cao goto done; 223748cb27f2SChinh Cao 223848cb27f2SChinh Cao /* Call to get the current link speed */ 223948cb27f2SChinh Cao p->phy.get_link_info = true; 224048cb27f2SChinh Cao status = ice_get_link_status(p, &linkup); 224148cb27f2SChinh Cao if (status) { 224248cb27f2SChinh Cao err = -EAGAIN; 224348cb27f2SChinh Cao goto done; 224448cb27f2SChinh Cao } 224548cb27f2SChinh Cao 224648cb27f2SChinh Cao curr_link_speed = p->phy.link_info.link_speed; 224748cb27f2SChinh Cao adv_link_speed = ice_ksettings_find_adv_link_speed(ks); 224848cb27f2SChinh Cao 224948cb27f2SChinh Cao /* If speed didn't get set, set it to what it currently is. 225048cb27f2SChinh Cao * This is needed because if advertise is 0 (as it is when autoneg 225148cb27f2SChinh Cao * is disabled) then speed won't get set. 225248cb27f2SChinh Cao */ 225348cb27f2SChinh Cao if (!adv_link_speed) 225448cb27f2SChinh Cao adv_link_speed = curr_link_speed; 225548cb27f2SChinh Cao 225648cb27f2SChinh Cao /* Convert the advertise link speeds to their corresponded PHY_TYPE */ 2257aef74145SAnirudh Venkataramanan ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed); 225848cb27f2SChinh Cao 225948cb27f2SChinh Cao if (!autoneg_changed && adv_link_speed == curr_link_speed) { 226048cb27f2SChinh Cao netdev_info(netdev, "Nothing changed, exiting without setting anything.\n"); 226148cb27f2SChinh Cao goto done; 226248cb27f2SChinh Cao } 226348cb27f2SChinh Cao 226448cb27f2SChinh Cao /* copy over the rest of the abilities */ 226548cb27f2SChinh Cao config.low_power_ctrl = abilities->low_power_ctrl; 226648cb27f2SChinh Cao config.eee_cap = abilities->eee_cap; 226748cb27f2SChinh Cao config.eeer_value = abilities->eeer_value; 226848cb27f2SChinh Cao config.link_fec_opt = abilities->link_fec_options; 226948cb27f2SChinh Cao 227048cb27f2SChinh Cao /* save the requested speeds */ 227148cb27f2SChinh Cao p->phy.link_info.req_speeds = adv_link_speed; 227248cb27f2SChinh Cao 227348cb27f2SChinh Cao /* set link and auto negotiation so changes take effect */ 227448cb27f2SChinh Cao config.caps |= ICE_AQ_PHY_ENA_LINK; 227548cb27f2SChinh Cao 2276aef74145SAnirudh Venkataramanan if (phy_type_low || phy_type_high) { 2277aef74145SAnirudh Venkataramanan config.phy_type_high = cpu_to_le64(phy_type_high) & 2278aef74145SAnirudh Venkataramanan abilities->phy_type_high; 227948cb27f2SChinh Cao config.phy_type_low = cpu_to_le64(phy_type_low) & 228048cb27f2SChinh Cao abilities->phy_type_low; 228148cb27f2SChinh Cao } else { 228248cb27f2SChinh Cao err = -EAGAIN; 228348cb27f2SChinh Cao netdev_info(netdev, "Nothing changed. No PHY_TYPE is corresponded to advertised link speed.\n"); 228448cb27f2SChinh Cao goto done; 228548cb27f2SChinh Cao } 228648cb27f2SChinh Cao 228748cb27f2SChinh Cao /* If link is up put link down */ 228848cb27f2SChinh Cao if (p->phy.link_info.link_info & ICE_AQ_LINK_UP) { 228948cb27f2SChinh Cao /* Tell the OS link is going down, the link will go 229048cb27f2SChinh Cao * back up when fw says it is ready asynchronously 229148cb27f2SChinh Cao */ 229248cb27f2SChinh Cao ice_print_link_msg(np->vsi, false); 229348cb27f2SChinh Cao netif_carrier_off(netdev); 229448cb27f2SChinh Cao netif_tx_stop_all_queues(netdev); 229548cb27f2SChinh Cao } 229648cb27f2SChinh Cao 229748cb27f2SChinh Cao /* make the aq call */ 229848cb27f2SChinh Cao status = ice_aq_set_phy_cfg(&pf->hw, lport, &config, NULL); 229948cb27f2SChinh Cao if (status) { 230048cb27f2SChinh Cao netdev_info(netdev, "Set phy config failed,\n"); 230148cb27f2SChinh Cao err = -EAGAIN; 230248cb27f2SChinh Cao } 230348cb27f2SChinh Cao 230448cb27f2SChinh Cao done: 23059efe35d0STony Nguyen kfree(abilities); 230648cb27f2SChinh Cao clear_bit(__ICE_CFG_BUSY, pf->state); 230748cb27f2SChinh Cao 230848cb27f2SChinh Cao return err; 230948cb27f2SChinh Cao } 231048cb27f2SChinh Cao 231148cb27f2SChinh Cao /** 23126876fb64SMd Fahad Iqbal Polash * ice_parse_hdrs - parses headers from RSS hash input 23136876fb64SMd Fahad Iqbal Polash * @nfc: ethtool rxnfc command 23146876fb64SMd Fahad Iqbal Polash * 23156876fb64SMd Fahad Iqbal Polash * This function parses the rxnfc command and returns intended 23166876fb64SMd Fahad Iqbal Polash * header types for RSS configuration 23176876fb64SMd Fahad Iqbal Polash */ 23186876fb64SMd Fahad Iqbal Polash static u32 ice_parse_hdrs(struct ethtool_rxnfc *nfc) 23196876fb64SMd Fahad Iqbal Polash { 23206876fb64SMd Fahad Iqbal Polash u32 hdrs = ICE_FLOW_SEG_HDR_NONE; 23216876fb64SMd Fahad Iqbal Polash 23226876fb64SMd Fahad Iqbal Polash switch (nfc->flow_type) { 23236876fb64SMd Fahad Iqbal Polash case TCP_V4_FLOW: 23246876fb64SMd Fahad Iqbal Polash hdrs |= ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4; 23256876fb64SMd Fahad Iqbal Polash break; 23266876fb64SMd Fahad Iqbal Polash case UDP_V4_FLOW: 23276876fb64SMd Fahad Iqbal Polash hdrs |= ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4; 23286876fb64SMd Fahad Iqbal Polash break; 23296876fb64SMd Fahad Iqbal Polash case SCTP_V4_FLOW: 23306876fb64SMd Fahad Iqbal Polash hdrs |= ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4; 23316876fb64SMd Fahad Iqbal Polash break; 23326876fb64SMd Fahad Iqbal Polash case TCP_V6_FLOW: 23336876fb64SMd Fahad Iqbal Polash hdrs |= ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6; 23346876fb64SMd Fahad Iqbal Polash break; 23356876fb64SMd Fahad Iqbal Polash case UDP_V6_FLOW: 23366876fb64SMd Fahad Iqbal Polash hdrs |= ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6; 23376876fb64SMd Fahad Iqbal Polash break; 23386876fb64SMd Fahad Iqbal Polash case SCTP_V6_FLOW: 23396876fb64SMd Fahad Iqbal Polash hdrs |= ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6; 23406876fb64SMd Fahad Iqbal Polash break; 23416876fb64SMd Fahad Iqbal Polash default: 23426876fb64SMd Fahad Iqbal Polash break; 23436876fb64SMd Fahad Iqbal Polash } 23446876fb64SMd Fahad Iqbal Polash return hdrs; 23456876fb64SMd Fahad Iqbal Polash } 23466876fb64SMd Fahad Iqbal Polash 23476876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_IPV4_SA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) 23486876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_IPV6_SA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) 23496876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_IPV4_DA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) 23506876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_IPV6_DA BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) 23516876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_TCP_SRC_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT) 23526876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_TCP_DST_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT) 23536876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_UDP_SRC_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT) 23546876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_UDP_DST_PORT BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT) 23556876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_SCTP_SRC_PORT \ 23566876fb64SMd Fahad Iqbal Polash BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT) 23576876fb64SMd Fahad Iqbal Polash #define ICE_FLOW_HASH_FLD_SCTP_DST_PORT \ 23586876fb64SMd Fahad Iqbal Polash BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT) 23596876fb64SMd Fahad Iqbal Polash 23606876fb64SMd Fahad Iqbal Polash /** 23616876fb64SMd Fahad Iqbal Polash * ice_parse_hash_flds - parses hash fields from RSS hash input 23626876fb64SMd Fahad Iqbal Polash * @nfc: ethtool rxnfc command 23636876fb64SMd Fahad Iqbal Polash * 23646876fb64SMd Fahad Iqbal Polash * This function parses the rxnfc command and returns intended 23656876fb64SMd Fahad Iqbal Polash * hash fields for RSS configuration 23666876fb64SMd Fahad Iqbal Polash */ 23676876fb64SMd Fahad Iqbal Polash static u64 ice_parse_hash_flds(struct ethtool_rxnfc *nfc) 23686876fb64SMd Fahad Iqbal Polash { 23696876fb64SMd Fahad Iqbal Polash u64 hfld = ICE_HASH_INVALID; 23706876fb64SMd Fahad Iqbal Polash 23716876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_IP_SRC || nfc->data & RXH_IP_DST) { 23726876fb64SMd Fahad Iqbal Polash switch (nfc->flow_type) { 23736876fb64SMd Fahad Iqbal Polash case TCP_V4_FLOW: 23746876fb64SMd Fahad Iqbal Polash case UDP_V4_FLOW: 23756876fb64SMd Fahad Iqbal Polash case SCTP_V4_FLOW: 23766876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_IP_SRC) 23776876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_IPV4_SA; 23786876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_IP_DST) 23796876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_IPV4_DA; 23806876fb64SMd Fahad Iqbal Polash break; 23816876fb64SMd Fahad Iqbal Polash case TCP_V6_FLOW: 23826876fb64SMd Fahad Iqbal Polash case UDP_V6_FLOW: 23836876fb64SMd Fahad Iqbal Polash case SCTP_V6_FLOW: 23846876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_IP_SRC) 23856876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_IPV6_SA; 23866876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_IP_DST) 23876876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_IPV6_DA; 23886876fb64SMd Fahad Iqbal Polash break; 23896876fb64SMd Fahad Iqbal Polash default: 23906876fb64SMd Fahad Iqbal Polash break; 23916876fb64SMd Fahad Iqbal Polash } 23926876fb64SMd Fahad Iqbal Polash } 23936876fb64SMd Fahad Iqbal Polash 23946876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_L4_B_0_1 || nfc->data & RXH_L4_B_2_3) { 23956876fb64SMd Fahad Iqbal Polash switch (nfc->flow_type) { 23966876fb64SMd Fahad Iqbal Polash case TCP_V4_FLOW: 23976876fb64SMd Fahad Iqbal Polash case TCP_V6_FLOW: 23986876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_L4_B_0_1) 23996876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_TCP_SRC_PORT; 24006876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_L4_B_2_3) 24016876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_TCP_DST_PORT; 24026876fb64SMd Fahad Iqbal Polash break; 24036876fb64SMd Fahad Iqbal Polash case UDP_V4_FLOW: 24046876fb64SMd Fahad Iqbal Polash case UDP_V6_FLOW: 24056876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_L4_B_0_1) 24066876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_UDP_SRC_PORT; 24076876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_L4_B_2_3) 24086876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_UDP_DST_PORT; 24096876fb64SMd Fahad Iqbal Polash break; 24106876fb64SMd Fahad Iqbal Polash case SCTP_V4_FLOW: 24116876fb64SMd Fahad Iqbal Polash case SCTP_V6_FLOW: 24126876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_L4_B_0_1) 24136876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_SCTP_SRC_PORT; 24146876fb64SMd Fahad Iqbal Polash if (nfc->data & RXH_L4_B_2_3) 24156876fb64SMd Fahad Iqbal Polash hfld |= ICE_FLOW_HASH_FLD_SCTP_DST_PORT; 24166876fb64SMd Fahad Iqbal Polash break; 24176876fb64SMd Fahad Iqbal Polash default: 24186876fb64SMd Fahad Iqbal Polash break; 24196876fb64SMd Fahad Iqbal Polash } 24206876fb64SMd Fahad Iqbal Polash } 24216876fb64SMd Fahad Iqbal Polash 24226876fb64SMd Fahad Iqbal Polash return hfld; 24236876fb64SMd Fahad Iqbal Polash } 24246876fb64SMd Fahad Iqbal Polash 24256876fb64SMd Fahad Iqbal Polash /** 24266876fb64SMd Fahad Iqbal Polash * ice_set_rss_hash_opt - Enable/Disable flow types for RSS hash 24276876fb64SMd Fahad Iqbal Polash * @vsi: the VSI being configured 24286876fb64SMd Fahad Iqbal Polash * @nfc: ethtool rxnfc command 24296876fb64SMd Fahad Iqbal Polash * 24306876fb64SMd Fahad Iqbal Polash * Returns Success if the flow input set is supported. 24316876fb64SMd Fahad Iqbal Polash */ 24326876fb64SMd Fahad Iqbal Polash static int 24336876fb64SMd Fahad Iqbal Polash ice_set_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) 24346876fb64SMd Fahad Iqbal Polash { 24356876fb64SMd Fahad Iqbal Polash struct ice_pf *pf = vsi->back; 24366876fb64SMd Fahad Iqbal Polash enum ice_status status; 24376876fb64SMd Fahad Iqbal Polash struct device *dev; 24386876fb64SMd Fahad Iqbal Polash u64 hashed_flds; 24396876fb64SMd Fahad Iqbal Polash u32 hdrs; 24406876fb64SMd Fahad Iqbal Polash 24416876fb64SMd Fahad Iqbal Polash dev = ice_pf_to_dev(pf); 24426876fb64SMd Fahad Iqbal Polash if (ice_is_safe_mode(pf)) { 24436876fb64SMd Fahad Iqbal Polash dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n", 24446876fb64SMd Fahad Iqbal Polash vsi->vsi_num); 24456876fb64SMd Fahad Iqbal Polash return -EINVAL; 24466876fb64SMd Fahad Iqbal Polash } 24476876fb64SMd Fahad Iqbal Polash 24486876fb64SMd Fahad Iqbal Polash hashed_flds = ice_parse_hash_flds(nfc); 24496876fb64SMd Fahad Iqbal Polash if (hashed_flds == ICE_HASH_INVALID) { 24506876fb64SMd Fahad Iqbal Polash dev_dbg(dev, "Invalid hash fields, vsi num = %d\n", 24516876fb64SMd Fahad Iqbal Polash vsi->vsi_num); 24526876fb64SMd Fahad Iqbal Polash return -EINVAL; 24536876fb64SMd Fahad Iqbal Polash } 24546876fb64SMd Fahad Iqbal Polash 24556876fb64SMd Fahad Iqbal Polash hdrs = ice_parse_hdrs(nfc); 24566876fb64SMd Fahad Iqbal Polash if (hdrs == ICE_FLOW_SEG_HDR_NONE) { 24576876fb64SMd Fahad Iqbal Polash dev_dbg(dev, "Header type is not valid, vsi num = %d\n", 24586876fb64SMd Fahad Iqbal Polash vsi->vsi_num); 24596876fb64SMd Fahad Iqbal Polash return -EINVAL; 24606876fb64SMd Fahad Iqbal Polash } 24616876fb64SMd Fahad Iqbal Polash 24626876fb64SMd Fahad Iqbal Polash status = ice_add_rss_cfg(&pf->hw, vsi->idx, hashed_flds, hdrs); 24636876fb64SMd Fahad Iqbal Polash if (status) { 24640fee3577SLihong Yang dev_dbg(dev, "ice_add_rss_cfg failed, vsi num = %d, error = %s\n", 24650fee3577SLihong Yang vsi->vsi_num, ice_stat_str(status)); 24666876fb64SMd Fahad Iqbal Polash return -EINVAL; 24676876fb64SMd Fahad Iqbal Polash } 24686876fb64SMd Fahad Iqbal Polash 24696876fb64SMd Fahad Iqbal Polash return 0; 24706876fb64SMd Fahad Iqbal Polash } 24716876fb64SMd Fahad Iqbal Polash 24726876fb64SMd Fahad Iqbal Polash /** 24736876fb64SMd Fahad Iqbal Polash * ice_get_rss_hash_opt - Retrieve hash fields for a given flow-type 24746876fb64SMd Fahad Iqbal Polash * @vsi: the VSI being configured 24756876fb64SMd Fahad Iqbal Polash * @nfc: ethtool rxnfc command 24766876fb64SMd Fahad Iqbal Polash */ 24776876fb64SMd Fahad Iqbal Polash static void 24786876fb64SMd Fahad Iqbal Polash ice_get_rss_hash_opt(struct ice_vsi *vsi, struct ethtool_rxnfc *nfc) 24796876fb64SMd Fahad Iqbal Polash { 24806876fb64SMd Fahad Iqbal Polash struct ice_pf *pf = vsi->back; 24816876fb64SMd Fahad Iqbal Polash struct device *dev; 24826876fb64SMd Fahad Iqbal Polash u64 hash_flds; 24836876fb64SMd Fahad Iqbal Polash u32 hdrs; 24846876fb64SMd Fahad Iqbal Polash 24856876fb64SMd Fahad Iqbal Polash dev = ice_pf_to_dev(pf); 24866876fb64SMd Fahad Iqbal Polash 24876876fb64SMd Fahad Iqbal Polash nfc->data = 0; 24886876fb64SMd Fahad Iqbal Polash if (ice_is_safe_mode(pf)) { 24896876fb64SMd Fahad Iqbal Polash dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n", 24906876fb64SMd Fahad Iqbal Polash vsi->vsi_num); 24916876fb64SMd Fahad Iqbal Polash return; 24926876fb64SMd Fahad Iqbal Polash } 24936876fb64SMd Fahad Iqbal Polash 24946876fb64SMd Fahad Iqbal Polash hdrs = ice_parse_hdrs(nfc); 24956876fb64SMd Fahad Iqbal Polash if (hdrs == ICE_FLOW_SEG_HDR_NONE) { 24966876fb64SMd Fahad Iqbal Polash dev_dbg(dev, "Header type is not valid, vsi num = %d\n", 24976876fb64SMd Fahad Iqbal Polash vsi->vsi_num); 24986876fb64SMd Fahad Iqbal Polash return; 24996876fb64SMd Fahad Iqbal Polash } 25006876fb64SMd Fahad Iqbal Polash 25016876fb64SMd Fahad Iqbal Polash hash_flds = ice_get_rss_cfg(&pf->hw, vsi->idx, hdrs); 25026876fb64SMd Fahad Iqbal Polash if (hash_flds == ICE_HASH_INVALID) { 25036876fb64SMd Fahad Iqbal Polash dev_dbg(dev, "No hash fields found for the given header type, vsi num = %d\n", 25046876fb64SMd Fahad Iqbal Polash vsi->vsi_num); 25056876fb64SMd Fahad Iqbal Polash return; 25066876fb64SMd Fahad Iqbal Polash } 25076876fb64SMd Fahad Iqbal Polash 25086876fb64SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_HASH_FLD_IPV4_SA || 25096876fb64SMd Fahad Iqbal Polash hash_flds & ICE_FLOW_HASH_FLD_IPV6_SA) 25106876fb64SMd Fahad Iqbal Polash nfc->data |= (u64)RXH_IP_SRC; 25116876fb64SMd Fahad Iqbal Polash 25126876fb64SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_HASH_FLD_IPV4_DA || 25136876fb64SMd Fahad Iqbal Polash hash_flds & ICE_FLOW_HASH_FLD_IPV6_DA) 25146876fb64SMd Fahad Iqbal Polash nfc->data |= (u64)RXH_IP_DST; 25156876fb64SMd Fahad Iqbal Polash 25166876fb64SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_HASH_FLD_TCP_SRC_PORT || 25176876fb64SMd Fahad Iqbal Polash hash_flds & ICE_FLOW_HASH_FLD_UDP_SRC_PORT || 25186876fb64SMd Fahad Iqbal Polash hash_flds & ICE_FLOW_HASH_FLD_SCTP_SRC_PORT) 25196876fb64SMd Fahad Iqbal Polash nfc->data |= (u64)RXH_L4_B_0_1; 25206876fb64SMd Fahad Iqbal Polash 25216876fb64SMd Fahad Iqbal Polash if (hash_flds & ICE_FLOW_HASH_FLD_TCP_DST_PORT || 25226876fb64SMd Fahad Iqbal Polash hash_flds & ICE_FLOW_HASH_FLD_UDP_DST_PORT || 25236876fb64SMd Fahad Iqbal Polash hash_flds & ICE_FLOW_HASH_FLD_SCTP_DST_PORT) 25246876fb64SMd Fahad Iqbal Polash nfc->data |= (u64)RXH_L4_B_2_3; 25256876fb64SMd Fahad Iqbal Polash } 25266876fb64SMd Fahad Iqbal Polash 25276876fb64SMd Fahad Iqbal Polash /** 25286876fb64SMd Fahad Iqbal Polash * ice_set_rxnfc - command to set Rx flow rules. 25296876fb64SMd Fahad Iqbal Polash * @netdev: network interface device structure 25306876fb64SMd Fahad Iqbal Polash * @cmd: ethtool rxnfc command 25316876fb64SMd Fahad Iqbal Polash * 25326876fb64SMd Fahad Iqbal Polash * Returns 0 for success and negative values for errors 25336876fb64SMd Fahad Iqbal Polash */ 25346876fb64SMd Fahad Iqbal Polash static int ice_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) 25356876fb64SMd Fahad Iqbal Polash { 25366876fb64SMd Fahad Iqbal Polash struct ice_netdev_priv *np = netdev_priv(netdev); 25376876fb64SMd Fahad Iqbal Polash struct ice_vsi *vsi = np->vsi; 25386876fb64SMd Fahad Iqbal Polash 25396876fb64SMd Fahad Iqbal Polash switch (cmd->cmd) { 25406876fb64SMd Fahad Iqbal Polash case ETHTOOL_SRXFH: 25416876fb64SMd Fahad Iqbal Polash return ice_set_rss_hash_opt(vsi, cmd); 25426876fb64SMd Fahad Iqbal Polash default: 25436876fb64SMd Fahad Iqbal Polash break; 25446876fb64SMd Fahad Iqbal Polash } 25456876fb64SMd Fahad Iqbal Polash return -EOPNOTSUPP; 25466876fb64SMd Fahad Iqbal Polash } 25476876fb64SMd Fahad Iqbal Polash 25486876fb64SMd Fahad Iqbal Polash /** 2549f9867df6SAnirudh Venkataramanan * ice_get_rxnfc - command to get Rx flow classification rules 2550fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2551fcea6f3dSAnirudh Venkataramanan * @cmd: ethtool rxnfc command 2552fcea6f3dSAnirudh Venkataramanan * @rule_locs: buffer to rturn Rx flow classification rules 2553fcea6f3dSAnirudh Venkataramanan * 2554fcea6f3dSAnirudh Venkataramanan * Returns Success if the command is supported. 2555fcea6f3dSAnirudh Venkataramanan */ 2556c8b7abddSBruce Allan static int 2557c8b7abddSBruce Allan ice_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, 2558fcea6f3dSAnirudh Venkataramanan u32 __always_unused *rule_locs) 2559fcea6f3dSAnirudh Venkataramanan { 2560fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2561fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2562fcea6f3dSAnirudh Venkataramanan int ret = -EOPNOTSUPP; 25634ab95646SHenry Tieman struct ice_hw *hw; 25644ab95646SHenry Tieman 25654ab95646SHenry Tieman hw = &vsi->back->hw; 2566fcea6f3dSAnirudh Venkataramanan 2567fcea6f3dSAnirudh Venkataramanan switch (cmd->cmd) { 2568fcea6f3dSAnirudh Venkataramanan case ETHTOOL_GRXRINGS: 2569fcea6f3dSAnirudh Venkataramanan cmd->data = vsi->rss_size; 2570fcea6f3dSAnirudh Venkataramanan ret = 0; 2571fcea6f3dSAnirudh Venkataramanan break; 25724ab95646SHenry Tieman case ETHTOOL_GRXCLSRLCNT: 25734ab95646SHenry Tieman cmd->rule_cnt = hw->fdir_active_fltr; 25744ab95646SHenry Tieman /* report total rule count */ 25754ab95646SHenry Tieman cmd->data = ice_get_fdir_cnt_all(hw); 25764ab95646SHenry Tieman ret = 0; 25774ab95646SHenry Tieman break; 25784ab95646SHenry Tieman case ETHTOOL_GRXCLSRULE: 25794ab95646SHenry Tieman ret = ice_get_ethtool_fdir_entry(hw, cmd); 25804ab95646SHenry Tieman break; 25814ab95646SHenry Tieman case ETHTOOL_GRXCLSRLALL: 25824ab95646SHenry Tieman ret = ice_get_fdir_fltr_ids(hw, cmd, (u32 *)rule_locs); 25834ab95646SHenry Tieman break; 25846876fb64SMd Fahad Iqbal Polash case ETHTOOL_GRXFH: 25856876fb64SMd Fahad Iqbal Polash ice_get_rss_hash_opt(vsi, cmd); 25866876fb64SMd Fahad Iqbal Polash ret = 0; 25876876fb64SMd Fahad Iqbal Polash break; 2588fcea6f3dSAnirudh Venkataramanan default: 2589fcea6f3dSAnirudh Venkataramanan break; 2590fcea6f3dSAnirudh Venkataramanan } 2591fcea6f3dSAnirudh Venkataramanan 2592fcea6f3dSAnirudh Venkataramanan return ret; 2593fcea6f3dSAnirudh Venkataramanan } 2594fcea6f3dSAnirudh Venkataramanan 2595fcea6f3dSAnirudh Venkataramanan static void 2596fcea6f3dSAnirudh Venkataramanan ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 2597fcea6f3dSAnirudh Venkataramanan { 2598fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2599fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2600fcea6f3dSAnirudh Venkataramanan 2601fcea6f3dSAnirudh Venkataramanan ring->rx_max_pending = ICE_MAX_NUM_DESC; 2602fcea6f3dSAnirudh Venkataramanan ring->tx_max_pending = ICE_MAX_NUM_DESC; 2603fcea6f3dSAnirudh Venkataramanan ring->rx_pending = vsi->rx_rings[0]->count; 2604fcea6f3dSAnirudh Venkataramanan ring->tx_pending = vsi->tx_rings[0]->count; 2605f934bb9bSBruce Allan 2606f934bb9bSBruce Allan /* Rx mini and jumbo rings are not supported */ 2607fcea6f3dSAnirudh Venkataramanan ring->rx_mini_max_pending = 0; 2608fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_max_pending = 0; 2609f934bb9bSBruce Allan ring->rx_mini_pending = 0; 2610fcea6f3dSAnirudh Venkataramanan ring->rx_jumbo_pending = 0; 2611fcea6f3dSAnirudh Venkataramanan } 2612fcea6f3dSAnirudh Venkataramanan 2613fcea6f3dSAnirudh Venkataramanan static int 2614fcea6f3dSAnirudh Venkataramanan ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) 2615fcea6f3dSAnirudh Venkataramanan { 2616fcea6f3dSAnirudh Venkataramanan struct ice_ring *tx_rings = NULL, *rx_rings = NULL; 2617fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2618efc2214bSMaciej Fijalkowski struct ice_ring *xdp_rings = NULL; 2619fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2620fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2621fcea6f3dSAnirudh Venkataramanan int i, timeout = 50, err = 0; 262288865fc4SKarol Kolacinski u16 new_rx_cnt, new_tx_cnt; 2623fcea6f3dSAnirudh Venkataramanan 2624fcea6f3dSAnirudh Venkataramanan if (ring->tx_pending > ICE_MAX_NUM_DESC || 2625fcea6f3dSAnirudh Venkataramanan ring->tx_pending < ICE_MIN_NUM_DESC || 2626fcea6f3dSAnirudh Venkataramanan ring->rx_pending > ICE_MAX_NUM_DESC || 2627fcea6f3dSAnirudh Venkataramanan ring->rx_pending < ICE_MIN_NUM_DESC) { 2628f934bb9bSBruce Allan netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", 2629fcea6f3dSAnirudh Venkataramanan ring->tx_pending, ring->rx_pending, 2630f934bb9bSBruce Allan ICE_MIN_NUM_DESC, ICE_MAX_NUM_DESC, 2631f934bb9bSBruce Allan ICE_REQ_DESC_MULTIPLE); 2632fcea6f3dSAnirudh Venkataramanan return -EINVAL; 2633fcea6f3dSAnirudh Venkataramanan } 2634fcea6f3dSAnirudh Venkataramanan 2635fcea6f3dSAnirudh Venkataramanan new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE); 2636f934bb9bSBruce Allan if (new_tx_cnt != ring->tx_pending) 263719cce2c6SAnirudh Venkataramanan netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n", 2638f934bb9bSBruce Allan new_tx_cnt); 2639fcea6f3dSAnirudh Venkataramanan new_rx_cnt = ALIGN(ring->rx_pending, ICE_REQ_DESC_MULTIPLE); 2640f934bb9bSBruce Allan if (new_rx_cnt != ring->rx_pending) 264119cce2c6SAnirudh Venkataramanan netdev_info(netdev, "Requested Rx descriptor count rounded up to %d\n", 2642f934bb9bSBruce Allan new_rx_cnt); 2643fcea6f3dSAnirudh Venkataramanan 2644fcea6f3dSAnirudh Venkataramanan /* if nothing to do return success */ 2645fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count && 2646fcea6f3dSAnirudh Venkataramanan new_rx_cnt == vsi->rx_rings[0]->count) { 2647fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); 2648fcea6f3dSAnirudh Venkataramanan return 0; 2649fcea6f3dSAnirudh Venkataramanan } 2650fcea6f3dSAnirudh Venkataramanan 26512d4238f5SKrzysztof Kazimierczak /* If there is a AF_XDP UMEM attached to any of Rx rings, 26522d4238f5SKrzysztof Kazimierczak * disallow changing the number of descriptors -- regardless 26532d4238f5SKrzysztof Kazimierczak * if the netdev is running or not. 26542d4238f5SKrzysztof Kazimierczak */ 26552d4238f5SKrzysztof Kazimierczak if (ice_xsk_any_rx_ring_ena(vsi)) 26562d4238f5SKrzysztof Kazimierczak return -EBUSY; 26572d4238f5SKrzysztof Kazimierczak 2658fcea6f3dSAnirudh Venkataramanan while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) { 2659fcea6f3dSAnirudh Venkataramanan timeout--; 2660fcea6f3dSAnirudh Venkataramanan if (!timeout) 2661fcea6f3dSAnirudh Venkataramanan return -EBUSY; 2662fcea6f3dSAnirudh Venkataramanan usleep_range(1000, 2000); 2663fcea6f3dSAnirudh Venkataramanan } 2664fcea6f3dSAnirudh Venkataramanan 2665fcea6f3dSAnirudh Venkataramanan /* set for the next time the netdev is started */ 2666fcea6f3dSAnirudh Venkataramanan if (!netif_running(vsi->netdev)) { 2667fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) 2668fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[i]->count = new_tx_cnt; 2669fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) 2670fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[i]->count = new_rx_cnt; 2671efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) 2672efc2214bSMaciej Fijalkowski for (i = 0; i < vsi->num_xdp_txq; i++) 2673efc2214bSMaciej Fijalkowski vsi->xdp_rings[i]->count = new_tx_cnt; 267488865fc4SKarol Kolacinski vsi->num_tx_desc = (u16)new_tx_cnt; 267588865fc4SKarol Kolacinski vsi->num_rx_desc = (u16)new_rx_cnt; 2676fcea6f3dSAnirudh Venkataramanan netdev_dbg(netdev, "Link is down, descriptor count change happens when link is brought up\n"); 2677fcea6f3dSAnirudh Venkataramanan goto done; 2678fcea6f3dSAnirudh Venkataramanan } 2679fcea6f3dSAnirudh Venkataramanan 2680fcea6f3dSAnirudh Venkataramanan if (new_tx_cnt == vsi->tx_rings[0]->count) 2681fcea6f3dSAnirudh Venkataramanan goto process_rx; 2682fcea6f3dSAnirudh Venkataramanan 2683fcea6f3dSAnirudh Venkataramanan /* alloc updated Tx resources */ 2684fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Tx descriptor count from %d to %d\n", 2685fcea6f3dSAnirudh Venkataramanan vsi->tx_rings[0]->count, new_tx_cnt); 2686fcea6f3dSAnirudh Venkataramanan 26879efe35d0STony Nguyen tx_rings = kcalloc(vsi->num_txq, sizeof(*tx_rings), GFP_KERNEL); 2688fcea6f3dSAnirudh Venkataramanan if (!tx_rings) { 2689fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2690fcea6f3dSAnirudh Venkataramanan goto done; 2691fcea6f3dSAnirudh Venkataramanan } 2692fcea6f3dSAnirudh Venkataramanan 2693c0a3665fSUsha Ketineni ice_for_each_txq(vsi, i) { 2694fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 2695fcea6f3dSAnirudh Venkataramanan tx_rings[i] = *vsi->tx_rings[i]; 2696fcea6f3dSAnirudh Venkataramanan tx_rings[i].count = new_tx_cnt; 2697fcea6f3dSAnirudh Venkataramanan tx_rings[i].desc = NULL; 2698fcea6f3dSAnirudh Venkataramanan tx_rings[i].tx_buf = NULL; 2699fcea6f3dSAnirudh Venkataramanan err = ice_setup_tx_ring(&tx_rings[i]); 2700fcea6f3dSAnirudh Venkataramanan if (err) { 2701efc2214bSMaciej Fijalkowski while (i--) 2702fcea6f3dSAnirudh Venkataramanan ice_clean_tx_ring(&tx_rings[i]); 27039efe35d0STony Nguyen kfree(tx_rings); 2704fcea6f3dSAnirudh Venkataramanan goto done; 2705fcea6f3dSAnirudh Venkataramanan } 2706fcea6f3dSAnirudh Venkataramanan } 2707fcea6f3dSAnirudh Venkataramanan 2708efc2214bSMaciej Fijalkowski if (!ice_is_xdp_ena_vsi(vsi)) 2709efc2214bSMaciej Fijalkowski goto process_rx; 2710efc2214bSMaciej Fijalkowski 2711efc2214bSMaciej Fijalkowski /* alloc updated XDP resources */ 2712efc2214bSMaciej Fijalkowski netdev_info(netdev, "Changing XDP descriptor count from %d to %d\n", 2713efc2214bSMaciej Fijalkowski vsi->xdp_rings[0]->count, new_tx_cnt); 2714efc2214bSMaciej Fijalkowski 27159efe35d0STony Nguyen xdp_rings = kcalloc(vsi->num_xdp_txq, sizeof(*xdp_rings), GFP_KERNEL); 2716efc2214bSMaciej Fijalkowski if (!xdp_rings) { 2717efc2214bSMaciej Fijalkowski err = -ENOMEM; 2718efc2214bSMaciej Fijalkowski goto free_tx; 2719efc2214bSMaciej Fijalkowski } 2720efc2214bSMaciej Fijalkowski 2721efc2214bSMaciej Fijalkowski for (i = 0; i < vsi->num_xdp_txq; i++) { 2722efc2214bSMaciej Fijalkowski /* clone ring and setup updated count */ 2723efc2214bSMaciej Fijalkowski xdp_rings[i] = *vsi->xdp_rings[i]; 2724efc2214bSMaciej Fijalkowski xdp_rings[i].count = new_tx_cnt; 2725efc2214bSMaciej Fijalkowski xdp_rings[i].desc = NULL; 2726efc2214bSMaciej Fijalkowski xdp_rings[i].tx_buf = NULL; 2727efc2214bSMaciej Fijalkowski err = ice_setup_tx_ring(&xdp_rings[i]); 2728efc2214bSMaciej Fijalkowski if (err) { 2729efc2214bSMaciej Fijalkowski while (i--) 2730efc2214bSMaciej Fijalkowski ice_clean_tx_ring(&xdp_rings[i]); 27319efe35d0STony Nguyen kfree(xdp_rings); 2732efc2214bSMaciej Fijalkowski goto free_tx; 2733efc2214bSMaciej Fijalkowski } 2734efc2214bSMaciej Fijalkowski ice_set_ring_xdp(&xdp_rings[i]); 2735efc2214bSMaciej Fijalkowski } 2736efc2214bSMaciej Fijalkowski 2737fcea6f3dSAnirudh Venkataramanan process_rx: 2738fcea6f3dSAnirudh Venkataramanan if (new_rx_cnt == vsi->rx_rings[0]->count) 2739fcea6f3dSAnirudh Venkataramanan goto process_link; 2740fcea6f3dSAnirudh Venkataramanan 2741fcea6f3dSAnirudh Venkataramanan /* alloc updated Rx resources */ 2742fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing Rx descriptor count from %d to %d\n", 2743fcea6f3dSAnirudh Venkataramanan vsi->rx_rings[0]->count, new_rx_cnt); 2744fcea6f3dSAnirudh Venkataramanan 27459efe35d0STony Nguyen rx_rings = kcalloc(vsi->num_rxq, sizeof(*rx_rings), GFP_KERNEL); 2746fcea6f3dSAnirudh Venkataramanan if (!rx_rings) { 2747fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2748fcea6f3dSAnirudh Venkataramanan goto done; 2749fcea6f3dSAnirudh Venkataramanan } 2750fcea6f3dSAnirudh Venkataramanan 2751c0a3665fSUsha Ketineni ice_for_each_rxq(vsi, i) { 2752fcea6f3dSAnirudh Venkataramanan /* clone ring and setup updated count */ 2753fcea6f3dSAnirudh Venkataramanan rx_rings[i] = *vsi->rx_rings[i]; 2754fcea6f3dSAnirudh Venkataramanan rx_rings[i].count = new_rx_cnt; 2755fcea6f3dSAnirudh Venkataramanan rx_rings[i].desc = NULL; 2756fcea6f3dSAnirudh Venkataramanan rx_rings[i].rx_buf = NULL; 2757fcea6f3dSAnirudh Venkataramanan /* this is to allow wr32 to have something to write to 2758fcea6f3dSAnirudh Venkataramanan * during early allocation of Rx buffers 2759fcea6f3dSAnirudh Venkataramanan */ 2760fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->back->hw.hw_addr + PRTGEN_STATUS; 2761fcea6f3dSAnirudh Venkataramanan 2762fcea6f3dSAnirudh Venkataramanan err = ice_setup_rx_ring(&rx_rings[i]); 2763fcea6f3dSAnirudh Venkataramanan if (err) 2764fcea6f3dSAnirudh Venkataramanan goto rx_unwind; 2765fcea6f3dSAnirudh Venkataramanan 2766fcea6f3dSAnirudh Venkataramanan /* allocate Rx buffers */ 2767fcea6f3dSAnirudh Venkataramanan err = ice_alloc_rx_bufs(&rx_rings[i], 2768fcea6f3dSAnirudh Venkataramanan ICE_DESC_UNUSED(&rx_rings[i])); 2769fcea6f3dSAnirudh Venkataramanan rx_unwind: 2770fcea6f3dSAnirudh Venkataramanan if (err) { 2771fcea6f3dSAnirudh Venkataramanan while (i) { 2772fcea6f3dSAnirudh Venkataramanan i--; 2773fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(&rx_rings[i]); 2774fcea6f3dSAnirudh Venkataramanan } 27759efe35d0STony Nguyen kfree(rx_rings); 2776fcea6f3dSAnirudh Venkataramanan err = -ENOMEM; 2777fcea6f3dSAnirudh Venkataramanan goto free_tx; 2778fcea6f3dSAnirudh Venkataramanan } 2779fcea6f3dSAnirudh Venkataramanan } 2780fcea6f3dSAnirudh Venkataramanan 2781fcea6f3dSAnirudh Venkataramanan process_link: 2782fcea6f3dSAnirudh Venkataramanan /* Bring interface down, copy in the new ring info, then restore the 2783fcea6f3dSAnirudh Venkataramanan * interface. if VSI is up, bring it down and then back up 2784fcea6f3dSAnirudh Venkataramanan */ 2785fcea6f3dSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) { 2786fcea6f3dSAnirudh Venkataramanan ice_down(vsi); 2787fcea6f3dSAnirudh Venkataramanan 2788fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 2789c0a3665fSUsha Ketineni ice_for_each_txq(vsi, i) { 2790fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 2791fcea6f3dSAnirudh Venkataramanan *vsi->tx_rings[i] = tx_rings[i]; 2792fcea6f3dSAnirudh Venkataramanan } 27939efe35d0STony Nguyen kfree(tx_rings); 2794fcea6f3dSAnirudh Venkataramanan } 2795fcea6f3dSAnirudh Venkataramanan 2796fcea6f3dSAnirudh Venkataramanan if (rx_rings) { 2797c0a3665fSUsha Ketineni ice_for_each_rxq(vsi, i) { 2798fcea6f3dSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 2799fcea6f3dSAnirudh Venkataramanan /* copy the real tail offset */ 2800fcea6f3dSAnirudh Venkataramanan rx_rings[i].tail = vsi->rx_rings[i]->tail; 2801fcea6f3dSAnirudh Venkataramanan /* this is to fake out the allocation routine 2802fcea6f3dSAnirudh Venkataramanan * into thinking it has to realloc everything 2803fcea6f3dSAnirudh Venkataramanan * but the recycling logic will let us re-use 2804fcea6f3dSAnirudh Venkataramanan * the buffers allocated above 2805fcea6f3dSAnirudh Venkataramanan */ 2806fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_use = 0; 2807fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_clean = 0; 2808fcea6f3dSAnirudh Venkataramanan rx_rings[i].next_to_alloc = 0; 2809fcea6f3dSAnirudh Venkataramanan *vsi->rx_rings[i] = rx_rings[i]; 2810fcea6f3dSAnirudh Venkataramanan } 28119efe35d0STony Nguyen kfree(rx_rings); 2812fcea6f3dSAnirudh Venkataramanan } 2813fcea6f3dSAnirudh Venkataramanan 2814efc2214bSMaciej Fijalkowski if (xdp_rings) { 2815efc2214bSMaciej Fijalkowski for (i = 0; i < vsi->num_xdp_txq; i++) { 2816efc2214bSMaciej Fijalkowski ice_free_tx_ring(vsi->xdp_rings[i]); 2817efc2214bSMaciej Fijalkowski *vsi->xdp_rings[i] = xdp_rings[i]; 2818efc2214bSMaciej Fijalkowski } 28199efe35d0STony Nguyen kfree(xdp_rings); 2820efc2214bSMaciej Fijalkowski } 2821efc2214bSMaciej Fijalkowski 2822efc2214bSMaciej Fijalkowski vsi->num_tx_desc = new_tx_cnt; 2823efc2214bSMaciej Fijalkowski vsi->num_rx_desc = new_rx_cnt; 2824fcea6f3dSAnirudh Venkataramanan ice_up(vsi); 2825fcea6f3dSAnirudh Venkataramanan } 2826fcea6f3dSAnirudh Venkataramanan goto done; 2827fcea6f3dSAnirudh Venkataramanan 2828fcea6f3dSAnirudh Venkataramanan free_tx: 2829fcea6f3dSAnirudh Venkataramanan /* error cleanup if the Rx allocations failed after getting Tx */ 2830fcea6f3dSAnirudh Venkataramanan if (tx_rings) { 2831c0a3665fSUsha Ketineni ice_for_each_txq(vsi, i) 2832fcea6f3dSAnirudh Venkataramanan ice_free_tx_ring(&tx_rings[i]); 28339efe35d0STony Nguyen kfree(tx_rings); 2834fcea6f3dSAnirudh Venkataramanan } 2835fcea6f3dSAnirudh Venkataramanan 2836fcea6f3dSAnirudh Venkataramanan done: 2837fcea6f3dSAnirudh Venkataramanan clear_bit(__ICE_CFG_BUSY, pf->state); 2838fcea6f3dSAnirudh Venkataramanan return err; 2839fcea6f3dSAnirudh Venkataramanan } 2840fcea6f3dSAnirudh Venkataramanan 2841fcea6f3dSAnirudh Venkataramanan /** 2842fcea6f3dSAnirudh Venkataramanan * ice_get_pauseparam - Get Flow Control status 2843fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2844fcea6f3dSAnirudh Venkataramanan * @pause: ethernet pause (flow control) parameters 28455a056cd7SPaul Greenwalt * 28465a056cd7SPaul Greenwalt * Get requested flow control status from PHY capability. 28475a056cd7SPaul Greenwalt * If autoneg is true, then ethtool will send the ETHTOOL_GSET ioctl which 28485a056cd7SPaul Greenwalt * is handled by ice_get_link_ksettings. ice_get_link_ksettings will report 28495a056cd7SPaul Greenwalt * the negotiated Rx/Tx pause via lp_advertising. 2850fcea6f3dSAnirudh Venkataramanan */ 2851fcea6f3dSAnirudh Venkataramanan static void 2852fcea6f3dSAnirudh Venkataramanan ice_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 2853fcea6f3dSAnirudh Venkataramanan { 2854fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 285540c3c546SLukasz Czapnik struct ice_port_info *pi = np->vsi->port_info; 285640c3c546SLukasz Czapnik struct ice_aqc_get_phy_caps_data *pcaps; 28573a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 285840c3c546SLukasz Czapnik enum ice_status status; 2859fcea6f3dSAnirudh Venkataramanan 286040c3c546SLukasz Czapnik /* Initialize pause params */ 286140c3c546SLukasz Czapnik pause->rx_pause = 0; 286240c3c546SLukasz Czapnik pause->tx_pause = 0; 286340c3c546SLukasz Czapnik 28643a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 28653a257a14SAnirudh Venkataramanan 28669efe35d0STony Nguyen pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL); 286740c3c546SLukasz Czapnik if (!pcaps) 286840c3c546SLukasz Czapnik return; 286940c3c546SLukasz Czapnik 2870f9867df6SAnirudh Venkataramanan /* Get current PHY config */ 287140c3c546SLukasz Czapnik status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, 287240c3c546SLukasz Czapnik NULL); 287340c3c546SLukasz Czapnik if (status) 287440c3c546SLukasz Czapnik goto out; 287540c3c546SLukasz Czapnik 287640c3c546SLukasz Czapnik pause->autoneg = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ? 2877fcea6f3dSAnirudh Venkataramanan AUTONEG_ENABLE : AUTONEG_DISABLE); 2878fcea6f3dSAnirudh Venkataramanan 28793a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) 28803a257a14SAnirudh Venkataramanan /* PFC enabled so report LFC as off */ 28813a257a14SAnirudh Venkataramanan goto out; 28823a257a14SAnirudh Venkataramanan 288340c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_TX_LINK_PAUSE) 2884fcea6f3dSAnirudh Venkataramanan pause->tx_pause = 1; 288540c3c546SLukasz Czapnik if (pcaps->caps & ICE_AQC_PHY_EN_RX_LINK_PAUSE) 2886fcea6f3dSAnirudh Venkataramanan pause->rx_pause = 1; 288740c3c546SLukasz Czapnik 288840c3c546SLukasz Czapnik out: 28899efe35d0STony Nguyen kfree(pcaps); 2890fcea6f3dSAnirudh Venkataramanan } 2891fcea6f3dSAnirudh Venkataramanan 2892fcea6f3dSAnirudh Venkataramanan /** 2893fcea6f3dSAnirudh Venkataramanan * ice_set_pauseparam - Set Flow Control parameter 2894fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 2895d337f2afSAnirudh Venkataramanan * @pause: return Tx/Rx flow control status 2896fcea6f3dSAnirudh Venkataramanan */ 2897fcea6f3dSAnirudh Venkataramanan static int 2898fcea6f3dSAnirudh Venkataramanan ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) 2899fcea6f3dSAnirudh Venkataramanan { 2900fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 2901f1a4a66dSPaul Greenwalt struct ice_aqc_get_phy_caps_data *pcaps; 2902fcea6f3dSAnirudh Venkataramanan struct ice_link_status *hw_link_info; 2903fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = np->vsi->back; 29043a257a14SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbx_cfg; 2905fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 2906fcea6f3dSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2907fcea6f3dSAnirudh Venkataramanan struct ice_port_info *pi; 2908fcea6f3dSAnirudh Venkataramanan enum ice_status status; 2909fcea6f3dSAnirudh Venkataramanan u8 aq_failures; 2910fcea6f3dSAnirudh Venkataramanan bool link_up; 2911fcea6f3dSAnirudh Venkataramanan int err = 0; 2912f1a4a66dSPaul Greenwalt u32 is_an; 2913fcea6f3dSAnirudh Venkataramanan 2914fcea6f3dSAnirudh Venkataramanan pi = vsi->port_info; 2915fcea6f3dSAnirudh Venkataramanan hw_link_info = &pi->phy.link_info; 29163a257a14SAnirudh Venkataramanan dcbx_cfg = &pi->local_dcbx_cfg; 2917fcea6f3dSAnirudh Venkataramanan link_up = hw_link_info->link_info & ICE_AQ_LINK_UP; 2918fcea6f3dSAnirudh Venkataramanan 2919fcea6f3dSAnirudh Venkataramanan /* Changing the port's flow control is not supported if this isn't the 2920fcea6f3dSAnirudh Venkataramanan * PF VSI 2921fcea6f3dSAnirudh Venkataramanan */ 2922fcea6f3dSAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) { 2923fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Changing flow control parameters only supported for PF VSI\n"); 2924fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2925fcea6f3dSAnirudh Venkataramanan } 2926fcea6f3dSAnirudh Venkataramanan 2927f1a4a66dSPaul Greenwalt /* Get pause param reports configured and negotiated flow control pause 2928f1a4a66dSPaul Greenwalt * when ETHTOOL_GLINKSETTINGS is defined. Since ETHTOOL_GLINKSETTINGS is 2929f1a4a66dSPaul Greenwalt * defined get pause param pause->autoneg reports SW configured setting, 2930f1a4a66dSPaul Greenwalt * so compare pause->autoneg with SW configured to prevent the user from 2931f1a4a66dSPaul Greenwalt * using set pause param to chance autoneg. 2932f1a4a66dSPaul Greenwalt */ 2933f1a4a66dSPaul Greenwalt pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL); 2934f1a4a66dSPaul Greenwalt if (!pcaps) 2935f1a4a66dSPaul Greenwalt return -ENOMEM; 2936f1a4a66dSPaul Greenwalt 2937f1a4a66dSPaul Greenwalt /* Get current PHY config */ 2938f1a4a66dSPaul Greenwalt status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_SW_CFG, pcaps, 2939f1a4a66dSPaul Greenwalt NULL); 2940f1a4a66dSPaul Greenwalt if (status) { 2941f1a4a66dSPaul Greenwalt kfree(pcaps); 2942f1a4a66dSPaul Greenwalt return -EIO; 2943f1a4a66dSPaul Greenwalt } 2944f1a4a66dSPaul Greenwalt 2945f1a4a66dSPaul Greenwalt is_an = ((pcaps->caps & ICE_AQC_PHY_AN_MODE) ? 2946f1a4a66dSPaul Greenwalt AUTONEG_ENABLE : AUTONEG_DISABLE); 2947f1a4a66dSPaul Greenwalt 2948f1a4a66dSPaul Greenwalt kfree(pcaps); 2949f1a4a66dSPaul Greenwalt 2950f1a4a66dSPaul Greenwalt if (pause->autoneg != is_an) { 2951fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n"); 2952fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 2953fcea6f3dSAnirudh Venkataramanan } 2954fcea6f3dSAnirudh Venkataramanan 2955fcea6f3dSAnirudh Venkataramanan /* If we have link and don't have autoneg */ 2956fcea6f3dSAnirudh Venkataramanan if (!test_bit(__ICE_DOWN, pf->state) && 2957fcea6f3dSAnirudh Venkataramanan !(hw_link_info->an_info & ICE_AQ_AN_COMPLETED)) { 2958fcea6f3dSAnirudh Venkataramanan /* Send message that it might not necessarily work*/ 2959fcea6f3dSAnirudh Venkataramanan netdev_info(netdev, "Autoneg did not complete so changing settings may not result in an actual change.\n"); 2960fcea6f3dSAnirudh Venkataramanan } 2961fcea6f3dSAnirudh Venkataramanan 29623a257a14SAnirudh Venkataramanan if (dcbx_cfg->pfc.pfcena) { 29633a257a14SAnirudh Venkataramanan netdev_info(netdev, "Priority flow control enabled. Cannot set link flow control.\n"); 29643a257a14SAnirudh Venkataramanan return -EOPNOTSUPP; 29653a257a14SAnirudh Venkataramanan } 2966fcea6f3dSAnirudh Venkataramanan if (pause->rx_pause && pause->tx_pause) 2967fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_FULL; 2968fcea6f3dSAnirudh Venkataramanan else if (pause->rx_pause && !pause->tx_pause) 2969fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_RX_PAUSE; 2970fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && pause->tx_pause) 2971fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_TX_PAUSE; 2972fcea6f3dSAnirudh Venkataramanan else if (!pause->rx_pause && !pause->tx_pause) 2973fcea6f3dSAnirudh Venkataramanan pi->fc.req_mode = ICE_FC_NONE; 2974fcea6f3dSAnirudh Venkataramanan else 2975fcea6f3dSAnirudh Venkataramanan return -EINVAL; 2976fcea6f3dSAnirudh Venkataramanan 2977fcea6f3dSAnirudh Venkataramanan /* Set the FC mode and only restart AN if link is up */ 2978fcea6f3dSAnirudh Venkataramanan status = ice_set_fc(pi, &aq_failures, link_up); 2979fcea6f3dSAnirudh Venkataramanan 2980fcea6f3dSAnirudh Venkataramanan if (aq_failures & ICE_SET_FC_AQ_FAIL_GET) { 29810fee3577SLihong Yang netdev_info(netdev, "Set fc failed on the get_phy_capabilities call with err %s aq_err %s\n", 29820fee3577SLihong Yang ice_stat_str(status), 29830fee3577SLihong Yang ice_aq_str(hw->adminq.sq_last_status)); 2984fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2985fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_SET) { 29860fee3577SLihong Yang netdev_info(netdev, "Set fc failed on the set_phy_config call with err %s aq_err %s\n", 29870fee3577SLihong Yang ice_stat_str(status), 29880fee3577SLihong Yang ice_aq_str(hw->adminq.sq_last_status)); 2989fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2990fcea6f3dSAnirudh Venkataramanan } else if (aq_failures & ICE_SET_FC_AQ_FAIL_UPDATE) { 29910fee3577SLihong Yang netdev_info(netdev, "Set fc failed on the get_link_info call with err %s aq_err %s\n", 29920fee3577SLihong Yang ice_stat_str(status), 29930fee3577SLihong Yang ice_aq_str(hw->adminq.sq_last_status)); 2994fcea6f3dSAnirudh Venkataramanan err = -EAGAIN; 2995fcea6f3dSAnirudh Venkataramanan } 2996fcea6f3dSAnirudh Venkataramanan 2997fcea6f3dSAnirudh Venkataramanan return err; 2998fcea6f3dSAnirudh Venkataramanan } 2999fcea6f3dSAnirudh Venkataramanan 3000fcea6f3dSAnirudh Venkataramanan /** 3001fcea6f3dSAnirudh Venkataramanan * ice_get_rxfh_key_size - get the RSS hash key size 3002fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3003fcea6f3dSAnirudh Venkataramanan * 3004fcea6f3dSAnirudh Venkataramanan * Returns the table size. 3005fcea6f3dSAnirudh Venkataramanan */ 3006fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_key_size(struct net_device __always_unused *netdev) 3007fcea6f3dSAnirudh Venkataramanan { 3008fcea6f3dSAnirudh Venkataramanan return ICE_VSIQF_HKEY_ARRAY_SIZE; 3009fcea6f3dSAnirudh Venkataramanan } 3010fcea6f3dSAnirudh Venkataramanan 3011fcea6f3dSAnirudh Venkataramanan /** 3012d337f2afSAnirudh Venkataramanan * ice_get_rxfh_indir_size - get the Rx flow hash indirection table size 3013fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3014fcea6f3dSAnirudh Venkataramanan * 3015fcea6f3dSAnirudh Venkataramanan * Returns the table size. 3016fcea6f3dSAnirudh Venkataramanan */ 3017fcea6f3dSAnirudh Venkataramanan static u32 ice_get_rxfh_indir_size(struct net_device *netdev) 3018fcea6f3dSAnirudh Venkataramanan { 3019fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3020fcea6f3dSAnirudh Venkataramanan 3021fcea6f3dSAnirudh Venkataramanan return np->vsi->rss_table_size; 3022fcea6f3dSAnirudh Venkataramanan } 3023fcea6f3dSAnirudh Venkataramanan 3024fcea6f3dSAnirudh Venkataramanan /** 3025d337f2afSAnirudh Venkataramanan * ice_get_rxfh - get the Rx flow hash indirection table 3026fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3027fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 3028fcea6f3dSAnirudh Venkataramanan * @key: hash key 3029fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 3030fcea6f3dSAnirudh Venkataramanan * 3031fcea6f3dSAnirudh Venkataramanan * Reads the indirection table directly from the hardware. 3032fcea6f3dSAnirudh Venkataramanan */ 3033fcea6f3dSAnirudh Venkataramanan static int 3034fcea6f3dSAnirudh Venkataramanan ice_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) 3035fcea6f3dSAnirudh Venkataramanan { 3036fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3037fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3038fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3039fcea6f3dSAnirudh Venkataramanan int ret = 0, i; 3040fcea6f3dSAnirudh Venkataramanan u8 *lut; 3041fcea6f3dSAnirudh Venkataramanan 3042fcea6f3dSAnirudh Venkataramanan if (hfunc) 3043fcea6f3dSAnirudh Venkataramanan *hfunc = ETH_RSS_HASH_TOP; 3044fcea6f3dSAnirudh Venkataramanan 3045fcea6f3dSAnirudh Venkataramanan if (!indir) 3046fcea6f3dSAnirudh Venkataramanan return 0; 3047fcea6f3dSAnirudh Venkataramanan 3048fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 3049fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 3050fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 3051fcea6f3dSAnirudh Venkataramanan return -EIO; 3052fcea6f3dSAnirudh Venkataramanan } 3053fcea6f3dSAnirudh Venkataramanan 30549efe35d0STony Nguyen lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); 3055fcea6f3dSAnirudh Venkataramanan if (!lut) 3056fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 3057fcea6f3dSAnirudh Venkataramanan 3058fcea6f3dSAnirudh Venkataramanan if (ice_get_rss(vsi, key, lut, vsi->rss_table_size)) { 3059fcea6f3dSAnirudh Venkataramanan ret = -EIO; 3060fcea6f3dSAnirudh Venkataramanan goto out; 3061fcea6f3dSAnirudh Venkataramanan } 3062fcea6f3dSAnirudh Venkataramanan 3063fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 3064fcea6f3dSAnirudh Venkataramanan indir[i] = (u32)(lut[i]); 3065fcea6f3dSAnirudh Venkataramanan 3066fcea6f3dSAnirudh Venkataramanan out: 30679efe35d0STony Nguyen kfree(lut); 3068fcea6f3dSAnirudh Venkataramanan return ret; 3069fcea6f3dSAnirudh Venkataramanan } 3070fcea6f3dSAnirudh Venkataramanan 3071fcea6f3dSAnirudh Venkataramanan /** 3072d337f2afSAnirudh Venkataramanan * ice_set_rxfh - set the Rx flow hash indirection table 3073fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3074fcea6f3dSAnirudh Venkataramanan * @indir: indirection table 3075fcea6f3dSAnirudh Venkataramanan * @key: hash key 3076fcea6f3dSAnirudh Venkataramanan * @hfunc: hash function 3077fcea6f3dSAnirudh Venkataramanan * 3078f9867df6SAnirudh Venkataramanan * Returns -EINVAL if the table specifies an invalid queue ID, otherwise 3079fcea6f3dSAnirudh Venkataramanan * returns 0 after programming the table. 3080fcea6f3dSAnirudh Venkataramanan */ 3081c8b7abddSBruce Allan static int 3082c8b7abddSBruce Allan ice_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, 3083c8b7abddSBruce Allan const u8 hfunc) 3084fcea6f3dSAnirudh Venkataramanan { 3085fcea6f3dSAnirudh Venkataramanan struct ice_netdev_priv *np = netdev_priv(netdev); 3086fcea6f3dSAnirudh Venkataramanan struct ice_vsi *vsi = np->vsi; 3087fcea6f3dSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 30884015d11eSBrett Creeley struct device *dev; 3089fcea6f3dSAnirudh Venkataramanan u8 *seed = NULL; 3090fcea6f3dSAnirudh Venkataramanan 30914015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 3092fcea6f3dSAnirudh Venkataramanan if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) 3093fcea6f3dSAnirudh Venkataramanan return -EOPNOTSUPP; 3094fcea6f3dSAnirudh Venkataramanan 3095fcea6f3dSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 3096fcea6f3dSAnirudh Venkataramanan /* RSS not supported return error here */ 3097fcea6f3dSAnirudh Venkataramanan netdev_warn(netdev, "RSS is not configured on this VSI!\n"); 3098fcea6f3dSAnirudh Venkataramanan return -EIO; 3099fcea6f3dSAnirudh Venkataramanan } 3100fcea6f3dSAnirudh Venkataramanan 3101fcea6f3dSAnirudh Venkataramanan if (key) { 3102fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) { 3103fcea6f3dSAnirudh Venkataramanan vsi->rss_hkey_user = 31044015d11eSBrett Creeley devm_kzalloc(dev, ICE_VSIQF_HKEY_ARRAY_SIZE, 3105fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 3106fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_hkey_user) 3107fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 3108fcea6f3dSAnirudh Venkataramanan } 3109fcea6f3dSAnirudh Venkataramanan memcpy(vsi->rss_hkey_user, key, ICE_VSIQF_HKEY_ARRAY_SIZE); 3110fcea6f3dSAnirudh Venkataramanan seed = vsi->rss_hkey_user; 3111fcea6f3dSAnirudh Venkataramanan } 3112fcea6f3dSAnirudh Venkataramanan 3113fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) { 31144015d11eSBrett Creeley vsi->rss_lut_user = devm_kzalloc(dev, vsi->rss_table_size, 3115fcea6f3dSAnirudh Venkataramanan GFP_KERNEL); 3116fcea6f3dSAnirudh Venkataramanan if (!vsi->rss_lut_user) 3117fcea6f3dSAnirudh Venkataramanan return -ENOMEM; 3118fcea6f3dSAnirudh Venkataramanan } 3119fcea6f3dSAnirudh Venkataramanan 3120fcea6f3dSAnirudh Venkataramanan /* Each 32 bits pointed by 'indir' is stored with a lut entry */ 3121fcea6f3dSAnirudh Venkataramanan if (indir) { 3122fcea6f3dSAnirudh Venkataramanan int i; 3123fcea6f3dSAnirudh Venkataramanan 3124fcea6f3dSAnirudh Venkataramanan for (i = 0; i < vsi->rss_table_size; i++) 3125fcea6f3dSAnirudh Venkataramanan vsi->rss_lut_user[i] = (u8)(indir[i]); 3126fcea6f3dSAnirudh Venkataramanan } else { 3127fcea6f3dSAnirudh Venkataramanan ice_fill_rss_lut(vsi->rss_lut_user, vsi->rss_table_size, 3128fcea6f3dSAnirudh Venkataramanan vsi->rss_size); 3129fcea6f3dSAnirudh Venkataramanan } 3130fcea6f3dSAnirudh Venkataramanan 3131fcea6f3dSAnirudh Venkataramanan if (ice_set_rss(vsi, seed, vsi->rss_lut_user, vsi->rss_table_size)) 3132fcea6f3dSAnirudh Venkataramanan return -EIO; 3133fcea6f3dSAnirudh Venkataramanan 3134fcea6f3dSAnirudh Venkataramanan return 0; 3135fcea6f3dSAnirudh Venkataramanan } 3136fcea6f3dSAnirudh Venkataramanan 313787324e74SHenry Tieman /** 313887324e74SHenry Tieman * ice_get_max_txq - return the maximum number of Tx queues for in a PF 313987324e74SHenry Tieman * @pf: PF structure 314087324e74SHenry Tieman */ 314187324e74SHenry Tieman static int ice_get_max_txq(struct ice_pf *pf) 314287324e74SHenry Tieman { 314387324e74SHenry Tieman return min_t(int, num_online_cpus(), 314487324e74SHenry Tieman pf->hw.func_caps.common_cap.num_txq); 314587324e74SHenry Tieman } 314687324e74SHenry Tieman 314787324e74SHenry Tieman /** 314887324e74SHenry Tieman * ice_get_max_rxq - return the maximum number of Rx queues for in a PF 314987324e74SHenry Tieman * @pf: PF structure 315087324e74SHenry Tieman */ 315187324e74SHenry Tieman static int ice_get_max_rxq(struct ice_pf *pf) 315287324e74SHenry Tieman { 315387324e74SHenry Tieman return min_t(int, num_online_cpus(), 315487324e74SHenry Tieman pf->hw.func_caps.common_cap.num_rxq); 315587324e74SHenry Tieman } 315687324e74SHenry Tieman 315787324e74SHenry Tieman /** 315887324e74SHenry Tieman * ice_get_combined_cnt - return the current number of combined channels 315987324e74SHenry Tieman * @vsi: PF VSI pointer 316087324e74SHenry Tieman * 316187324e74SHenry Tieman * Go through all queue vectors and count ones that have both Rx and Tx ring 316287324e74SHenry Tieman * attached 316387324e74SHenry Tieman */ 316487324e74SHenry Tieman static u32 ice_get_combined_cnt(struct ice_vsi *vsi) 316587324e74SHenry Tieman { 316687324e74SHenry Tieman u32 combined = 0; 316787324e74SHenry Tieman int q_idx; 316887324e74SHenry Tieman 316987324e74SHenry Tieman ice_for_each_q_vector(vsi, q_idx) { 317087324e74SHenry Tieman struct ice_q_vector *q_vector = vsi->q_vectors[q_idx]; 317187324e74SHenry Tieman 317287324e74SHenry Tieman if (q_vector->rx.ring && q_vector->tx.ring) 317387324e74SHenry Tieman combined++; 317487324e74SHenry Tieman } 317587324e74SHenry Tieman 317687324e74SHenry Tieman return combined; 317787324e74SHenry Tieman } 317887324e74SHenry Tieman 317987324e74SHenry Tieman /** 318087324e74SHenry Tieman * ice_get_channels - get the current and max supported channels 318187324e74SHenry Tieman * @dev: network interface device structure 318287324e74SHenry Tieman * @ch: ethtool channel data structure 318387324e74SHenry Tieman */ 318487324e74SHenry Tieman static void 318587324e74SHenry Tieman ice_get_channels(struct net_device *dev, struct ethtool_channels *ch) 318687324e74SHenry Tieman { 318787324e74SHenry Tieman struct ice_netdev_priv *np = netdev_priv(dev); 318887324e74SHenry Tieman struct ice_vsi *vsi = np->vsi; 318987324e74SHenry Tieman struct ice_pf *pf = vsi->back; 319087324e74SHenry Tieman 319187324e74SHenry Tieman /* check to see if VSI is active */ 319287324e74SHenry Tieman if (test_bit(__ICE_DOWN, vsi->state)) 319387324e74SHenry Tieman return; 319487324e74SHenry Tieman 319587324e74SHenry Tieman /* report maximum channels */ 319687324e74SHenry Tieman ch->max_rx = ice_get_max_rxq(pf); 319787324e74SHenry Tieman ch->max_tx = ice_get_max_txq(pf); 319887324e74SHenry Tieman ch->max_combined = min_t(int, ch->max_rx, ch->max_tx); 319987324e74SHenry Tieman 320087324e74SHenry Tieman /* report current channels */ 320187324e74SHenry Tieman ch->combined_count = ice_get_combined_cnt(vsi); 320287324e74SHenry Tieman ch->rx_count = vsi->num_rxq - ch->combined_count; 320387324e74SHenry Tieman ch->tx_count = vsi->num_txq - ch->combined_count; 3204148beb61SHenry Tieman 3205148beb61SHenry Tieman /* report other queues */ 3206148beb61SHenry Tieman ch->other_count = test_bit(ICE_FLAG_FD_ENA, pf->flags) ? 1 : 0; 3207148beb61SHenry Tieman ch->max_other = ch->other_count; 320887324e74SHenry Tieman } 320987324e74SHenry Tieman 321087324e74SHenry Tieman /** 321187324e74SHenry Tieman * ice_vsi_set_dflt_rss_lut - set default RSS LUT with requested RSS size 321287324e74SHenry Tieman * @vsi: VSI to reconfigure RSS LUT on 321387324e74SHenry Tieman * @req_rss_size: requested range of queue numbers for hashing 321487324e74SHenry Tieman * 321587324e74SHenry Tieman * Set the VSI's RSS parameters, configure the RSS LUT based on these. 321687324e74SHenry Tieman */ 321787324e74SHenry Tieman static int ice_vsi_set_dflt_rss_lut(struct ice_vsi *vsi, int req_rss_size) 321887324e74SHenry Tieman { 321987324e74SHenry Tieman struct ice_pf *pf = vsi->back; 322087324e74SHenry Tieman enum ice_status status; 322187324e74SHenry Tieman struct device *dev; 322287324e74SHenry Tieman struct ice_hw *hw; 322387324e74SHenry Tieman int err = 0; 322487324e74SHenry Tieman u8 *lut; 322587324e74SHenry Tieman 322687324e74SHenry Tieman dev = ice_pf_to_dev(pf); 322787324e74SHenry Tieman hw = &pf->hw; 322887324e74SHenry Tieman 322987324e74SHenry Tieman if (!req_rss_size) 323087324e74SHenry Tieman return -EINVAL; 323187324e74SHenry Tieman 323287324e74SHenry Tieman lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); 323387324e74SHenry Tieman if (!lut) 323487324e74SHenry Tieman return -ENOMEM; 323587324e74SHenry Tieman 323687324e74SHenry Tieman /* set RSS LUT parameters */ 323787324e74SHenry Tieman if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 323887324e74SHenry Tieman vsi->rss_size = 1; 323987324e74SHenry Tieman } else { 324087324e74SHenry Tieman struct ice_hw_common_caps *caps = &hw->func_caps.common_cap; 324187324e74SHenry Tieman 324287324e74SHenry Tieman vsi->rss_size = min_t(int, req_rss_size, 324387324e74SHenry Tieman BIT(caps->rss_table_entry_width)); 324487324e74SHenry Tieman } 324587324e74SHenry Tieman 324687324e74SHenry Tieman /* create/set RSS LUT */ 324787324e74SHenry Tieman ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); 324887324e74SHenry Tieman status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type, lut, 324987324e74SHenry Tieman vsi->rss_table_size); 325087324e74SHenry Tieman if (status) { 32510fee3577SLihong Yang dev_err(dev, "Cannot set RSS lut, err %s aq_err %s\n", 32520fee3577SLihong Yang ice_stat_str(status), 32530fee3577SLihong Yang ice_aq_str(hw->adminq.rq_last_status)); 325487324e74SHenry Tieman err = -EIO; 325587324e74SHenry Tieman } 325687324e74SHenry Tieman 325787324e74SHenry Tieman kfree(lut); 325887324e74SHenry Tieman return err; 325987324e74SHenry Tieman } 326087324e74SHenry Tieman 326187324e74SHenry Tieman /** 326287324e74SHenry Tieman * ice_set_channels - set the number channels 326387324e74SHenry Tieman * @dev: network interface device structure 326487324e74SHenry Tieman * @ch: ethtool channel data structure 326587324e74SHenry Tieman */ 326687324e74SHenry Tieman static int ice_set_channels(struct net_device *dev, struct ethtool_channels *ch) 326787324e74SHenry Tieman { 326887324e74SHenry Tieman struct ice_netdev_priv *np = netdev_priv(dev); 326987324e74SHenry Tieman struct ice_vsi *vsi = np->vsi; 327087324e74SHenry Tieman struct ice_pf *pf = vsi->back; 327187324e74SHenry Tieman int new_rx = 0, new_tx = 0; 327287324e74SHenry Tieman u32 curr_combined; 327387324e74SHenry Tieman 327487324e74SHenry Tieman /* do not support changing channels in Safe Mode */ 327587324e74SHenry Tieman if (ice_is_safe_mode(pf)) { 327687324e74SHenry Tieman netdev_err(dev, "Changing channel in Safe Mode is not supported\n"); 327787324e74SHenry Tieman return -EOPNOTSUPP; 327887324e74SHenry Tieman } 327987324e74SHenry Tieman /* do not support changing other_count */ 3280148beb61SHenry Tieman if (ch->other_count != (test_bit(ICE_FLAG_FD_ENA, pf->flags) ? 1U : 0U)) 328187324e74SHenry Tieman return -EINVAL; 328287324e74SHenry Tieman 3283148beb61SHenry Tieman if (test_bit(ICE_FLAG_FD_ENA, pf->flags) && pf->hw.fdir_active_fltr) { 3284148beb61SHenry Tieman netdev_err(dev, "Cannot set channels when Flow Director filters are active\n"); 3285148beb61SHenry Tieman return -EOPNOTSUPP; 3286148beb61SHenry Tieman } 3287148beb61SHenry Tieman 328887324e74SHenry Tieman curr_combined = ice_get_combined_cnt(vsi); 328987324e74SHenry Tieman 329087324e74SHenry Tieman /* these checks are for cases where user didn't specify a particular 329187324e74SHenry Tieman * value on cmd line but we get non-zero value anyway via 329287324e74SHenry Tieman * get_channels(); look at ethtool.c in ethtool repository (the user 329387324e74SHenry Tieman * space part), particularly, do_schannels() routine 329487324e74SHenry Tieman */ 329587324e74SHenry Tieman if (ch->rx_count == vsi->num_rxq - curr_combined) 329687324e74SHenry Tieman ch->rx_count = 0; 329787324e74SHenry Tieman if (ch->tx_count == vsi->num_txq - curr_combined) 329887324e74SHenry Tieman ch->tx_count = 0; 329987324e74SHenry Tieman if (ch->combined_count == curr_combined) 330087324e74SHenry Tieman ch->combined_count = 0; 330187324e74SHenry Tieman 330287324e74SHenry Tieman if (!(ch->combined_count || (ch->rx_count && ch->tx_count))) { 330387324e74SHenry Tieman netdev_err(dev, "Please specify at least 1 Rx and 1 Tx channel\n"); 330487324e74SHenry Tieman return -EINVAL; 330587324e74SHenry Tieman } 330687324e74SHenry Tieman 330787324e74SHenry Tieman new_rx = ch->combined_count + ch->rx_count; 330887324e74SHenry Tieman new_tx = ch->combined_count + ch->tx_count; 330987324e74SHenry Tieman 331087324e74SHenry Tieman if (new_rx > ice_get_max_rxq(pf)) { 331187324e74SHenry Tieman netdev_err(dev, "Maximum allowed Rx channels is %d\n", 331287324e74SHenry Tieman ice_get_max_rxq(pf)); 331387324e74SHenry Tieman return -EINVAL; 331487324e74SHenry Tieman } 331587324e74SHenry Tieman if (new_tx > ice_get_max_txq(pf)) { 331687324e74SHenry Tieman netdev_err(dev, "Maximum allowed Tx channels is %d\n", 331787324e74SHenry Tieman ice_get_max_txq(pf)); 331887324e74SHenry Tieman return -EINVAL; 331987324e74SHenry Tieman } 332087324e74SHenry Tieman 332187324e74SHenry Tieman ice_vsi_recfg_qs(vsi, new_rx, new_tx); 332287324e74SHenry Tieman 332387324e74SHenry Tieman if (new_rx && !netif_is_rxfh_configured(dev)) 332487324e74SHenry Tieman return ice_vsi_set_dflt_rss_lut(vsi, new_rx); 332587324e74SHenry Tieman 332687324e74SHenry Tieman return 0; 332787324e74SHenry Tieman } 332887324e74SHenry Tieman 332967fe64d7SBrett Creeley enum ice_container_type { 333067fe64d7SBrett Creeley ICE_RX_CONTAINER, 333167fe64d7SBrett Creeley ICE_TX_CONTAINER, 333267fe64d7SBrett Creeley }; 333367fe64d7SBrett Creeley 333467fe64d7SBrett Creeley /** 333567fe64d7SBrett Creeley * ice_get_rc_coalesce - get ITR values for specific ring container 333667fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 3337f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 333867fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 333967fe64d7SBrett Creeley * 334067fe64d7SBrett Creeley * Query the device for ice_ring_container specific ITR values. This is 334167fe64d7SBrett Creeley * done per ice_ring_container because each q_vector can have 1 or more rings 334267fe64d7SBrett Creeley * and all of said ring(s) will have the same ITR values. 334367fe64d7SBrett Creeley * 334467fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 334567fe64d7SBrett Creeley */ 334667fe64d7SBrett Creeley static int 334767fe64d7SBrett Creeley ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, 334867fe64d7SBrett Creeley struct ice_ring_container *rc) 334967fe64d7SBrett Creeley { 3350b9c8bb06SBrett Creeley struct ice_pf *pf; 3351b9c8bb06SBrett Creeley 3352b9c8bb06SBrett Creeley if (!rc->ring) 3353b9c8bb06SBrett Creeley return -EINVAL; 3354b9c8bb06SBrett Creeley 3355b9c8bb06SBrett Creeley pf = rc->ring->vsi->back; 335667fe64d7SBrett Creeley 335767fe64d7SBrett Creeley switch (c_type) { 335867fe64d7SBrett Creeley case ICE_RX_CONTAINER: 335967fe64d7SBrett Creeley ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 336067fe64d7SBrett Creeley ec->rx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 3361b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high = rc->ring->q_vector->intrl; 336267fe64d7SBrett Creeley break; 336367fe64d7SBrett Creeley case ICE_TX_CONTAINER: 336467fe64d7SBrett Creeley ec->use_adaptive_tx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); 336567fe64d7SBrett Creeley ec->tx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; 336667fe64d7SBrett Creeley break; 336767fe64d7SBrett Creeley default: 33684015d11eSBrett Creeley dev_dbg(ice_pf_to_dev(pf), "Invalid c_type %d\n", c_type); 336967fe64d7SBrett Creeley return -EINVAL; 337067fe64d7SBrett Creeley } 337167fe64d7SBrett Creeley 337267fe64d7SBrett Creeley return 0; 337367fe64d7SBrett Creeley } 337467fe64d7SBrett Creeley 337567fe64d7SBrett Creeley /** 3376e40c899aSBrett Creeley * ice_get_q_coalesce - get a queue's ITR/INTRL (coalesce) settings 3377e40c899aSBrett Creeley * @vsi: VSI associated to the queue for getting ITR/INTRL (coalesce) settings 3378e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 3379e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 3380e40c899aSBrett Creeley * 3381e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 3382e40c899aSBrett Creeley * 1. Getting Tx or Rx ITR/INTRL (coalesce) settings failed. 3383e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 3384e40c899aSBrett Creeley */ 3385e40c899aSBrett Creeley static int 3386e40c899aSBrett Creeley ice_get_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 3387e40c899aSBrett Creeley { 3388e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 3389e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 3390e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 3391e40c899aSBrett Creeley return -EINVAL; 3392e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 3393e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 3394e40c899aSBrett Creeley return -EINVAL; 3395e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 3396e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_RX_CONTAINER, 3397e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx)) 3398e40c899aSBrett Creeley return -EINVAL; 3399e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 3400e40c899aSBrett Creeley if (ice_get_rc_coalesce(ec, ICE_TX_CONTAINER, 3401e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx)) 3402e40c899aSBrett Creeley return -EINVAL; 3403e40c899aSBrett Creeley } else { 3404e40c899aSBrett Creeley return -EINVAL; 3405e40c899aSBrett Creeley } 3406e40c899aSBrett Creeley 3407e40c899aSBrett Creeley return 0; 3408e40c899aSBrett Creeley } 3409e40c899aSBrett Creeley 3410e40c899aSBrett Creeley /** 341167fe64d7SBrett Creeley * __ice_get_coalesce - get ITR/INTRL values for the device 341267fe64d7SBrett Creeley * @netdev: pointer to the netdev associated with this query 341367fe64d7SBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 341467fe64d7SBrett Creeley * @q_num: queue number to get the coalesce settings for 3415e40c899aSBrett Creeley * 3416e40c899aSBrett Creeley * If the caller passes in a negative q_num then we return coalesce settings 3417e40c899aSBrett Creeley * based on queue number 0, else use the actual q_num passed in. 341867fe64d7SBrett Creeley */ 341967fe64d7SBrett Creeley static int 342067fe64d7SBrett Creeley __ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 342167fe64d7SBrett Creeley int q_num) 342267fe64d7SBrett Creeley { 342367fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 342467fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 342567fe64d7SBrett Creeley 3426e40c899aSBrett Creeley if (q_num < 0) 3427e40c899aSBrett Creeley q_num = 0; 342867fe64d7SBrett Creeley 3429e40c899aSBrett Creeley if (ice_get_q_coalesce(vsi, ec, q_num)) 343067fe64d7SBrett Creeley return -EINVAL; 343167fe64d7SBrett Creeley 343267fe64d7SBrett Creeley return 0; 343367fe64d7SBrett Creeley } 343467fe64d7SBrett Creeley 343567fe64d7SBrett Creeley static int 343667fe64d7SBrett Creeley ice_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 343767fe64d7SBrett Creeley { 343867fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, -1); 343967fe64d7SBrett Creeley } 344067fe64d7SBrett Creeley 3441c8b7abddSBruce Allan static int 3442c8b7abddSBruce Allan ice_get_per_q_coalesce(struct net_device *netdev, u32 q_num, 344367fe64d7SBrett Creeley struct ethtool_coalesce *ec) 344467fe64d7SBrett Creeley { 344567fe64d7SBrett Creeley return __ice_get_coalesce(netdev, ec, q_num); 344667fe64d7SBrett Creeley } 344767fe64d7SBrett Creeley 344867fe64d7SBrett Creeley /** 344967fe64d7SBrett Creeley * ice_set_rc_coalesce - set ITR values for specific ring container 3450f9867df6SAnirudh Venkataramanan * @c_type: container type, Rx or Tx 345167fe64d7SBrett Creeley * @ec: ethtool structure from user to update ITR settings 345267fe64d7SBrett Creeley * @rc: ring container that the ITR values will come from 345367fe64d7SBrett Creeley * @vsi: VSI associated to the ring container 345467fe64d7SBrett Creeley * 345567fe64d7SBrett Creeley * Set specific ITR values. This is done per ice_ring_container because each 345667fe64d7SBrett Creeley * q_vector can have 1 or more rings and all of said ring(s) will have the same 345767fe64d7SBrett Creeley * ITR values. 345867fe64d7SBrett Creeley * 345967fe64d7SBrett Creeley * Returns 0 on success, negative otherwise. 346067fe64d7SBrett Creeley */ 346167fe64d7SBrett Creeley static int 346267fe64d7SBrett Creeley ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec, 346367fe64d7SBrett Creeley struct ice_ring_container *rc, struct ice_vsi *vsi) 346467fe64d7SBrett Creeley { 3465567af267SBrett Creeley const char *c_type_str = (c_type == ICE_RX_CONTAINER) ? "rx" : "tx"; 3466567af267SBrett Creeley u32 use_adaptive_coalesce, coalesce_usecs; 346767fe64d7SBrett Creeley struct ice_pf *pf = vsi->back; 346867fe64d7SBrett Creeley u16 itr_setting; 346967fe64d7SBrett Creeley 347067fe64d7SBrett Creeley if (!rc->ring) 347167fe64d7SBrett Creeley return -EINVAL; 347267fe64d7SBrett Creeley 347367fe64d7SBrett Creeley switch (c_type) { 347467fe64d7SBrett Creeley case ICE_RX_CONTAINER: 3475b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high > ICE_MAX_INTRL || 3476b9c8bb06SBrett Creeley (ec->rx_coalesce_usecs_high && 3477b9c8bb06SBrett Creeley ec->rx_coalesce_usecs_high < pf->hw.intrl_gran)) { 347819cce2c6SAnirudh Venkataramanan netdev_info(vsi->netdev, "Invalid value, %s-usecs-high valid values are 0 (disabled), %d-%d\n", 3479567af267SBrett Creeley c_type_str, pf->hw.intrl_gran, 3480567af267SBrett Creeley ICE_MAX_INTRL); 3481b9c8bb06SBrett Creeley return -EINVAL; 3482b9c8bb06SBrett Creeley } 3483b9c8bb06SBrett Creeley if (ec->rx_coalesce_usecs_high != rc->ring->q_vector->intrl) { 3484b9c8bb06SBrett Creeley rc->ring->q_vector->intrl = ec->rx_coalesce_usecs_high; 3485cbe66bfeSBrett Creeley wr32(&pf->hw, GLINT_RATE(rc->ring->q_vector->reg_idx), 3486b9c8bb06SBrett Creeley ice_intrl_usec_to_reg(ec->rx_coalesce_usecs_high, 3487b9c8bb06SBrett Creeley pf->hw.intrl_gran)); 3488b9c8bb06SBrett Creeley } 3489b9c8bb06SBrett Creeley 3490567af267SBrett Creeley use_adaptive_coalesce = ec->use_adaptive_rx_coalesce; 3491567af267SBrett Creeley coalesce_usecs = ec->rx_coalesce_usecs; 349267fe64d7SBrett Creeley 349367fe64d7SBrett Creeley break; 349467fe64d7SBrett Creeley case ICE_TX_CONTAINER: 3495567af267SBrett Creeley use_adaptive_coalesce = ec->use_adaptive_tx_coalesce; 3496567af267SBrett Creeley coalesce_usecs = ec->tx_coalesce_usecs; 349767fe64d7SBrett Creeley 349867fe64d7SBrett Creeley break; 349967fe64d7SBrett Creeley default: 35004015d11eSBrett Creeley dev_dbg(ice_pf_to_dev(pf), "Invalid container type %d\n", 35014015d11eSBrett Creeley c_type); 350267fe64d7SBrett Creeley return -EINVAL; 350367fe64d7SBrett Creeley } 350467fe64d7SBrett Creeley 3505567af267SBrett Creeley itr_setting = rc->itr_setting & ~ICE_ITR_DYNAMIC; 3506567af267SBrett Creeley if (coalesce_usecs != itr_setting && use_adaptive_coalesce) { 350719cce2c6SAnirudh Venkataramanan netdev_info(vsi->netdev, "%s interrupt throttling cannot be changed if adaptive-%s is enabled\n", 3508567af267SBrett Creeley c_type_str, c_type_str); 3509567af267SBrett Creeley return -EINVAL; 3510567af267SBrett Creeley } 3511567af267SBrett Creeley 3512567af267SBrett Creeley if (coalesce_usecs > ICE_ITR_MAX) { 351319cce2c6SAnirudh Venkataramanan netdev_info(vsi->netdev, "Invalid value, %s-usecs range is 0-%d\n", 3514567af267SBrett Creeley c_type_str, ICE_ITR_MAX); 3515567af267SBrett Creeley return -EINVAL; 3516567af267SBrett Creeley } 3517567af267SBrett Creeley 3518567af267SBrett Creeley if (use_adaptive_coalesce) { 3519567af267SBrett Creeley rc->itr_setting |= ICE_ITR_DYNAMIC; 3520567af267SBrett Creeley } else { 3521840f8ad0SBrett Creeley /* save the user set usecs */ 3522567af267SBrett Creeley rc->itr_setting = coalesce_usecs; 3523840f8ad0SBrett Creeley /* device ITR granularity is in 2 usec increments */ 3524840f8ad0SBrett Creeley rc->target_itr = ITR_REG_ALIGN(rc->itr_setting); 3525567af267SBrett Creeley } 3526567af267SBrett Creeley 352767fe64d7SBrett Creeley return 0; 352867fe64d7SBrett Creeley } 352967fe64d7SBrett Creeley 3530e40c899aSBrett Creeley /** 3531e40c899aSBrett Creeley * ice_set_q_coalesce - set a queue's ITR/INTRL (coalesce) settings 3532e40c899aSBrett Creeley * @vsi: VSI associated to the queue that need updating 3533e40c899aSBrett Creeley * @ec: coalesce settings to program the device with 3534e40c899aSBrett Creeley * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index 3535e40c899aSBrett Creeley * 3536e40c899aSBrett Creeley * Return 0 on success, and negative under the following conditions: 3537e40c899aSBrett Creeley * 1. Setting Tx or Rx ITR/INTRL (coalesce) settings failed. 3538e40c899aSBrett Creeley * 2. The q_num passed in is not a valid number/index for Tx and Rx rings. 3539e40c899aSBrett Creeley */ 3540e40c899aSBrett Creeley static int 3541e40c899aSBrett Creeley ice_set_q_coalesce(struct ice_vsi *vsi, struct ethtool_coalesce *ec, int q_num) 3542e40c899aSBrett Creeley { 3543e40c899aSBrett Creeley if (q_num < vsi->num_rxq && q_num < vsi->num_txq) { 3544e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 3545e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 3546e40c899aSBrett Creeley vsi)) 3547e40c899aSBrett Creeley return -EINVAL; 3548e40c899aSBrett Creeley 3549e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 3550e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 3551e40c899aSBrett Creeley vsi)) 3552e40c899aSBrett Creeley return -EINVAL; 3553e40c899aSBrett Creeley } else if (q_num < vsi->num_rxq) { 3554e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_RX_CONTAINER, ec, 3555e40c899aSBrett Creeley &vsi->rx_rings[q_num]->q_vector->rx, 3556e40c899aSBrett Creeley vsi)) 3557e40c899aSBrett Creeley return -EINVAL; 3558e40c899aSBrett Creeley } else if (q_num < vsi->num_txq) { 3559e40c899aSBrett Creeley if (ice_set_rc_coalesce(ICE_TX_CONTAINER, ec, 3560e40c899aSBrett Creeley &vsi->tx_rings[q_num]->q_vector->tx, 3561e40c899aSBrett Creeley vsi)) 3562e40c899aSBrett Creeley return -EINVAL; 3563e40c899aSBrett Creeley } else { 3564e40c899aSBrett Creeley return -EINVAL; 3565e40c899aSBrett Creeley } 3566e40c899aSBrett Creeley 3567e40c899aSBrett Creeley return 0; 3568e40c899aSBrett Creeley } 3569e40c899aSBrett Creeley 3570e40c899aSBrett Creeley /** 3571840f8ad0SBrett Creeley * ice_print_if_odd_usecs - print message if user tries to set odd [tx|rx]-usecs 3572840f8ad0SBrett Creeley * @netdev: netdev used for print 3573840f8ad0SBrett Creeley * @itr_setting: previous user setting 3574840f8ad0SBrett Creeley * @use_adaptive_coalesce: if adaptive coalesce is enabled or being enabled 3575840f8ad0SBrett Creeley * @coalesce_usecs: requested value of [tx|rx]-usecs 3576840f8ad0SBrett Creeley * @c_type_str: either "rx" or "tx" to match user set field of [tx|rx]-usecs 3577840f8ad0SBrett Creeley */ 3578840f8ad0SBrett Creeley static void 3579840f8ad0SBrett Creeley ice_print_if_odd_usecs(struct net_device *netdev, u16 itr_setting, 3580840f8ad0SBrett Creeley u32 use_adaptive_coalesce, u32 coalesce_usecs, 3581840f8ad0SBrett Creeley const char *c_type_str) 3582840f8ad0SBrett Creeley { 3583840f8ad0SBrett Creeley if (use_adaptive_coalesce) 3584840f8ad0SBrett Creeley return; 3585840f8ad0SBrett Creeley 3586840f8ad0SBrett Creeley itr_setting = ITR_TO_REG(itr_setting); 3587840f8ad0SBrett Creeley 3588840f8ad0SBrett Creeley if (itr_setting != coalesce_usecs && (coalesce_usecs % 2)) 3589840f8ad0SBrett Creeley netdev_info(netdev, "User set %s-usecs to %d, device only supports even values. Rounding down and attempting to set %s-usecs to %d\n", 3590840f8ad0SBrett Creeley c_type_str, coalesce_usecs, c_type_str, 3591840f8ad0SBrett Creeley ITR_REG_ALIGN(coalesce_usecs)); 3592840f8ad0SBrett Creeley } 3593840f8ad0SBrett Creeley 3594840f8ad0SBrett Creeley /** 3595e40c899aSBrett Creeley * __ice_set_coalesce - set ITR/INTRL values for the device 3596e40c899aSBrett Creeley * @netdev: pointer to the netdev associated with this query 3597e40c899aSBrett Creeley * @ec: ethtool structure to fill with driver's coalesce settings 3598e40c899aSBrett Creeley * @q_num: queue number to get the coalesce settings for 3599e40c899aSBrett Creeley * 3600e40c899aSBrett Creeley * If the caller passes in a negative q_num then we set the coalesce settings 3601e40c899aSBrett Creeley * for all Tx/Rx queues, else use the actual q_num passed in. 3602e40c899aSBrett Creeley */ 360367fe64d7SBrett Creeley static int 360467fe64d7SBrett Creeley __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, 360567fe64d7SBrett Creeley int q_num) 360667fe64d7SBrett Creeley { 360767fe64d7SBrett Creeley struct ice_netdev_priv *np = netdev_priv(netdev); 360867fe64d7SBrett Creeley struct ice_vsi *vsi = np->vsi; 360967fe64d7SBrett Creeley 361067fe64d7SBrett Creeley if (q_num < 0) { 3611840f8ad0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[0]; 3612e25f9152SBrett Creeley int v_idx; 361367fe64d7SBrett Creeley 3614840f8ad0SBrett Creeley if (q_vector) { 3615840f8ad0SBrett Creeley ice_print_if_odd_usecs(netdev, q_vector->rx.itr_setting, 3616840f8ad0SBrett Creeley ec->use_adaptive_rx_coalesce, 3617840f8ad0SBrett Creeley ec->rx_coalesce_usecs, "rx"); 3618840f8ad0SBrett Creeley 3619840f8ad0SBrett Creeley ice_print_if_odd_usecs(netdev, q_vector->tx.itr_setting, 3620840f8ad0SBrett Creeley ec->use_adaptive_tx_coalesce, 3621840f8ad0SBrett Creeley ec->tx_coalesce_usecs, "tx"); 3622840f8ad0SBrett Creeley } 3623840f8ad0SBrett Creeley 3624e25f9152SBrett Creeley ice_for_each_q_vector(vsi, v_idx) { 3625e25f9152SBrett Creeley /* In some cases if DCB is configured the num_[rx|tx]q 3626e25f9152SBrett Creeley * can be less than vsi->num_q_vectors. This check 3627e25f9152SBrett Creeley * accounts for that so we don't report a false failure 3628e25f9152SBrett Creeley */ 3629e25f9152SBrett Creeley if (v_idx >= vsi->num_rxq && v_idx >= vsi->num_txq) 3630e25f9152SBrett Creeley goto set_complete; 3631e25f9152SBrett Creeley 3632e25f9152SBrett Creeley if (ice_set_q_coalesce(vsi, ec, v_idx)) 363367fe64d7SBrett Creeley return -EINVAL; 363467fe64d7SBrett Creeley } 36359d56b7fdSJesse Brandeburg goto set_complete; 363667fe64d7SBrett Creeley } 363767fe64d7SBrett Creeley 3638e40c899aSBrett Creeley if (ice_set_q_coalesce(vsi, ec, q_num)) 363967fe64d7SBrett Creeley return -EINVAL; 364067fe64d7SBrett Creeley 36419d56b7fdSJesse Brandeburg set_complete: 364267fe64d7SBrett Creeley 364367fe64d7SBrett Creeley return 0; 364467fe64d7SBrett Creeley } 364567fe64d7SBrett Creeley 364667fe64d7SBrett Creeley static int 364767fe64d7SBrett Creeley ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) 364867fe64d7SBrett Creeley { 364967fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, -1); 365067fe64d7SBrett Creeley } 365167fe64d7SBrett Creeley 3652c8b7abddSBruce Allan static int 3653c8b7abddSBruce Allan ice_set_per_q_coalesce(struct net_device *netdev, u32 q_num, 365467fe64d7SBrett Creeley struct ethtool_coalesce *ec) 365567fe64d7SBrett Creeley { 365667fe64d7SBrett Creeley return __ice_set_coalesce(netdev, ec, q_num); 365767fe64d7SBrett Creeley } 365867fe64d7SBrett Creeley 3659a012dca9SScott W Taylor #define ICE_I2C_EEPROM_DEV_ADDR 0xA0 3660a012dca9SScott W Taylor #define ICE_I2C_EEPROM_DEV_ADDR2 0xA2 3661a012dca9SScott W Taylor #define ICE_MODULE_TYPE_SFP 0x03 3662a012dca9SScott W Taylor #define ICE_MODULE_TYPE_QSFP_PLUS 0x0D 3663a012dca9SScott W Taylor #define ICE_MODULE_TYPE_QSFP28 0x11 3664a012dca9SScott W Taylor #define ICE_MODULE_SFF_ADDR_MODE 0x04 3665a012dca9SScott W Taylor #define ICE_MODULE_SFF_DIAG_CAPAB 0x40 3666a012dca9SScott W Taylor #define ICE_MODULE_REVISION_ADDR 0x01 3667a012dca9SScott W Taylor #define ICE_MODULE_SFF_8472_COMP 0x5E 3668a012dca9SScott W Taylor #define ICE_MODULE_SFF_8472_SWAP 0x5C 3669a012dca9SScott W Taylor #define ICE_MODULE_QSFP_MAX_LEN 640 3670a012dca9SScott W Taylor 3671a012dca9SScott W Taylor /** 3672a012dca9SScott W Taylor * ice_get_module_info - get SFF module type and revision information 3673a012dca9SScott W Taylor * @netdev: network interface device structure 3674a012dca9SScott W Taylor * @modinfo: module EEPROM size and layout information structure 3675a012dca9SScott W Taylor */ 3676a012dca9SScott W Taylor static int 3677a012dca9SScott W Taylor ice_get_module_info(struct net_device *netdev, 3678a012dca9SScott W Taylor struct ethtool_modinfo *modinfo) 3679a012dca9SScott W Taylor { 3680a012dca9SScott W Taylor struct ice_netdev_priv *np = netdev_priv(netdev); 3681a012dca9SScott W Taylor struct ice_vsi *vsi = np->vsi; 3682a012dca9SScott W Taylor struct ice_pf *pf = vsi->back; 3683a012dca9SScott W Taylor struct ice_hw *hw = &pf->hw; 3684a012dca9SScott W Taylor enum ice_status status; 3685a012dca9SScott W Taylor u8 sff8472_comp = 0; 3686a012dca9SScott W Taylor u8 sff8472_swap = 0; 3687a012dca9SScott W Taylor u8 sff8636_rev = 0; 3688a012dca9SScott W Taylor u8 value = 0; 3689a012dca9SScott W Taylor 3690a012dca9SScott W Taylor status = ice_aq_sff_eeprom(hw, 0, ICE_I2C_EEPROM_DEV_ADDR, 0x00, 0x00, 3691a012dca9SScott W Taylor 0, &value, 1, 0, NULL); 3692a012dca9SScott W Taylor if (status) 3693a012dca9SScott W Taylor return -EIO; 3694a012dca9SScott W Taylor 3695a012dca9SScott W Taylor switch (value) { 3696a012dca9SScott W Taylor case ICE_MODULE_TYPE_SFP: 3697a012dca9SScott W Taylor status = ice_aq_sff_eeprom(hw, 0, ICE_I2C_EEPROM_DEV_ADDR, 3698a012dca9SScott W Taylor ICE_MODULE_SFF_8472_COMP, 0x00, 0, 3699a012dca9SScott W Taylor &sff8472_comp, 1, 0, NULL); 3700a012dca9SScott W Taylor if (status) 3701a012dca9SScott W Taylor return -EIO; 3702a012dca9SScott W Taylor status = ice_aq_sff_eeprom(hw, 0, ICE_I2C_EEPROM_DEV_ADDR, 3703a012dca9SScott W Taylor ICE_MODULE_SFF_8472_SWAP, 0x00, 0, 3704a012dca9SScott W Taylor &sff8472_swap, 1, 0, NULL); 3705a012dca9SScott W Taylor if (status) 3706a012dca9SScott W Taylor return -EIO; 3707a012dca9SScott W Taylor 3708a012dca9SScott W Taylor if (sff8472_swap & ICE_MODULE_SFF_ADDR_MODE) { 3709a012dca9SScott W Taylor modinfo->type = ETH_MODULE_SFF_8079; 3710a012dca9SScott W Taylor modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; 3711a012dca9SScott W Taylor } else if (sff8472_comp && 3712a012dca9SScott W Taylor (sff8472_swap & ICE_MODULE_SFF_DIAG_CAPAB)) { 3713a012dca9SScott W Taylor modinfo->type = ETH_MODULE_SFF_8472; 3714a012dca9SScott W Taylor modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 3715a012dca9SScott W Taylor } else { 3716a012dca9SScott W Taylor modinfo->type = ETH_MODULE_SFF_8079; 3717a012dca9SScott W Taylor modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; 3718a012dca9SScott W Taylor } 3719a012dca9SScott W Taylor break; 3720a012dca9SScott W Taylor case ICE_MODULE_TYPE_QSFP_PLUS: 3721a012dca9SScott W Taylor case ICE_MODULE_TYPE_QSFP28: 3722a012dca9SScott W Taylor status = ice_aq_sff_eeprom(hw, 0, ICE_I2C_EEPROM_DEV_ADDR, 3723a012dca9SScott W Taylor ICE_MODULE_REVISION_ADDR, 0x00, 0, 3724a012dca9SScott W Taylor &sff8636_rev, 1, 0, NULL); 3725a012dca9SScott W Taylor if (status) 3726a012dca9SScott W Taylor return -EIO; 3727a012dca9SScott W Taylor /* Check revision compliance */ 3728a012dca9SScott W Taylor if (sff8636_rev > 0x02) { 3729a012dca9SScott W Taylor /* Module is SFF-8636 compliant */ 3730a012dca9SScott W Taylor modinfo->type = ETH_MODULE_SFF_8636; 3731a012dca9SScott W Taylor modinfo->eeprom_len = ICE_MODULE_QSFP_MAX_LEN; 3732a012dca9SScott W Taylor } else { 3733a012dca9SScott W Taylor modinfo->type = ETH_MODULE_SFF_8436; 3734a012dca9SScott W Taylor modinfo->eeprom_len = ICE_MODULE_QSFP_MAX_LEN; 3735a012dca9SScott W Taylor } 3736a012dca9SScott W Taylor break; 3737a012dca9SScott W Taylor default: 373819cce2c6SAnirudh Venkataramanan netdev_warn(netdev, "SFF Module Type not recognized.\n"); 3739a012dca9SScott W Taylor return -EINVAL; 3740a012dca9SScott W Taylor } 3741a012dca9SScott W Taylor return 0; 3742a012dca9SScott W Taylor } 3743a012dca9SScott W Taylor 3744a012dca9SScott W Taylor /** 3745a012dca9SScott W Taylor * ice_get_module_eeprom - fill buffer with SFF EEPROM contents 3746a012dca9SScott W Taylor * @netdev: network interface device structure 3747a012dca9SScott W Taylor * @ee: EEPROM dump request structure 3748a012dca9SScott W Taylor * @data: buffer to be filled with EEPROM contents 3749a012dca9SScott W Taylor */ 3750a012dca9SScott W Taylor static int 3751a012dca9SScott W Taylor ice_get_module_eeprom(struct net_device *netdev, 3752a012dca9SScott W Taylor struct ethtool_eeprom *ee, u8 *data) 3753a012dca9SScott W Taylor { 3754a012dca9SScott W Taylor struct ice_netdev_priv *np = netdev_priv(netdev); 3755a012dca9SScott W Taylor u8 addr = ICE_I2C_EEPROM_DEV_ADDR; 3756a012dca9SScott W Taylor struct ice_vsi *vsi = np->vsi; 3757a012dca9SScott W Taylor struct ice_pf *pf = vsi->back; 3758a012dca9SScott W Taylor struct ice_hw *hw = &pf->hw; 3759a012dca9SScott W Taylor enum ice_status status; 3760a012dca9SScott W Taylor bool is_sfp = false; 3761a012dca9SScott W Taylor u16 offset = 0; 3762a012dca9SScott W Taylor u8 value = 0; 3763a012dca9SScott W Taylor u8 page = 0; 3764a012dca9SScott W Taylor int i; 3765a012dca9SScott W Taylor 3766a012dca9SScott W Taylor status = ice_aq_sff_eeprom(hw, 0, addr, offset, page, 0, 3767a012dca9SScott W Taylor &value, 1, 0, NULL); 3768a012dca9SScott W Taylor if (status) 3769a012dca9SScott W Taylor return -EIO; 3770a012dca9SScott W Taylor 3771a012dca9SScott W Taylor if (!ee || !ee->len || !data) 3772a012dca9SScott W Taylor return -EINVAL; 3773a012dca9SScott W Taylor 3774a012dca9SScott W Taylor if (value == ICE_MODULE_TYPE_SFP) 3775a012dca9SScott W Taylor is_sfp = true; 3776a012dca9SScott W Taylor 3777a012dca9SScott W Taylor for (i = 0; i < ee->len; i++) { 3778a012dca9SScott W Taylor offset = i + ee->offset; 3779a012dca9SScott W Taylor 3780a012dca9SScott W Taylor /* Check if we need to access the other memory page */ 3781a012dca9SScott W Taylor if (is_sfp) { 3782a012dca9SScott W Taylor if (offset >= ETH_MODULE_SFF_8079_LEN) { 3783a012dca9SScott W Taylor offset -= ETH_MODULE_SFF_8079_LEN; 3784a012dca9SScott W Taylor addr = ICE_I2C_EEPROM_DEV_ADDR2; 3785a012dca9SScott W Taylor } 3786a012dca9SScott W Taylor } else { 3787a012dca9SScott W Taylor while (offset >= ETH_MODULE_SFF_8436_LEN) { 3788a012dca9SScott W Taylor /* Compute memory page number and offset. */ 3789a012dca9SScott W Taylor offset -= ETH_MODULE_SFF_8436_LEN / 2; 3790a012dca9SScott W Taylor page++; 3791a012dca9SScott W Taylor } 3792a012dca9SScott W Taylor } 3793a012dca9SScott W Taylor 3794a012dca9SScott W Taylor status = ice_aq_sff_eeprom(hw, 0, addr, offset, page, !is_sfp, 3795a012dca9SScott W Taylor &value, 1, 0, NULL); 3796a012dca9SScott W Taylor if (status) 3797a012dca9SScott W Taylor value = 0; 3798a012dca9SScott W Taylor data[i] = value; 3799a012dca9SScott W Taylor } 3800a012dca9SScott W Taylor return 0; 3801a012dca9SScott W Taylor } 3802a012dca9SScott W Taylor 3803fcea6f3dSAnirudh Venkataramanan static const struct ethtool_ops ice_ethtool_ops = { 38044a80a183SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS | 38054a80a183SJakub Kicinski ETHTOOL_COALESCE_USE_ADAPTIVE | 38064a80a183SJakub Kicinski ETHTOOL_COALESCE_RX_USECS_HIGH, 3807fcea6f3dSAnirudh Venkataramanan .get_link_ksettings = ice_get_link_ksettings, 380848cb27f2SChinh Cao .set_link_ksettings = ice_set_link_ksettings, 3809fcea6f3dSAnirudh Venkataramanan .get_drvinfo = ice_get_drvinfo, 3810fcea6f3dSAnirudh Venkataramanan .get_regs_len = ice_get_regs_len, 3811fcea6f3dSAnirudh Venkataramanan .get_regs = ice_get_regs, 3812fcea6f3dSAnirudh Venkataramanan .get_msglevel = ice_get_msglevel, 3813fcea6f3dSAnirudh Venkataramanan .set_msglevel = ice_set_msglevel, 38140e674aebSAnirudh Venkataramanan .self_test = ice_self_test, 3815fcea6f3dSAnirudh Venkataramanan .get_link = ethtool_op_get_link, 38164c98ab55SBruce Allan .get_eeprom_len = ice_get_eeprom_len, 38174c98ab55SBruce Allan .get_eeprom = ice_get_eeprom, 381867fe64d7SBrett Creeley .get_coalesce = ice_get_coalesce, 381967fe64d7SBrett Creeley .set_coalesce = ice_set_coalesce, 3820fcea6f3dSAnirudh Venkataramanan .get_strings = ice_get_strings, 38218e151d50SAnirudh Venkataramanan .set_phys_id = ice_set_phys_id, 3822fcea6f3dSAnirudh Venkataramanan .get_ethtool_stats = ice_get_ethtool_stats, 3823ab4ab73fSBruce Allan .get_priv_flags = ice_get_priv_flags, 3824ab4ab73fSBruce Allan .set_priv_flags = ice_set_priv_flags, 3825fcea6f3dSAnirudh Venkataramanan .get_sset_count = ice_get_sset_count, 3826fcea6f3dSAnirudh Venkataramanan .get_rxnfc = ice_get_rxnfc, 38276876fb64SMd Fahad Iqbal Polash .set_rxnfc = ice_set_rxnfc, 3828fcea6f3dSAnirudh Venkataramanan .get_ringparam = ice_get_ringparam, 3829fcea6f3dSAnirudh Venkataramanan .set_ringparam = ice_set_ringparam, 3830fcea6f3dSAnirudh Venkataramanan .nway_reset = ice_nway_reset, 3831fcea6f3dSAnirudh Venkataramanan .get_pauseparam = ice_get_pauseparam, 3832fcea6f3dSAnirudh Venkataramanan .set_pauseparam = ice_set_pauseparam, 3833fcea6f3dSAnirudh Venkataramanan .get_rxfh_key_size = ice_get_rxfh_key_size, 3834fcea6f3dSAnirudh Venkataramanan .get_rxfh_indir_size = ice_get_rxfh_indir_size, 3835fcea6f3dSAnirudh Venkataramanan .get_rxfh = ice_get_rxfh, 3836fcea6f3dSAnirudh Venkataramanan .set_rxfh = ice_set_rxfh, 383787324e74SHenry Tieman .get_channels = ice_get_channels, 383887324e74SHenry Tieman .set_channels = ice_set_channels, 3839a8939784STony Nguyen .get_ts_info = ethtool_op_get_ts_info, 384067fe64d7SBrett Creeley .get_per_queue_coalesce = ice_get_per_q_coalesce, 384167fe64d7SBrett Creeley .set_per_queue_coalesce = ice_set_per_q_coalesce, 3842f776b3acSPaul Greenwalt .get_fecparam = ice_get_fecparam, 3843f776b3acSPaul Greenwalt .set_fecparam = ice_set_fecparam, 3844a012dca9SScott W Taylor .get_module_info = ice_get_module_info, 3845a012dca9SScott W Taylor .get_module_eeprom = ice_get_module_eeprom, 3846fcea6f3dSAnirudh Venkataramanan }; 3847fcea6f3dSAnirudh Venkataramanan 3848462acf6aSTony Nguyen static const struct ethtool_ops ice_ethtool_safe_mode_ops = { 3849462acf6aSTony Nguyen .get_link_ksettings = ice_get_link_ksettings, 3850462acf6aSTony Nguyen .set_link_ksettings = ice_set_link_ksettings, 3851462acf6aSTony Nguyen .get_drvinfo = ice_get_drvinfo, 3852462acf6aSTony Nguyen .get_regs_len = ice_get_regs_len, 3853462acf6aSTony Nguyen .get_regs = ice_get_regs, 3854462acf6aSTony Nguyen .get_msglevel = ice_get_msglevel, 3855462acf6aSTony Nguyen .set_msglevel = ice_set_msglevel, 3856111820b0SBrett Creeley .get_link = ethtool_op_get_link, 3857462acf6aSTony Nguyen .get_eeprom_len = ice_get_eeprom_len, 3858462acf6aSTony Nguyen .get_eeprom = ice_get_eeprom, 3859462acf6aSTony Nguyen .get_strings = ice_get_strings, 3860462acf6aSTony Nguyen .get_ethtool_stats = ice_get_ethtool_stats, 3861462acf6aSTony Nguyen .get_sset_count = ice_get_sset_count, 3862462acf6aSTony Nguyen .get_ringparam = ice_get_ringparam, 3863462acf6aSTony Nguyen .set_ringparam = ice_set_ringparam, 3864462acf6aSTony Nguyen .nway_reset = ice_nway_reset, 386587324e74SHenry Tieman .get_channels = ice_get_channels, 3866462acf6aSTony Nguyen }; 3867462acf6aSTony Nguyen 3868462acf6aSTony Nguyen /** 3869462acf6aSTony Nguyen * ice_set_ethtool_safe_mode_ops - setup safe mode ethtool ops 3870462acf6aSTony Nguyen * @netdev: network interface device structure 3871462acf6aSTony Nguyen */ 3872462acf6aSTony Nguyen void ice_set_ethtool_safe_mode_ops(struct net_device *netdev) 3873462acf6aSTony Nguyen { 3874462acf6aSTony Nguyen netdev->ethtool_ops = &ice_ethtool_safe_mode_ops; 3875462acf6aSTony Nguyen } 3876462acf6aSTony Nguyen 3877fcea6f3dSAnirudh Venkataramanan /** 3878fcea6f3dSAnirudh Venkataramanan * ice_set_ethtool_ops - setup netdev ethtool ops 3879fcea6f3dSAnirudh Venkataramanan * @netdev: network interface device structure 3880fcea6f3dSAnirudh Venkataramanan * 3881fcea6f3dSAnirudh Venkataramanan * setup netdev ethtool ops with ice specific ops 3882fcea6f3dSAnirudh Venkataramanan */ 3883fcea6f3dSAnirudh Venkataramanan void ice_set_ethtool_ops(struct net_device *netdev) 3884fcea6f3dSAnirudh Venkataramanan { 3885fcea6f3dSAnirudh Venkataramanan netdev->ethtool_ops = &ice_ethtool_ops; 3886fcea6f3dSAnirudh Venkataramanan } 3887