151dce24bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0 251dce24bSJeff Kirsher /* Copyright(c) 1999 - 2018 Intel Corporation. */ 3dee1ad47SJeff Kirsher 4dee1ad47SJeff Kirsher /* ethtool support for ixgbevf */ 5dee1ad47SJeff Kirsher 6dbd9636eSJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7dbd9636eSJeff Kirsher 8dee1ad47SJeff Kirsher #include <linux/types.h> 9dee1ad47SJeff Kirsher #include <linux/module.h> 10dee1ad47SJeff Kirsher #include <linux/slab.h> 11dee1ad47SJeff Kirsher #include <linux/pci.h> 12dee1ad47SJeff Kirsher #include <linux/netdevice.h> 13dee1ad47SJeff Kirsher #include <linux/ethtool.h> 14dee1ad47SJeff Kirsher #include <linux/vmalloc.h> 15dee1ad47SJeff Kirsher #include <linux/if_vlan.h> 16dee1ad47SJeff Kirsher #include <linux/uaccess.h> 17dee1ad47SJeff Kirsher 18dee1ad47SJeff Kirsher #include "ixgbevf.h" 19dee1ad47SJeff Kirsher 20dee1ad47SJeff Kirsher #define IXGBE_ALL_RAR_ENTRIES 16 21dee1ad47SJeff Kirsher 22d72d6c19SEmil Tantilov enum {NETDEV_STATS, IXGBEVF_STATS}; 23d72d6c19SEmil Tantilov 24dee1ad47SJeff Kirsher struct ixgbe_stats { 25dee1ad47SJeff Kirsher char stat_string[ETH_GSTRING_LEN]; 26d72d6c19SEmil Tantilov int type; 27dee1ad47SJeff Kirsher int sizeof_stat; 28dee1ad47SJeff Kirsher int stat_offset; 2944bd741eSDon Skidmore }; 30dee1ad47SJeff Kirsher 31d72d6c19SEmil Tantilov #define IXGBEVF_STAT(_name, _stat) { \ 32d72d6c19SEmil Tantilov .stat_string = _name, \ 33d72d6c19SEmil Tantilov .type = IXGBEVF_STATS, \ 34c593642cSPankaj Bharadiya .sizeof_stat = sizeof_field(struct ixgbevf_adapter, _stat), \ 35d72d6c19SEmil Tantilov .stat_offset = offsetof(struct ixgbevf_adapter, _stat) \ 3644bd741eSDon Skidmore } 3744bd741eSDon Skidmore 38d72d6c19SEmil Tantilov #define IXGBEVF_NETDEV_STAT(_net_stat) { \ 39d72d6c19SEmil Tantilov .stat_string = #_net_stat, \ 40d72d6c19SEmil Tantilov .type = NETDEV_STATS, \ 41c593642cSPankaj Bharadiya .sizeof_stat = sizeof_field(struct net_device_stats, _net_stat), \ 42d72d6c19SEmil Tantilov .stat_offset = offsetof(struct net_device_stats, _net_stat) \ 4344bd741eSDon Skidmore } 44b47aca13SStephen Hemminger 45d72d6c19SEmil Tantilov static struct ixgbe_stats ixgbevf_gstrings_stats[] = { 46d72d6c19SEmil Tantilov IXGBEVF_NETDEV_STAT(rx_packets), 47d72d6c19SEmil Tantilov IXGBEVF_NETDEV_STAT(tx_packets), 48d72d6c19SEmil Tantilov IXGBEVF_NETDEV_STAT(rx_bytes), 49d72d6c19SEmil Tantilov IXGBEVF_NETDEV_STAT(tx_bytes), 50d72d6c19SEmil Tantilov IXGBEVF_STAT("tx_busy", tx_busy), 51d72d6c19SEmil Tantilov IXGBEVF_STAT("tx_restart_queue", restart_queue), 52d72d6c19SEmil Tantilov IXGBEVF_STAT("tx_timeout_count", tx_timeout_count), 53d72d6c19SEmil Tantilov IXGBEVF_NETDEV_STAT(multicast), 54d72d6c19SEmil Tantilov IXGBEVF_STAT("rx_csum_offload_errors", hw_csum_rx_error), 552a35efe5SEmil Tantilov IXGBEVF_STAT("alloc_rx_page", alloc_rx_page), 562a35efe5SEmil Tantilov IXGBEVF_STAT("alloc_rx_page_failed", alloc_rx_page_failed), 572a35efe5SEmil Tantilov IXGBEVF_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed), 587f68d430SShannon Nelson IXGBEVF_STAT("tx_ipsec", tx_ipsec), 597f68d430SShannon Nelson IXGBEVF_STAT("rx_ipsec", rx_ipsec), 60dee1ad47SJeff Kirsher }; 61dee1ad47SJeff Kirsher 62d72d6c19SEmil Tantilov #define IXGBEVF_QUEUE_STATS_LEN ( \ 63d72d6c19SEmil Tantilov (((struct ixgbevf_adapter *)netdev_priv(netdev))->num_tx_queues + \ 642eb34bafSTony Nguyen ((struct ixgbevf_adapter *)netdev_priv(netdev))->num_xdp_queues + \ 65d72d6c19SEmil Tantilov ((struct ixgbevf_adapter *)netdev_priv(netdev))->num_rx_queues) * \ 66f87fc447SEmil Tantilov (sizeof(struct ixgbevf_stats) / sizeof(u64))) 67d72d6c19SEmil Tantilov #define IXGBEVF_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbevf_gstrings_stats) 68dee1ad47SJeff Kirsher 69d72d6c19SEmil Tantilov #define IXGBEVF_STATS_LEN (IXGBEVF_GLOBAL_STATS_LEN + IXGBEVF_QUEUE_STATS_LEN) 70dee1ad47SJeff Kirsher static const char ixgbe_gstrings_test[][ETH_GSTRING_LEN] = { 71dee1ad47SJeff Kirsher "Register test (offline)", 72dee1ad47SJeff Kirsher "Link test (on/offline)" 73dee1ad47SJeff Kirsher }; 74dec0d8e4SJeff Kirsher 75d72d6c19SEmil Tantilov #define IXGBEVF_TEST_LEN (sizeof(ixgbe_gstrings_test) / ETH_GSTRING_LEN) 76dee1ad47SJeff Kirsher 77bc04347fSEmil Tantilov static const char ixgbevf_priv_flags_strings[][ETH_GSTRING_LEN] = { 78bc04347fSEmil Tantilov #define IXGBEVF_PRIV_FLAGS_LEGACY_RX BIT(0) 79bc04347fSEmil Tantilov "legacy-rx", 80bc04347fSEmil Tantilov }; 81bc04347fSEmil Tantilov 82bc04347fSEmil Tantilov #define IXGBEVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(ixgbevf_priv_flags_strings) 83bc04347fSEmil Tantilov 849668c936SPhilippe Reynes static int ixgbevf_get_link_ksettings(struct net_device *netdev, 859668c936SPhilippe Reynes struct ethtool_link_ksettings *cmd) 86dee1ad47SJeff Kirsher { 87dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 88dee1ad47SJeff Kirsher 899668c936SPhilippe Reynes ethtool_link_ksettings_zero_link_mode(cmd, supported); 909668c936SPhilippe Reynes ethtool_link_ksettings_add_link_mode(cmd, supported, 10000baseT_Full); 919668c936SPhilippe Reynes cmd->base.autoneg = AUTONEG_DISABLE; 929668c936SPhilippe Reynes cmd->base.port = -1; 93dee1ad47SJeff Kirsher 941e1b0c65SAlexander Duyck if (adapter->link_up) { 9531a1b375SGreg Rose __u32 speed = SPEED_10000; 96dec0d8e4SJeff Kirsher 971e1b0c65SAlexander Duyck switch (adapter->link_speed) { 9831a1b375SGreg Rose case IXGBE_LINK_SPEED_10GB_FULL: 9931a1b375SGreg Rose speed = SPEED_10000; 10031a1b375SGreg Rose break; 10131a1b375SGreg Rose case IXGBE_LINK_SPEED_1GB_FULL: 10231a1b375SGreg Rose speed = SPEED_1000; 10331a1b375SGreg Rose break; 10431a1b375SGreg Rose case IXGBE_LINK_SPEED_100_FULL: 10531a1b375SGreg Rose speed = SPEED_100; 10631a1b375SGreg Rose break; 10731a1b375SGreg Rose } 10831a1b375SGreg Rose 1099668c936SPhilippe Reynes cmd->base.speed = speed; 1109668c936SPhilippe Reynes cmd->base.duplex = DUPLEX_FULL; 111dee1ad47SJeff Kirsher } else { 1129668c936SPhilippe Reynes cmd->base.speed = SPEED_UNKNOWN; 1139668c936SPhilippe Reynes cmd->base.duplex = DUPLEX_UNKNOWN; 114dee1ad47SJeff Kirsher } 115dee1ad47SJeff Kirsher 116dee1ad47SJeff Kirsher return 0; 117dee1ad47SJeff Kirsher } 118dee1ad47SJeff Kirsher 119dee1ad47SJeff Kirsher static u32 ixgbevf_get_msglevel(struct net_device *netdev) 120dee1ad47SJeff Kirsher { 121dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 122dec0d8e4SJeff Kirsher 123dee1ad47SJeff Kirsher return adapter->msg_enable; 124dee1ad47SJeff Kirsher } 125dee1ad47SJeff Kirsher 126dee1ad47SJeff Kirsher static void ixgbevf_set_msglevel(struct net_device *netdev, u32 data) 127dee1ad47SJeff Kirsher { 128dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 129dec0d8e4SJeff Kirsher 130dee1ad47SJeff Kirsher adapter->msg_enable = data; 131dee1ad47SJeff Kirsher } 132dee1ad47SJeff Kirsher 133dee1ad47SJeff Kirsher #define IXGBE_GET_STAT(_A_, _R_) (_A_->stats._R_) 134dee1ad47SJeff Kirsher 135dee1ad47SJeff Kirsher static int ixgbevf_get_regs_len(struct net_device *netdev) 136dee1ad47SJeff Kirsher { 137fa07f10dSJacob Keller #define IXGBE_REGS_LEN 45 138fa07f10dSJacob Keller return IXGBE_REGS_LEN * sizeof(u32); 139dee1ad47SJeff Kirsher } 140dee1ad47SJeff Kirsher 141dee1ad47SJeff Kirsher static void ixgbevf_get_regs(struct net_device *netdev, 142dee1ad47SJeff Kirsher struct ethtool_regs *regs, 143dee1ad47SJeff Kirsher void *p) 144dee1ad47SJeff Kirsher { 145dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 146dee1ad47SJeff Kirsher struct ixgbe_hw *hw = &adapter->hw; 147dee1ad47SJeff Kirsher u32 *regs_buff = p; 148dee1ad47SJeff Kirsher u32 regs_len = ixgbevf_get_regs_len(netdev); 149dee1ad47SJeff Kirsher u8 i; 150dee1ad47SJeff Kirsher 151dee1ad47SJeff Kirsher memset(p, 0, regs_len); 152dee1ad47SJeff Kirsher 1538d055cc0SJacob Keller /* generate a number suitable for ethtool's register version */ 1548d055cc0SJacob Keller regs->version = (1u << 24) | (hw->revision_id << 16) | hw->device_id; 155dee1ad47SJeff Kirsher 156dee1ad47SJeff Kirsher /* General Registers */ 157dee1ad47SJeff Kirsher regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_VFCTRL); 158dee1ad47SJeff Kirsher regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); 159dee1ad47SJeff Kirsher regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); 160dee1ad47SJeff Kirsher regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); 161dee1ad47SJeff Kirsher regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER); 162dee1ad47SJeff Kirsher 163dee1ad47SJeff Kirsher /* Interrupt */ 164dee1ad47SJeff Kirsher /* don't read EICR because it can clear interrupt causes, instead 165dec0d8e4SJeff Kirsher * read EICS which is a shadow but doesn't clear EICR 166dec0d8e4SJeff Kirsher */ 167dee1ad47SJeff Kirsher regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_VTEICS); 168dee1ad47SJeff Kirsher regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_VTEICS); 169dee1ad47SJeff Kirsher regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_VTEIMS); 170dee1ad47SJeff Kirsher regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_VTEIMC); 171dee1ad47SJeff Kirsher regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_VTEIAC); 172dee1ad47SJeff Kirsher regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_VTEIAM); 173dee1ad47SJeff Kirsher regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_VTEITR(0)); 174dee1ad47SJeff Kirsher regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_VTIVAR(0)); 175dee1ad47SJeff Kirsher regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); 176dee1ad47SJeff Kirsher 177dee1ad47SJeff Kirsher /* Receive DMA */ 178dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 179dee1ad47SJeff Kirsher regs_buff[14 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAL(i)); 180dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 181dee1ad47SJeff Kirsher regs_buff[16 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAH(i)); 182dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 183dee1ad47SJeff Kirsher regs_buff[18 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDLEN(i)); 184dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 185dee1ad47SJeff Kirsher regs_buff[20 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDH(i)); 186dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 187dee1ad47SJeff Kirsher regs_buff[22 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDT(i)); 188dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 189dee1ad47SJeff Kirsher regs_buff[24 + i] = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); 190dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 191dee1ad47SJeff Kirsher regs_buff[26 + i] = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i)); 192dee1ad47SJeff Kirsher 193dee1ad47SJeff Kirsher /* Receive */ 194dee1ad47SJeff Kirsher regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_VFPSRTYPE); 195dee1ad47SJeff Kirsher 196dee1ad47SJeff Kirsher /* Transmit */ 197dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 198dee1ad47SJeff Kirsher regs_buff[29 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAL(i)); 199dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 200dee1ad47SJeff Kirsher regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAH(i)); 201dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 202dee1ad47SJeff Kirsher regs_buff[33 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDLEN(i)); 203dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 204dee1ad47SJeff Kirsher regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDH(i)); 205dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 206dee1ad47SJeff Kirsher regs_buff[37 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDT(i)); 207dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 208dee1ad47SJeff Kirsher regs_buff[39 + i] = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); 209dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 210dee1ad47SJeff Kirsher regs_buff[41 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAL(i)); 211dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 212dee1ad47SJeff Kirsher regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAH(i)); 213dee1ad47SJeff Kirsher } 214dee1ad47SJeff Kirsher 215dee1ad47SJeff Kirsher static void ixgbevf_get_drvinfo(struct net_device *netdev, 216dee1ad47SJeff Kirsher struct ethtool_drvinfo *drvinfo) 217dee1ad47SJeff Kirsher { 218dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 219dee1ad47SJeff Kirsher 22084b40501SRick Jones strlcpy(drvinfo->driver, ixgbevf_driver_name, sizeof(drvinfo->driver)); 22184b40501SRick Jones strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 22284b40501SRick Jones sizeof(drvinfo->bus_info)); 223bc04347fSEmil Tantilov 224bc04347fSEmil Tantilov drvinfo->n_priv_flags = IXGBEVF_PRIV_FLAGS_STR_LEN; 225dee1ad47SJeff Kirsher } 226dee1ad47SJeff Kirsher 227dee1ad47SJeff Kirsher static void ixgbevf_get_ringparam(struct net_device *netdev, 228dee1ad47SJeff Kirsher struct ethtool_ringparam *ring) 229dee1ad47SJeff Kirsher { 230dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 231dee1ad47SJeff Kirsher 232dee1ad47SJeff Kirsher ring->rx_max_pending = IXGBEVF_MAX_RXD; 233dee1ad47SJeff Kirsher ring->tx_max_pending = IXGBEVF_MAX_TXD; 234eb022d05SAlexander Duyck ring->rx_pending = adapter->rx_ring_count; 235eb022d05SAlexander Duyck ring->tx_pending = adapter->tx_ring_count; 236dee1ad47SJeff Kirsher } 237dee1ad47SJeff Kirsher 238dee1ad47SJeff Kirsher static int ixgbevf_set_ringparam(struct net_device *netdev, 239dee1ad47SJeff Kirsher struct ethtool_ringparam *ring) 240dee1ad47SJeff Kirsher { 241dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 242dee1ad47SJeff Kirsher struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL; 243dee1ad47SJeff Kirsher u32 new_rx_count, new_tx_count; 24421092e9cSTony Nguyen int i, j, err = 0; 245dee1ad47SJeff Kirsher 246dee1ad47SJeff Kirsher if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 247dee1ad47SJeff Kirsher return -EINVAL; 248dee1ad47SJeff Kirsher 249eb022d05SAlexander Duyck new_tx_count = max_t(u32, ring->tx_pending, IXGBEVF_MIN_TXD); 250eb022d05SAlexander Duyck new_tx_count = min_t(u32, new_tx_count, IXGBEVF_MAX_TXD); 251dee1ad47SJeff Kirsher new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); 252dee1ad47SJeff Kirsher 253eb022d05SAlexander Duyck new_rx_count = max_t(u32, ring->rx_pending, IXGBEVF_MIN_RXD); 254eb022d05SAlexander Duyck new_rx_count = min_t(u32, new_rx_count, IXGBEVF_MAX_RXD); 255eb022d05SAlexander Duyck new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); 256eb022d05SAlexander Duyck 257eb022d05SAlexander Duyck /* if nothing to do return success */ 258eb022d05SAlexander Duyck if ((new_tx_count == adapter->tx_ring_count) && 259eb022d05SAlexander Duyck (new_rx_count == adapter->rx_ring_count)) 260dee1ad47SJeff Kirsher return 0; 261dee1ad47SJeff Kirsher 262dee1ad47SJeff Kirsher while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) 263eb022d05SAlexander Duyck usleep_range(1000, 2000); 264dee1ad47SJeff Kirsher 265dee1ad47SJeff Kirsher if (!netif_running(adapter->netdev)) { 266dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_tx_queues; i++) 26787e70ab9SDon Skidmore adapter->tx_ring[i]->count = new_tx_count; 26821092e9cSTony Nguyen for (i = 0; i < adapter->num_xdp_queues; i++) 26921092e9cSTony Nguyen adapter->xdp_ring[i]->count = new_tx_count; 270dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_rx_queues; i++) 27187e70ab9SDon Skidmore adapter->rx_ring[i]->count = new_rx_count; 272dee1ad47SJeff Kirsher adapter->tx_ring_count = new_tx_count; 27321092e9cSTony Nguyen adapter->xdp_ring_count = new_tx_count; 274dee1ad47SJeff Kirsher adapter->rx_ring_count = new_rx_count; 275dee1ad47SJeff Kirsher goto clear_reset; 276dee1ad47SJeff Kirsher } 277dee1ad47SJeff Kirsher 278eb022d05SAlexander Duyck if (new_tx_count != adapter->tx_ring_count) { 27942bc47b3SKees Cook tx_ring = vmalloc(array_size(sizeof(*tx_ring), 28042bc47b3SKees Cook adapter->num_tx_queues + 28142bc47b3SKees Cook adapter->num_xdp_queues)); 282dee1ad47SJeff Kirsher if (!tx_ring) { 283dee1ad47SJeff Kirsher err = -ENOMEM; 284dee1ad47SJeff Kirsher goto clear_reset; 285dee1ad47SJeff Kirsher } 286dee1ad47SJeff Kirsher 287dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_tx_queues; i++) { 288eb022d05SAlexander Duyck /* clone ring and setup updated count */ 28987e70ab9SDon Skidmore tx_ring[i] = *adapter->tx_ring[i]; 290dee1ad47SJeff Kirsher tx_ring[i].count = new_tx_count; 29105d063aaSEmil Tantilov err = ixgbevf_setup_tx_resources(&tx_ring[i]); 29205d063aaSEmil Tantilov if (err) { 293dee1ad47SJeff Kirsher while (i) { 294dee1ad47SJeff Kirsher i--; 29505d063aaSEmil Tantilov ixgbevf_free_tx_resources(&tx_ring[i]); 296dee1ad47SJeff Kirsher } 297eb022d05SAlexander Duyck 298eb022d05SAlexander Duyck vfree(tx_ring); 299eb022d05SAlexander Duyck tx_ring = NULL; 300eb022d05SAlexander Duyck 301eb022d05SAlexander Duyck goto clear_reset; 302dee1ad47SJeff Kirsher } 303dee1ad47SJeff Kirsher } 30421092e9cSTony Nguyen 30521092e9cSTony Nguyen for (j = 0; j < adapter->num_xdp_queues; i++, j++) { 30621092e9cSTony Nguyen /* clone ring and setup updated count */ 30721092e9cSTony Nguyen tx_ring[i] = *adapter->xdp_ring[j]; 30821092e9cSTony Nguyen tx_ring[i].count = new_tx_count; 30921092e9cSTony Nguyen err = ixgbevf_setup_tx_resources(&tx_ring[i]); 31021092e9cSTony Nguyen if (err) { 31121092e9cSTony Nguyen while (i) { 31221092e9cSTony Nguyen i--; 31321092e9cSTony Nguyen ixgbevf_free_tx_resources(&tx_ring[i]); 31421092e9cSTony Nguyen } 31521092e9cSTony Nguyen 31621092e9cSTony Nguyen vfree(tx_ring); 31721092e9cSTony Nguyen tx_ring = NULL; 31821092e9cSTony Nguyen 31921092e9cSTony Nguyen goto clear_reset; 32021092e9cSTony Nguyen } 32121092e9cSTony Nguyen } 32205d063aaSEmil Tantilov } 323dee1ad47SJeff Kirsher 324eb022d05SAlexander Duyck if (new_rx_count != adapter->rx_ring_count) { 32542bc47b3SKees Cook rx_ring = vmalloc(array_size(sizeof(*rx_ring), 32642bc47b3SKees Cook adapter->num_rx_queues)); 327eb022d05SAlexander Duyck if (!rx_ring) { 328eb022d05SAlexander Duyck err = -ENOMEM; 329eb022d05SAlexander Duyck goto clear_reset; 330eb022d05SAlexander Duyck } 331eb022d05SAlexander Duyck 332dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_rx_queues; i++) { 333eb022d05SAlexander Duyck /* clone ring and setup updated count */ 33487e70ab9SDon Skidmore rx_ring[i] = *adapter->rx_ring[i]; 335c7aec596STony Nguyen 336c7aec596STony Nguyen /* Clear copied XDP RX-queue info */ 337c7aec596STony Nguyen memset(&rx_ring[i].xdp_rxq, 0, 338c7aec596STony Nguyen sizeof(rx_ring[i].xdp_rxq)); 339c7aec596STony Nguyen 340dee1ad47SJeff Kirsher rx_ring[i].count = new_rx_count; 341c7aec596STony Nguyen err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]); 34205d063aaSEmil Tantilov if (err) { 343dee1ad47SJeff Kirsher while (i) { 344dee1ad47SJeff Kirsher i--; 34505d063aaSEmil Tantilov ixgbevf_free_rx_resources(&rx_ring[i]); 346dee1ad47SJeff Kirsher } 347dee1ad47SJeff Kirsher 348eb022d05SAlexander Duyck vfree(rx_ring); 349eb022d05SAlexander Duyck rx_ring = NULL; 350dee1ad47SJeff Kirsher 351dee1ad47SJeff Kirsher goto clear_reset; 352eb022d05SAlexander Duyck } 353eb022d05SAlexander Duyck } 35405d063aaSEmil Tantilov } 355dee1ad47SJeff Kirsher 356eb022d05SAlexander Duyck /* bring interface down to prepare for update */ 357eb022d05SAlexander Duyck ixgbevf_down(adapter); 358dee1ad47SJeff Kirsher 359eb022d05SAlexander Duyck /* Tx */ 360eb022d05SAlexander Duyck if (tx_ring) { 361eb022d05SAlexander Duyck for (i = 0; i < adapter->num_tx_queues; i++) { 36205d063aaSEmil Tantilov ixgbevf_free_tx_resources(adapter->tx_ring[i]); 36387e70ab9SDon Skidmore *adapter->tx_ring[i] = tx_ring[i]; 364eb022d05SAlexander Duyck } 365eb022d05SAlexander Duyck adapter->tx_ring_count = new_tx_count; 366dee1ad47SJeff Kirsher 36721092e9cSTony Nguyen for (j = 0; j < adapter->num_xdp_queues; i++, j++) { 36821092e9cSTony Nguyen ixgbevf_free_tx_resources(adapter->xdp_ring[j]); 36921092e9cSTony Nguyen *adapter->xdp_ring[j] = tx_ring[i]; 37021092e9cSTony Nguyen } 37121092e9cSTony Nguyen adapter->xdp_ring_count = new_tx_count; 37221092e9cSTony Nguyen 373eb022d05SAlexander Duyck vfree(tx_ring); 374eb022d05SAlexander Duyck tx_ring = NULL; 375eb022d05SAlexander Duyck } 376eb022d05SAlexander Duyck 377eb022d05SAlexander Duyck /* Rx */ 378eb022d05SAlexander Duyck if (rx_ring) { 379eb022d05SAlexander Duyck for (i = 0; i < adapter->num_rx_queues; i++) { 38005d063aaSEmil Tantilov ixgbevf_free_rx_resources(adapter->rx_ring[i]); 38187e70ab9SDon Skidmore *adapter->rx_ring[i] = rx_ring[i]; 382eb022d05SAlexander Duyck } 383eb022d05SAlexander Duyck adapter->rx_ring_count = new_rx_count; 384eb022d05SAlexander Duyck 385eb022d05SAlexander Duyck vfree(rx_ring); 386eb022d05SAlexander Duyck rx_ring = NULL; 387eb022d05SAlexander Duyck } 388eb022d05SAlexander Duyck 389eb022d05SAlexander Duyck /* restore interface using new values */ 390eb022d05SAlexander Duyck ixgbevf_up(adapter); 391dee1ad47SJeff Kirsher 392dee1ad47SJeff Kirsher clear_reset: 393eb022d05SAlexander Duyck /* free Tx resources if Rx error is encountered */ 394eb022d05SAlexander Duyck if (tx_ring) { 39521092e9cSTony Nguyen for (i = 0; 39621092e9cSTony Nguyen i < adapter->num_tx_queues + adapter->num_xdp_queues; i++) 39705d063aaSEmil Tantilov ixgbevf_free_tx_resources(&tx_ring[i]); 398eb022d05SAlexander Duyck vfree(tx_ring); 399eb022d05SAlexander Duyck } 400eb022d05SAlexander Duyck 401dee1ad47SJeff Kirsher clear_bit(__IXGBEVF_RESETTING, &adapter->state); 402dee1ad47SJeff Kirsher return err; 403dee1ad47SJeff Kirsher } 404dee1ad47SJeff Kirsher 405a02a5a53SEmil Tantilov static int ixgbevf_get_sset_count(struct net_device *netdev, int stringset) 406dee1ad47SJeff Kirsher { 407dee1ad47SJeff Kirsher switch (stringset) { 408dee1ad47SJeff Kirsher case ETH_SS_TEST: 409d72d6c19SEmil Tantilov return IXGBEVF_TEST_LEN; 410dee1ad47SJeff Kirsher case ETH_SS_STATS: 411a02a5a53SEmil Tantilov return IXGBEVF_STATS_LEN; 412bc04347fSEmil Tantilov case ETH_SS_PRIV_FLAGS: 413bc04347fSEmil Tantilov return IXGBEVF_PRIV_FLAGS_STR_LEN; 414dee1ad47SJeff Kirsher default: 415dee1ad47SJeff Kirsher return -EINVAL; 416dee1ad47SJeff Kirsher } 417dee1ad47SJeff Kirsher } 418dee1ad47SJeff Kirsher 419dee1ad47SJeff Kirsher static void ixgbevf_get_ethtool_stats(struct net_device *netdev, 420dee1ad47SJeff Kirsher struct ethtool_stats *stats, u64 *data) 421dee1ad47SJeff Kirsher { 422dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 423d72d6c19SEmil Tantilov struct rtnl_link_stats64 temp; 424d72d6c19SEmil Tantilov const struct rtnl_link_stats64 *net_stats; 425a02a5a53SEmil Tantilov unsigned int start; 426a02a5a53SEmil Tantilov struct ixgbevf_ring *ring; 427a02a5a53SEmil Tantilov int i, j; 428d72d6c19SEmil Tantilov char *p; 429d72d6c19SEmil Tantilov 430dee1ad47SJeff Kirsher ixgbevf_update_stats(adapter); 431d72d6c19SEmil Tantilov net_stats = dev_get_stats(netdev, &temp); 432d72d6c19SEmil Tantilov for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { 433d72d6c19SEmil Tantilov switch (ixgbevf_gstrings_stats[i].type) { 434d72d6c19SEmil Tantilov case NETDEV_STATS: 435d72d6c19SEmil Tantilov p = (char *)net_stats + 436d72d6c19SEmil Tantilov ixgbevf_gstrings_stats[i].stat_offset; 437d72d6c19SEmil Tantilov break; 438d72d6c19SEmil Tantilov case IXGBEVF_STATS: 439d72d6c19SEmil Tantilov p = (char *)adapter + 440d72d6c19SEmil Tantilov ixgbevf_gstrings_stats[i].stat_offset; 441d72d6c19SEmil Tantilov break; 442d72d6c19SEmil Tantilov default: 443d72d6c19SEmil Tantilov data[i] = 0; 444d72d6c19SEmil Tantilov continue; 44544bd741eSDon Skidmore } 446d72d6c19SEmil Tantilov 447d72d6c19SEmil Tantilov data[i] = (ixgbevf_gstrings_stats[i].sizeof_stat == 448d72d6c19SEmil Tantilov sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 449dee1ad47SJeff Kirsher } 450a02a5a53SEmil Tantilov 451a02a5a53SEmil Tantilov /* populate Tx queue data */ 452a02a5a53SEmil Tantilov for (j = 0; j < adapter->num_tx_queues; j++) { 453a02a5a53SEmil Tantilov ring = adapter->tx_ring[j]; 454a02a5a53SEmil Tantilov if (!ring) { 455a02a5a53SEmil Tantilov data[i++] = 0; 456a02a5a53SEmil Tantilov data[i++] = 0; 457a02a5a53SEmil Tantilov continue; 458a02a5a53SEmil Tantilov } 459a02a5a53SEmil Tantilov 460a02a5a53SEmil Tantilov do { 461a02a5a53SEmil Tantilov start = u64_stats_fetch_begin_irq(&ring->syncp); 462a02a5a53SEmil Tantilov data[i] = ring->stats.packets; 463a02a5a53SEmil Tantilov data[i + 1] = ring->stats.bytes; 464a02a5a53SEmil Tantilov } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 465a02a5a53SEmil Tantilov i += 2; 466a02a5a53SEmil Tantilov } 467a02a5a53SEmil Tantilov 4682eb34bafSTony Nguyen /* populate XDP queue data */ 4692eb34bafSTony Nguyen for (j = 0; j < adapter->num_xdp_queues; j++) { 4702eb34bafSTony Nguyen ring = adapter->xdp_ring[j]; 4712eb34bafSTony Nguyen if (!ring) { 4722eb34bafSTony Nguyen data[i++] = 0; 4732eb34bafSTony Nguyen data[i++] = 0; 4742eb34bafSTony Nguyen continue; 4752eb34bafSTony Nguyen } 4762eb34bafSTony Nguyen 4772eb34bafSTony Nguyen do { 4782eb34bafSTony Nguyen start = u64_stats_fetch_begin_irq(&ring->syncp); 4792eb34bafSTony Nguyen data[i] = ring->stats.packets; 4802eb34bafSTony Nguyen data[i + 1] = ring->stats.bytes; 4812eb34bafSTony Nguyen } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 4822eb34bafSTony Nguyen i += 2; 4832eb34bafSTony Nguyen } 4842eb34bafSTony Nguyen 485a02a5a53SEmil Tantilov /* populate Rx queue data */ 486a02a5a53SEmil Tantilov for (j = 0; j < adapter->num_rx_queues; j++) { 487a02a5a53SEmil Tantilov ring = adapter->rx_ring[j]; 488a02a5a53SEmil Tantilov if (!ring) { 489a02a5a53SEmil Tantilov data[i++] = 0; 490a02a5a53SEmil Tantilov data[i++] = 0; 491a02a5a53SEmil Tantilov continue; 492a02a5a53SEmil Tantilov } 493a02a5a53SEmil Tantilov 494a02a5a53SEmil Tantilov do { 495a02a5a53SEmil Tantilov start = u64_stats_fetch_begin_irq(&ring->syncp); 496a02a5a53SEmil Tantilov data[i] = ring->stats.packets; 497a02a5a53SEmil Tantilov data[i + 1] = ring->stats.bytes; 498a02a5a53SEmil Tantilov } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 499a02a5a53SEmil Tantilov i += 2; 500a02a5a53SEmil Tantilov } 501dee1ad47SJeff Kirsher } 502dee1ad47SJeff Kirsher 503dee1ad47SJeff Kirsher static void ixgbevf_get_strings(struct net_device *netdev, u32 stringset, 504dee1ad47SJeff Kirsher u8 *data) 505dee1ad47SJeff Kirsher { 506a02a5a53SEmil Tantilov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 507dee1ad47SJeff Kirsher char *p = (char *)data; 508dee1ad47SJeff Kirsher int i; 509dee1ad47SJeff Kirsher 510dee1ad47SJeff Kirsher switch (stringset) { 511dee1ad47SJeff Kirsher case ETH_SS_TEST: 512dee1ad47SJeff Kirsher memcpy(data, *ixgbe_gstrings_test, 513d72d6c19SEmil Tantilov IXGBEVF_TEST_LEN * ETH_GSTRING_LEN); 514dee1ad47SJeff Kirsher break; 515dee1ad47SJeff Kirsher case ETH_SS_STATS: 516d72d6c19SEmil Tantilov for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { 517d72d6c19SEmil Tantilov memcpy(p, ixgbevf_gstrings_stats[i].stat_string, 518dee1ad47SJeff Kirsher ETH_GSTRING_LEN); 519dee1ad47SJeff Kirsher p += ETH_GSTRING_LEN; 520dee1ad47SJeff Kirsher } 521a02a5a53SEmil Tantilov 522a02a5a53SEmil Tantilov for (i = 0; i < adapter->num_tx_queues; i++) { 523a02a5a53SEmil Tantilov sprintf(p, "tx_queue_%u_packets", i); 524a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 525a02a5a53SEmil Tantilov sprintf(p, "tx_queue_%u_bytes", i); 526a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 527a02a5a53SEmil Tantilov } 5282eb34bafSTony Nguyen for (i = 0; i < adapter->num_xdp_queues; i++) { 5292eb34bafSTony Nguyen sprintf(p, "xdp_queue_%u_packets", i); 5302eb34bafSTony Nguyen p += ETH_GSTRING_LEN; 5312eb34bafSTony Nguyen sprintf(p, "xdp_queue_%u_bytes", i); 5322eb34bafSTony Nguyen p += ETH_GSTRING_LEN; 5332eb34bafSTony Nguyen } 534a02a5a53SEmil Tantilov for (i = 0; i < adapter->num_rx_queues; i++) { 535a02a5a53SEmil Tantilov sprintf(p, "rx_queue_%u_packets", i); 536a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 537a02a5a53SEmil Tantilov sprintf(p, "rx_queue_%u_bytes", i); 538a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 539a02a5a53SEmil Tantilov } 540dee1ad47SJeff Kirsher break; 541bc04347fSEmil Tantilov case ETH_SS_PRIV_FLAGS: 542bc04347fSEmil Tantilov memcpy(data, ixgbevf_priv_flags_strings, 543bc04347fSEmil Tantilov IXGBEVF_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN); 544bc04347fSEmil Tantilov break; 545dee1ad47SJeff Kirsher } 546dee1ad47SJeff Kirsher } 547dee1ad47SJeff Kirsher 548dee1ad47SJeff Kirsher static int ixgbevf_link_test(struct ixgbevf_adapter *adapter, u64 *data) 549dee1ad47SJeff Kirsher { 550dee1ad47SJeff Kirsher struct ixgbe_hw *hw = &adapter->hw; 551dee1ad47SJeff Kirsher bool link_up; 552dee1ad47SJeff Kirsher u32 link_speed = 0; 553dee1ad47SJeff Kirsher *data = 0; 554dee1ad47SJeff Kirsher 555dee1ad47SJeff Kirsher hw->mac.ops.check_link(hw, &link_speed, &link_up, true); 556dee1ad47SJeff Kirsher if (!link_up) 557dee1ad47SJeff Kirsher *data = 1; 558dee1ad47SJeff Kirsher 559dee1ad47SJeff Kirsher return *data; 560dee1ad47SJeff Kirsher } 561dee1ad47SJeff Kirsher 562dee1ad47SJeff Kirsher /* ethtool register test data */ 563dee1ad47SJeff Kirsher struct ixgbevf_reg_test { 564dee1ad47SJeff Kirsher u16 reg; 565dee1ad47SJeff Kirsher u8 array_len; 566dee1ad47SJeff Kirsher u8 test_type; 567dee1ad47SJeff Kirsher u32 mask; 568dee1ad47SJeff Kirsher u32 write; 569dee1ad47SJeff Kirsher }; 570dee1ad47SJeff Kirsher 571dee1ad47SJeff Kirsher /* In the hardware, registers are laid out either singly, in arrays 572dee1ad47SJeff Kirsher * spaced 0x40 bytes apart, or in contiguous tables. We assume 573dee1ad47SJeff Kirsher * most tests take place on arrays or single registers (handled 574dee1ad47SJeff Kirsher * as a single-element array) and special-case the tables. 575dee1ad47SJeff Kirsher * Table tests are always pattern tests. 576dee1ad47SJeff Kirsher * 577dee1ad47SJeff Kirsher * We also make provision for some required setup steps by specifying 578dee1ad47SJeff Kirsher * registers to be written without any read-back testing. 579dee1ad47SJeff Kirsher */ 580dee1ad47SJeff Kirsher 581dee1ad47SJeff Kirsher #define PATTERN_TEST 1 582dee1ad47SJeff Kirsher #define SET_READ_TEST 2 583dee1ad47SJeff Kirsher #define WRITE_NO_TEST 3 584dee1ad47SJeff Kirsher #define TABLE32_TEST 4 585dee1ad47SJeff Kirsher #define TABLE64_TEST_LO 5 586dee1ad47SJeff Kirsher #define TABLE64_TEST_HI 6 587dee1ad47SJeff Kirsher 588dee1ad47SJeff Kirsher /* default VF register test */ 589dee1ad47SJeff Kirsher static const struct ixgbevf_reg_test reg_test_vf[] = { 590dee1ad47SJeff Kirsher { IXGBE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, 591dee1ad47SJeff Kirsher { IXGBE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 592dee1ad47SJeff Kirsher { IXGBE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, 593dee1ad47SJeff Kirsher { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, 594dee1ad47SJeff Kirsher { IXGBE_VFRDT(0), 2, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, 595dee1ad47SJeff Kirsher { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, 0 }, 596dee1ad47SJeff Kirsher { IXGBE_VFTDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, 597dee1ad47SJeff Kirsher { IXGBE_VFTDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 598dee1ad47SJeff Kirsher { IXGBE_VFTDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFF80 }, 599db99d95cSMark Rustad { .reg = 0 } 600dee1ad47SJeff Kirsher }; 601dee1ad47SJeff Kirsher 602dee1ad47SJeff Kirsher static const u32 register_test_patterns[] = { 603dee1ad47SJeff Kirsher 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF 604dee1ad47SJeff Kirsher }; 605dee1ad47SJeff Kirsher 606388b2e4cSMark Rustad static bool reg_pattern_test(struct ixgbevf_adapter *adapter, u64 *data, 607388b2e4cSMark Rustad int reg, u32 mask, u32 write) 608388b2e4cSMark Rustad { 609388b2e4cSMark Rustad u32 pat, val, before; 610388b2e4cSMark Rustad 61126597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 61226597802SMark Rustad *data = 1; 61326597802SMark Rustad return true; 61426597802SMark Rustad } 615388b2e4cSMark Rustad for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) { 61632c74949SMark Rustad before = ixgbevf_read_reg(&adapter->hw, reg); 617388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, 618388b2e4cSMark Rustad register_test_patterns[pat] & write); 61932c74949SMark Rustad val = ixgbevf_read_reg(&adapter->hw, reg); 620388b2e4cSMark Rustad if (val != (register_test_patterns[pat] & write & mask)) { 621388b2e4cSMark Rustad hw_dbg(&adapter->hw, 622388b2e4cSMark Rustad "pattern test reg %04X failed: got 0x%08X expected 0x%08X\n", 623388b2e4cSMark Rustad reg, val, 624388b2e4cSMark Rustad register_test_patterns[pat] & write & mask); 625388b2e4cSMark Rustad *data = reg; 626388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 627388b2e4cSMark Rustad return true; 628388b2e4cSMark Rustad } 629388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 630388b2e4cSMark Rustad } 631388b2e4cSMark Rustad return false; 632dee1ad47SJeff Kirsher } 633dee1ad47SJeff Kirsher 634388b2e4cSMark Rustad static bool reg_set_and_check(struct ixgbevf_adapter *adapter, u64 *data, 635388b2e4cSMark Rustad int reg, u32 mask, u32 write) 636388b2e4cSMark Rustad { 637388b2e4cSMark Rustad u32 val, before; 638388b2e4cSMark Rustad 63926597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 64026597802SMark Rustad *data = 1; 64126597802SMark Rustad return true; 64226597802SMark Rustad } 64332c74949SMark Rustad before = ixgbevf_read_reg(&adapter->hw, reg); 644388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, write & mask); 64532c74949SMark Rustad val = ixgbevf_read_reg(&adapter->hw, reg); 646388b2e4cSMark Rustad if ((write & mask) != (val & mask)) { 647388b2e4cSMark Rustad pr_err("set/check reg %04X test failed: got 0x%08X expected 0x%08X\n", 648388b2e4cSMark Rustad reg, (val & mask), write & mask); 649388b2e4cSMark Rustad *data = reg; 650388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 651388b2e4cSMark Rustad return true; 652388b2e4cSMark Rustad } 653388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 654388b2e4cSMark Rustad return false; 655dee1ad47SJeff Kirsher } 656dee1ad47SJeff Kirsher 657dee1ad47SJeff Kirsher static int ixgbevf_reg_test(struct ixgbevf_adapter *adapter, u64 *data) 658dee1ad47SJeff Kirsher { 659dee1ad47SJeff Kirsher const struct ixgbevf_reg_test *test; 660dee1ad47SJeff Kirsher u32 i; 661dee1ad47SJeff Kirsher 66226597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 66326597802SMark Rustad dev_err(&adapter->pdev->dev, 66426597802SMark Rustad "Adapter removed - register test blocked\n"); 66526597802SMark Rustad *data = 1; 66626597802SMark Rustad return 1; 66726597802SMark Rustad } 668dee1ad47SJeff Kirsher test = reg_test_vf; 669dee1ad47SJeff Kirsher 670dec0d8e4SJeff Kirsher /* Perform the register test, looping through the test table 671dee1ad47SJeff Kirsher * until we either fail or reach the null entry. 672dee1ad47SJeff Kirsher */ 673dee1ad47SJeff Kirsher while (test->reg) { 674dee1ad47SJeff Kirsher for (i = 0; i < test->array_len; i++) { 675388b2e4cSMark Rustad bool b = false; 676388b2e4cSMark Rustad 677dee1ad47SJeff Kirsher switch (test->test_type) { 678dee1ad47SJeff Kirsher case PATTERN_TEST: 679388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 680388b2e4cSMark Rustad test->reg + (i * 0x40), 681dee1ad47SJeff Kirsher test->mask, 682dee1ad47SJeff Kirsher test->write); 683dee1ad47SJeff Kirsher break; 684dee1ad47SJeff Kirsher case SET_READ_TEST: 685388b2e4cSMark Rustad b = reg_set_and_check(adapter, data, 686388b2e4cSMark Rustad test->reg + (i * 0x40), 687dee1ad47SJeff Kirsher test->mask, 688dee1ad47SJeff Kirsher test->write); 689dee1ad47SJeff Kirsher break; 690dee1ad47SJeff Kirsher case WRITE_NO_TEST: 691388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, 692388b2e4cSMark Rustad test->reg + (i * 0x40), 693388b2e4cSMark Rustad test->write); 694dee1ad47SJeff Kirsher break; 695dee1ad47SJeff Kirsher case TABLE32_TEST: 696388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 697388b2e4cSMark Rustad test->reg + (i * 4), 698dee1ad47SJeff Kirsher test->mask, 699dee1ad47SJeff Kirsher test->write); 700dee1ad47SJeff Kirsher break; 701dee1ad47SJeff Kirsher case TABLE64_TEST_LO: 702388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 703388b2e4cSMark Rustad test->reg + (i * 8), 704dee1ad47SJeff Kirsher test->mask, 705dee1ad47SJeff Kirsher test->write); 706dee1ad47SJeff Kirsher break; 707dee1ad47SJeff Kirsher case TABLE64_TEST_HI: 708388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 709388b2e4cSMark Rustad test->reg + 4 + (i * 8), 710dee1ad47SJeff Kirsher test->mask, 711dee1ad47SJeff Kirsher test->write); 712dee1ad47SJeff Kirsher break; 713dee1ad47SJeff Kirsher } 714388b2e4cSMark Rustad if (b) 715388b2e4cSMark Rustad return 1; 716dee1ad47SJeff Kirsher } 717dee1ad47SJeff Kirsher test++; 718dee1ad47SJeff Kirsher } 719dee1ad47SJeff Kirsher 720dee1ad47SJeff Kirsher *data = 0; 721dee1ad47SJeff Kirsher return *data; 722dee1ad47SJeff Kirsher } 723dee1ad47SJeff Kirsher 724dee1ad47SJeff Kirsher static void ixgbevf_diag_test(struct net_device *netdev, 725dee1ad47SJeff Kirsher struct ethtool_test *eth_test, u64 *data) 726dee1ad47SJeff Kirsher { 727dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 728dee1ad47SJeff Kirsher bool if_running = netif_running(netdev); 729dee1ad47SJeff Kirsher 73026597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 73126597802SMark Rustad dev_err(&adapter->pdev->dev, 73226597802SMark Rustad "Adapter removed - test blocked\n"); 73326597802SMark Rustad data[0] = 1; 73426597802SMark Rustad data[1] = 1; 73526597802SMark Rustad eth_test->flags |= ETH_TEST_FL_FAILED; 73626597802SMark Rustad return; 73726597802SMark Rustad } 738dee1ad47SJeff Kirsher set_bit(__IXGBEVF_TESTING, &adapter->state); 739dee1ad47SJeff Kirsher if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 740dee1ad47SJeff Kirsher /* Offline tests */ 741dee1ad47SJeff Kirsher 742dee1ad47SJeff Kirsher hw_dbg(&adapter->hw, "offline testing starting\n"); 743dee1ad47SJeff Kirsher 744dee1ad47SJeff Kirsher /* Link test performed before hardware reset so autoneg doesn't 745dec0d8e4SJeff Kirsher * interfere with test result 746dec0d8e4SJeff Kirsher */ 747dee1ad47SJeff Kirsher if (ixgbevf_link_test(adapter, &data[1])) 748dee1ad47SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED; 749dee1ad47SJeff Kirsher 750dee1ad47SJeff Kirsher if (if_running) 751dee1ad47SJeff Kirsher /* indicate we're in test mode */ 752324d0867SStefan Assmann ixgbevf_close(netdev); 753dee1ad47SJeff Kirsher else 754dee1ad47SJeff Kirsher ixgbevf_reset(adapter); 755dee1ad47SJeff Kirsher 756dee1ad47SJeff Kirsher hw_dbg(&adapter->hw, "register testing starting\n"); 757dee1ad47SJeff Kirsher if (ixgbevf_reg_test(adapter, &data[0])) 758dee1ad47SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED; 759dee1ad47SJeff Kirsher 760dee1ad47SJeff Kirsher ixgbevf_reset(adapter); 761dee1ad47SJeff Kirsher 762dee1ad47SJeff Kirsher clear_bit(__IXGBEVF_TESTING, &adapter->state); 763dee1ad47SJeff Kirsher if (if_running) 764324d0867SStefan Assmann ixgbevf_open(netdev); 765dee1ad47SJeff Kirsher } else { 766dee1ad47SJeff Kirsher hw_dbg(&adapter->hw, "online testing starting\n"); 767dee1ad47SJeff Kirsher /* Online tests */ 768dee1ad47SJeff Kirsher if (ixgbevf_link_test(adapter, &data[1])) 769dee1ad47SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED; 770dee1ad47SJeff Kirsher 771dee1ad47SJeff Kirsher /* Online tests aren't run; pass by default */ 772dee1ad47SJeff Kirsher data[0] = 0; 773dee1ad47SJeff Kirsher 774dee1ad47SJeff Kirsher clear_bit(__IXGBEVF_TESTING, &adapter->state); 775dee1ad47SJeff Kirsher } 776dee1ad47SJeff Kirsher msleep_interruptible(4 * 1000); 777dee1ad47SJeff Kirsher } 778dee1ad47SJeff Kirsher 779dee1ad47SJeff Kirsher static int ixgbevf_nway_reset(struct net_device *netdev) 780dee1ad47SJeff Kirsher { 781dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 782dee1ad47SJeff Kirsher 78377d5dfcaSAlexander Duyck if (netif_running(netdev)) 784dee1ad47SJeff Kirsher ixgbevf_reinit_locked(adapter); 785dee1ad47SJeff Kirsher 786dee1ad47SJeff Kirsher return 0; 787dee1ad47SJeff Kirsher } 788dee1ad47SJeff Kirsher 7893849623eSJacob Keller static int ixgbevf_get_coalesce(struct net_device *netdev, 790*f3ccfda1SYufeng Mo struct ethtool_coalesce *ec, 791*f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal, 792*f3ccfda1SYufeng Mo struct netlink_ext_ack *extack) 7933849623eSJacob Keller { 7943849623eSJacob Keller struct ixgbevf_adapter *adapter = netdev_priv(netdev); 7953849623eSJacob Keller 7963849623eSJacob Keller /* only valid if in constant ITR mode */ 7973849623eSJacob Keller if (adapter->rx_itr_setting <= 1) 7983849623eSJacob Keller ec->rx_coalesce_usecs = adapter->rx_itr_setting; 7993849623eSJacob Keller else 8003849623eSJacob Keller ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; 8013849623eSJacob Keller 802dec0d8e4SJeff Kirsher /* if in mixed Tx/Rx queues per vector mode, report only Rx settings */ 8033849623eSJacob Keller if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) 8043849623eSJacob Keller return 0; 8053849623eSJacob Keller 8063849623eSJacob Keller /* only valid if in constant ITR mode */ 8073849623eSJacob Keller if (adapter->tx_itr_setting <= 1) 8083849623eSJacob Keller ec->tx_coalesce_usecs = adapter->tx_itr_setting; 8093849623eSJacob Keller else 8103849623eSJacob Keller ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; 8113849623eSJacob Keller 8123849623eSJacob Keller return 0; 8133849623eSJacob Keller } 8143849623eSJacob Keller 8153849623eSJacob Keller static int ixgbevf_set_coalesce(struct net_device *netdev, 816*f3ccfda1SYufeng Mo struct ethtool_coalesce *ec, 817*f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal, 818*f3ccfda1SYufeng Mo struct netlink_ext_ack *extack) 8193849623eSJacob Keller { 8203849623eSJacob Keller struct ixgbevf_adapter *adapter = netdev_priv(netdev); 8213849623eSJacob Keller struct ixgbevf_q_vector *q_vector; 8223849623eSJacob Keller int num_vectors, i; 8233849623eSJacob Keller u16 tx_itr_param, rx_itr_param; 8243849623eSJacob Keller 825dec0d8e4SJeff Kirsher /* don't accept Tx specific changes if we've got mixed RxTx vectors */ 826dec0d8e4SJeff Kirsher if (adapter->q_vector[0]->tx.count && 827dec0d8e4SJeff Kirsher adapter->q_vector[0]->rx.count && ec->tx_coalesce_usecs) 8283849623eSJacob Keller return -EINVAL; 8293849623eSJacob Keller 8303849623eSJacob Keller if ((ec->rx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)) || 8313849623eSJacob Keller (ec->tx_coalesce_usecs > (IXGBE_MAX_EITR >> 2))) 8323849623eSJacob Keller return -EINVAL; 8333849623eSJacob Keller 8343849623eSJacob Keller if (ec->rx_coalesce_usecs > 1) 8353849623eSJacob Keller adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; 8363849623eSJacob Keller else 8373849623eSJacob Keller adapter->rx_itr_setting = ec->rx_coalesce_usecs; 8383849623eSJacob Keller 8393849623eSJacob Keller if (adapter->rx_itr_setting == 1) 8403849623eSJacob Keller rx_itr_param = IXGBE_20K_ITR; 8413849623eSJacob Keller else 8423849623eSJacob Keller rx_itr_param = adapter->rx_itr_setting; 8433849623eSJacob Keller 8443849623eSJacob Keller if (ec->tx_coalesce_usecs > 1) 8453849623eSJacob Keller adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; 8463849623eSJacob Keller else 8473849623eSJacob Keller adapter->tx_itr_setting = ec->tx_coalesce_usecs; 8483849623eSJacob Keller 8493849623eSJacob Keller if (adapter->tx_itr_setting == 1) 8508a9ca110SAlexander Duyck tx_itr_param = IXGBE_12K_ITR; 8513849623eSJacob Keller else 8523849623eSJacob Keller tx_itr_param = adapter->tx_itr_setting; 8533849623eSJacob Keller 8543849623eSJacob Keller num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 8553849623eSJacob Keller 8563849623eSJacob Keller for (i = 0; i < num_vectors; i++) { 8573849623eSJacob Keller q_vector = adapter->q_vector[i]; 8583849623eSJacob Keller if (q_vector->tx.count && !q_vector->rx.count) 859dec0d8e4SJeff Kirsher /* Tx only */ 8603849623eSJacob Keller q_vector->itr = tx_itr_param; 8613849623eSJacob Keller else 862dec0d8e4SJeff Kirsher /* Rx only or mixed */ 8633849623eSJacob Keller q_vector->itr = rx_itr_param; 8643849623eSJacob Keller ixgbevf_write_eitr(q_vector); 8653849623eSJacob Keller } 8663849623eSJacob Keller 8673849623eSJacob Keller return 0; 8683849623eSJacob Keller } 8693849623eSJacob Keller 870b6411739SVlad Zolotarov static int ixgbevf_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 871b6411739SVlad Zolotarov u32 *rules __always_unused) 872b6411739SVlad Zolotarov { 873b6411739SVlad Zolotarov struct ixgbevf_adapter *adapter = netdev_priv(dev); 874b6411739SVlad Zolotarov 875b6411739SVlad Zolotarov switch (info->cmd) { 876b6411739SVlad Zolotarov case ETHTOOL_GRXRINGS: 877b6411739SVlad Zolotarov info->data = adapter->num_rx_queues; 878b6411739SVlad Zolotarov return 0; 879b6411739SVlad Zolotarov default: 880b6411739SVlad Zolotarov hw_dbg(&adapter->hw, "Command parameters not supported\n"); 881b6411739SVlad Zolotarov return -EOPNOTSUPP; 882b6411739SVlad Zolotarov } 883b6411739SVlad Zolotarov } 884b6411739SVlad Zolotarov 885b6411739SVlad Zolotarov static u32 ixgbevf_get_rxfh_indir_size(struct net_device *netdev) 886b6411739SVlad Zolotarov { 887b6411739SVlad Zolotarov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 888b6411739SVlad Zolotarov 8899cba434fSEmil Tantilov if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) 8909cba434fSEmil Tantilov return IXGBEVF_X550_VFRETA_SIZE; 891b6411739SVlad Zolotarov 8929cba434fSEmil Tantilov return IXGBEVF_82599_RETA_SIZE; 893b6411739SVlad Zolotarov } 894b6411739SVlad Zolotarov 895b6411739SVlad Zolotarov static u32 ixgbevf_get_rxfh_key_size(struct net_device *netdev) 896b6411739SVlad Zolotarov { 897b6411739SVlad Zolotarov return IXGBEVF_RSS_HASH_KEY_SIZE; 898b6411739SVlad Zolotarov } 899b6411739SVlad Zolotarov 900b6411739SVlad Zolotarov static int ixgbevf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, 901b6411739SVlad Zolotarov u8 *hfunc) 902b6411739SVlad Zolotarov { 903b6411739SVlad Zolotarov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 904b6411739SVlad Zolotarov int err = 0; 905b6411739SVlad Zolotarov 906b6411739SVlad Zolotarov if (hfunc) 907b6411739SVlad Zolotarov *hfunc = ETH_RSS_HASH_TOP; 908b6411739SVlad Zolotarov 9099cba434fSEmil Tantilov if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) { 9109cba434fSEmil Tantilov if (key) 911e60ae003STony Nguyen memcpy(key, adapter->rss_key, 912e60ae003STony Nguyen ixgbevf_get_rxfh_key_size(netdev)); 9139cba434fSEmil Tantilov 9149cba434fSEmil Tantilov if (indir) { 9159cba434fSEmil Tantilov int i; 9169cba434fSEmil Tantilov 9179cba434fSEmil Tantilov for (i = 0; i < IXGBEVF_X550_VFRETA_SIZE; i++) 9189cba434fSEmil Tantilov indir[i] = adapter->rss_indir_tbl[i]; 9199cba434fSEmil Tantilov } 9209cba434fSEmil Tantilov } else { 9219cba434fSEmil Tantilov /* If neither indirection table nor hash key was requested 9229cba434fSEmil Tantilov * - just return a success avoiding taking any locks. 923b6411739SVlad Zolotarov */ 924b6411739SVlad Zolotarov if (!indir && !key) 925b6411739SVlad Zolotarov return 0; 926b6411739SVlad Zolotarov 927b6411739SVlad Zolotarov spin_lock_bh(&adapter->mbx_lock); 928b6411739SVlad Zolotarov if (indir) 929b6411739SVlad Zolotarov err = ixgbevf_get_reta_locked(&adapter->hw, indir, 930b6411739SVlad Zolotarov adapter->num_rx_queues); 931b6411739SVlad Zolotarov 932b6411739SVlad Zolotarov if (!err && key) 933b6411739SVlad Zolotarov err = ixgbevf_get_rss_key_locked(&adapter->hw, key); 934b6411739SVlad Zolotarov 935b6411739SVlad Zolotarov spin_unlock_bh(&adapter->mbx_lock); 9369cba434fSEmil Tantilov } 937b6411739SVlad Zolotarov 938b6411739SVlad Zolotarov return err; 939b6411739SVlad Zolotarov } 940b6411739SVlad Zolotarov 941bc04347fSEmil Tantilov static u32 ixgbevf_get_priv_flags(struct net_device *netdev) 942bc04347fSEmil Tantilov { 943bc04347fSEmil Tantilov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 944bc04347fSEmil Tantilov u32 priv_flags = 0; 945bc04347fSEmil Tantilov 946bc04347fSEmil Tantilov if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) 947bc04347fSEmil Tantilov priv_flags |= IXGBEVF_PRIV_FLAGS_LEGACY_RX; 948bc04347fSEmil Tantilov 949bc04347fSEmil Tantilov return priv_flags; 950bc04347fSEmil Tantilov } 951bc04347fSEmil Tantilov 952bc04347fSEmil Tantilov static int ixgbevf_set_priv_flags(struct net_device *netdev, u32 priv_flags) 953bc04347fSEmil Tantilov { 954bc04347fSEmil Tantilov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 955bc04347fSEmil Tantilov unsigned int flags = adapter->flags; 956bc04347fSEmil Tantilov 957bc04347fSEmil Tantilov flags &= ~IXGBEVF_FLAGS_LEGACY_RX; 958bc04347fSEmil Tantilov if (priv_flags & IXGBEVF_PRIV_FLAGS_LEGACY_RX) 959bc04347fSEmil Tantilov flags |= IXGBEVF_FLAGS_LEGACY_RX; 960bc04347fSEmil Tantilov 961bc04347fSEmil Tantilov if (flags != adapter->flags) { 962bc04347fSEmil Tantilov adapter->flags = flags; 963bc04347fSEmil Tantilov 964bc04347fSEmil Tantilov /* reset interface to repopulate queues */ 965bc04347fSEmil Tantilov if (netif_running(netdev)) 966bc04347fSEmil Tantilov ixgbevf_reinit_locked(adapter); 967bc04347fSEmil Tantilov } 968bc04347fSEmil Tantilov 969bc04347fSEmil Tantilov return 0; 970bc04347fSEmil Tantilov } 971bc04347fSEmil Tantilov 972b47aca13SStephen Hemminger static const struct ethtool_ops ixgbevf_ethtool_ops = { 973e259b911SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS, 974dee1ad47SJeff Kirsher .get_drvinfo = ixgbevf_get_drvinfo, 975dee1ad47SJeff Kirsher .get_regs_len = ixgbevf_get_regs_len, 976dee1ad47SJeff Kirsher .get_regs = ixgbevf_get_regs, 977dee1ad47SJeff Kirsher .nway_reset = ixgbevf_nway_reset, 978dee1ad47SJeff Kirsher .get_link = ethtool_op_get_link, 979dee1ad47SJeff Kirsher .get_ringparam = ixgbevf_get_ringparam, 980dee1ad47SJeff Kirsher .set_ringparam = ixgbevf_set_ringparam, 981dee1ad47SJeff Kirsher .get_msglevel = ixgbevf_get_msglevel, 982dee1ad47SJeff Kirsher .set_msglevel = ixgbevf_set_msglevel, 983dee1ad47SJeff Kirsher .self_test = ixgbevf_diag_test, 984dee1ad47SJeff Kirsher .get_sset_count = ixgbevf_get_sset_count, 985dee1ad47SJeff Kirsher .get_strings = ixgbevf_get_strings, 986dee1ad47SJeff Kirsher .get_ethtool_stats = ixgbevf_get_ethtool_stats, 9873849623eSJacob Keller .get_coalesce = ixgbevf_get_coalesce, 9883849623eSJacob Keller .set_coalesce = ixgbevf_set_coalesce, 989b6411739SVlad Zolotarov .get_rxnfc = ixgbevf_get_rxnfc, 990b6411739SVlad Zolotarov .get_rxfh_indir_size = ixgbevf_get_rxfh_indir_size, 991b6411739SVlad Zolotarov .get_rxfh_key_size = ixgbevf_get_rxfh_key_size, 992b6411739SVlad Zolotarov .get_rxfh = ixgbevf_get_rxfh, 9939668c936SPhilippe Reynes .get_link_ksettings = ixgbevf_get_link_ksettings, 994bc04347fSEmil Tantilov .get_priv_flags = ixgbevf_get_priv_flags, 995bc04347fSEmil Tantilov .set_priv_flags = ixgbevf_set_priv_flags, 996dee1ad47SJeff Kirsher }; 997dee1ad47SJeff Kirsher 998dee1ad47SJeff Kirsher void ixgbevf_set_ethtool_ops(struct net_device *netdev) 999dee1ad47SJeff Kirsher { 10007ad24ea4SWilfried Klaebe netdev->ethtool_ops = &ixgbevf_ethtool_ops; 1001dee1ad47SJeff Kirsher } 1002