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, \ 34d72d6c19SEmil Tantilov .sizeof_stat = FIELD_SIZEOF(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, \ 41d72d6c19SEmil Tantilov .sizeof_stat = FIELD_SIZEOF(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 struct ixgbe_hw *hw = &adapter->hw; 89dee1ad47SJeff Kirsher u32 link_speed = 0; 90dee1ad47SJeff Kirsher bool link_up; 91dee1ad47SJeff Kirsher 929668c936SPhilippe Reynes ethtool_link_ksettings_zero_link_mode(cmd, supported); 939668c936SPhilippe Reynes ethtool_link_ksettings_add_link_mode(cmd, supported, 10000baseT_Full); 949668c936SPhilippe Reynes cmd->base.autoneg = AUTONEG_DISABLE; 959668c936SPhilippe Reynes cmd->base.port = -1; 96dee1ad47SJeff Kirsher 97aa19c295SGreg Rose hw->mac.get_link_status = 1; 98dee1ad47SJeff Kirsher hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 99dee1ad47SJeff Kirsher 100dee1ad47SJeff Kirsher if (link_up) { 10131a1b375SGreg Rose __u32 speed = SPEED_10000; 102dec0d8e4SJeff Kirsher 10331a1b375SGreg Rose switch (link_speed) { 10431a1b375SGreg Rose case IXGBE_LINK_SPEED_10GB_FULL: 10531a1b375SGreg Rose speed = SPEED_10000; 10631a1b375SGreg Rose break; 10731a1b375SGreg Rose case IXGBE_LINK_SPEED_1GB_FULL: 10831a1b375SGreg Rose speed = SPEED_1000; 10931a1b375SGreg Rose break; 11031a1b375SGreg Rose case IXGBE_LINK_SPEED_100_FULL: 11131a1b375SGreg Rose speed = SPEED_100; 11231a1b375SGreg Rose break; 11331a1b375SGreg Rose } 11431a1b375SGreg Rose 1159668c936SPhilippe Reynes cmd->base.speed = speed; 1169668c936SPhilippe Reynes cmd->base.duplex = DUPLEX_FULL; 117dee1ad47SJeff Kirsher } else { 1189668c936SPhilippe Reynes cmd->base.speed = SPEED_UNKNOWN; 1199668c936SPhilippe Reynes cmd->base.duplex = DUPLEX_UNKNOWN; 120dee1ad47SJeff Kirsher } 121dee1ad47SJeff Kirsher 122dee1ad47SJeff Kirsher return 0; 123dee1ad47SJeff Kirsher } 124dee1ad47SJeff Kirsher 125dee1ad47SJeff Kirsher static u32 ixgbevf_get_msglevel(struct net_device *netdev) 126dee1ad47SJeff Kirsher { 127dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 128dec0d8e4SJeff Kirsher 129dee1ad47SJeff Kirsher return adapter->msg_enable; 130dee1ad47SJeff Kirsher } 131dee1ad47SJeff Kirsher 132dee1ad47SJeff Kirsher static void ixgbevf_set_msglevel(struct net_device *netdev, u32 data) 133dee1ad47SJeff Kirsher { 134dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 135dec0d8e4SJeff Kirsher 136dee1ad47SJeff Kirsher adapter->msg_enable = data; 137dee1ad47SJeff Kirsher } 138dee1ad47SJeff Kirsher 139dee1ad47SJeff Kirsher #define IXGBE_GET_STAT(_A_, _R_) (_A_->stats._R_) 140dee1ad47SJeff Kirsher 141dee1ad47SJeff Kirsher static int ixgbevf_get_regs_len(struct net_device *netdev) 142dee1ad47SJeff Kirsher { 143fa07f10dSJacob Keller #define IXGBE_REGS_LEN 45 144fa07f10dSJacob Keller return IXGBE_REGS_LEN * sizeof(u32); 145dee1ad47SJeff Kirsher } 146dee1ad47SJeff Kirsher 147dee1ad47SJeff Kirsher static void ixgbevf_get_regs(struct net_device *netdev, 148dee1ad47SJeff Kirsher struct ethtool_regs *regs, 149dee1ad47SJeff Kirsher void *p) 150dee1ad47SJeff Kirsher { 151dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 152dee1ad47SJeff Kirsher struct ixgbe_hw *hw = &adapter->hw; 153dee1ad47SJeff Kirsher u32 *regs_buff = p; 154dee1ad47SJeff Kirsher u32 regs_len = ixgbevf_get_regs_len(netdev); 155dee1ad47SJeff Kirsher u8 i; 156dee1ad47SJeff Kirsher 157dee1ad47SJeff Kirsher memset(p, 0, regs_len); 158dee1ad47SJeff Kirsher 1598d055cc0SJacob Keller /* generate a number suitable for ethtool's register version */ 1608d055cc0SJacob Keller regs->version = (1u << 24) | (hw->revision_id << 16) | hw->device_id; 161dee1ad47SJeff Kirsher 162dee1ad47SJeff Kirsher /* General Registers */ 163dee1ad47SJeff Kirsher regs_buff[0] = IXGBE_READ_REG(hw, IXGBE_VFCTRL); 164dee1ad47SJeff Kirsher regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); 165dee1ad47SJeff Kirsher regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); 166dee1ad47SJeff Kirsher regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); 167dee1ad47SJeff Kirsher regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER); 168dee1ad47SJeff Kirsher 169dee1ad47SJeff Kirsher /* Interrupt */ 170dee1ad47SJeff Kirsher /* don't read EICR because it can clear interrupt causes, instead 171dec0d8e4SJeff Kirsher * read EICS which is a shadow but doesn't clear EICR 172dec0d8e4SJeff Kirsher */ 173dee1ad47SJeff Kirsher regs_buff[5] = IXGBE_READ_REG(hw, IXGBE_VTEICS); 174dee1ad47SJeff Kirsher regs_buff[6] = IXGBE_READ_REG(hw, IXGBE_VTEICS); 175dee1ad47SJeff Kirsher regs_buff[7] = IXGBE_READ_REG(hw, IXGBE_VTEIMS); 176dee1ad47SJeff Kirsher regs_buff[8] = IXGBE_READ_REG(hw, IXGBE_VTEIMC); 177dee1ad47SJeff Kirsher regs_buff[9] = IXGBE_READ_REG(hw, IXGBE_VTEIAC); 178dee1ad47SJeff Kirsher regs_buff[10] = IXGBE_READ_REG(hw, IXGBE_VTEIAM); 179dee1ad47SJeff Kirsher regs_buff[11] = IXGBE_READ_REG(hw, IXGBE_VTEITR(0)); 180dee1ad47SJeff Kirsher regs_buff[12] = IXGBE_READ_REG(hw, IXGBE_VTIVAR(0)); 181dee1ad47SJeff Kirsher regs_buff[13] = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); 182dee1ad47SJeff Kirsher 183dee1ad47SJeff Kirsher /* Receive DMA */ 184dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 185dee1ad47SJeff Kirsher regs_buff[14 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAL(i)); 186dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 187dee1ad47SJeff Kirsher regs_buff[16 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDBAH(i)); 188dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 189dee1ad47SJeff Kirsher regs_buff[18 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDLEN(i)); 190dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 191dee1ad47SJeff Kirsher regs_buff[20 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDH(i)); 192dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 193dee1ad47SJeff Kirsher regs_buff[22 + i] = IXGBE_READ_REG(hw, IXGBE_VFRDT(i)); 194dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 195dee1ad47SJeff Kirsher regs_buff[24 + i] = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(i)); 196dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 197dee1ad47SJeff Kirsher regs_buff[26 + i] = IXGBE_READ_REG(hw, IXGBE_VFSRRCTL(i)); 198dee1ad47SJeff Kirsher 199dee1ad47SJeff Kirsher /* Receive */ 200dee1ad47SJeff Kirsher regs_buff[28] = IXGBE_READ_REG(hw, IXGBE_VFPSRTYPE); 201dee1ad47SJeff Kirsher 202dee1ad47SJeff Kirsher /* Transmit */ 203dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 204dee1ad47SJeff Kirsher regs_buff[29 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAL(i)); 205dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 206dee1ad47SJeff Kirsher regs_buff[31 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDBAH(i)); 207dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 208dee1ad47SJeff Kirsher regs_buff[33 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDLEN(i)); 209dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 210dee1ad47SJeff Kirsher regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDH(i)); 211dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 212dee1ad47SJeff Kirsher regs_buff[37 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDT(i)); 213dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 214dee1ad47SJeff Kirsher regs_buff[39 + i] = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(i)); 215dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 216dee1ad47SJeff Kirsher regs_buff[41 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAL(i)); 217dee1ad47SJeff Kirsher for (i = 0; i < 2; i++) 218dee1ad47SJeff Kirsher regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_VFTDWBAH(i)); 219dee1ad47SJeff Kirsher } 220dee1ad47SJeff Kirsher 221dee1ad47SJeff Kirsher static void ixgbevf_get_drvinfo(struct net_device *netdev, 222dee1ad47SJeff Kirsher struct ethtool_drvinfo *drvinfo) 223dee1ad47SJeff Kirsher { 224dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 225dee1ad47SJeff Kirsher 22684b40501SRick Jones strlcpy(drvinfo->driver, ixgbevf_driver_name, sizeof(drvinfo->driver)); 22784b40501SRick Jones strlcpy(drvinfo->version, ixgbevf_driver_version, 22884b40501SRick Jones sizeof(drvinfo->version)); 22984b40501SRick Jones strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 23084b40501SRick Jones sizeof(drvinfo->bus_info)); 231bc04347fSEmil Tantilov 232bc04347fSEmil Tantilov drvinfo->n_priv_flags = IXGBEVF_PRIV_FLAGS_STR_LEN; 233dee1ad47SJeff Kirsher } 234dee1ad47SJeff Kirsher 235dee1ad47SJeff Kirsher static void ixgbevf_get_ringparam(struct net_device *netdev, 236dee1ad47SJeff Kirsher struct ethtool_ringparam *ring) 237dee1ad47SJeff Kirsher { 238dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 239dee1ad47SJeff Kirsher 240dee1ad47SJeff Kirsher ring->rx_max_pending = IXGBEVF_MAX_RXD; 241dee1ad47SJeff Kirsher ring->tx_max_pending = IXGBEVF_MAX_TXD; 242eb022d05SAlexander Duyck ring->rx_pending = adapter->rx_ring_count; 243eb022d05SAlexander Duyck ring->tx_pending = adapter->tx_ring_count; 244dee1ad47SJeff Kirsher } 245dee1ad47SJeff Kirsher 246dee1ad47SJeff Kirsher static int ixgbevf_set_ringparam(struct net_device *netdev, 247dee1ad47SJeff Kirsher struct ethtool_ringparam *ring) 248dee1ad47SJeff Kirsher { 249dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 250dee1ad47SJeff Kirsher struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL; 251dee1ad47SJeff Kirsher u32 new_rx_count, new_tx_count; 25221092e9cSTony Nguyen int i, j, err = 0; 253dee1ad47SJeff Kirsher 254dee1ad47SJeff Kirsher if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 255dee1ad47SJeff Kirsher return -EINVAL; 256dee1ad47SJeff Kirsher 257eb022d05SAlexander Duyck new_tx_count = max_t(u32, ring->tx_pending, IXGBEVF_MIN_TXD); 258eb022d05SAlexander Duyck new_tx_count = min_t(u32, new_tx_count, IXGBEVF_MAX_TXD); 259dee1ad47SJeff Kirsher new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); 260dee1ad47SJeff Kirsher 261eb022d05SAlexander Duyck new_rx_count = max_t(u32, ring->rx_pending, IXGBEVF_MIN_RXD); 262eb022d05SAlexander Duyck new_rx_count = min_t(u32, new_rx_count, IXGBEVF_MAX_RXD); 263eb022d05SAlexander Duyck new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); 264eb022d05SAlexander Duyck 265eb022d05SAlexander Duyck /* if nothing to do return success */ 266eb022d05SAlexander Duyck if ((new_tx_count == adapter->tx_ring_count) && 267eb022d05SAlexander Duyck (new_rx_count == adapter->rx_ring_count)) 268dee1ad47SJeff Kirsher return 0; 269dee1ad47SJeff Kirsher 270dee1ad47SJeff Kirsher while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) 271eb022d05SAlexander Duyck usleep_range(1000, 2000); 272dee1ad47SJeff Kirsher 273dee1ad47SJeff Kirsher if (!netif_running(adapter->netdev)) { 274dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_tx_queues; i++) 27587e70ab9SDon Skidmore adapter->tx_ring[i]->count = new_tx_count; 27621092e9cSTony Nguyen for (i = 0; i < adapter->num_xdp_queues; i++) 27721092e9cSTony Nguyen adapter->xdp_ring[i]->count = new_tx_count; 278dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_rx_queues; i++) 27987e70ab9SDon Skidmore adapter->rx_ring[i]->count = new_rx_count; 280dee1ad47SJeff Kirsher adapter->tx_ring_count = new_tx_count; 28121092e9cSTony Nguyen adapter->xdp_ring_count = new_tx_count; 282dee1ad47SJeff Kirsher adapter->rx_ring_count = new_rx_count; 283dee1ad47SJeff Kirsher goto clear_reset; 284dee1ad47SJeff Kirsher } 285dee1ad47SJeff Kirsher 286eb022d05SAlexander Duyck if (new_tx_count != adapter->tx_ring_count) { 28742bc47b3SKees Cook tx_ring = vmalloc(array_size(sizeof(*tx_ring), 28842bc47b3SKees Cook adapter->num_tx_queues + 28942bc47b3SKees Cook adapter->num_xdp_queues)); 290dee1ad47SJeff Kirsher if (!tx_ring) { 291dee1ad47SJeff Kirsher err = -ENOMEM; 292dee1ad47SJeff Kirsher goto clear_reset; 293dee1ad47SJeff Kirsher } 294dee1ad47SJeff Kirsher 295dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_tx_queues; i++) { 296eb022d05SAlexander Duyck /* clone ring and setup updated count */ 29787e70ab9SDon Skidmore tx_ring[i] = *adapter->tx_ring[i]; 298dee1ad47SJeff Kirsher tx_ring[i].count = new_tx_count; 29905d063aaSEmil Tantilov err = ixgbevf_setup_tx_resources(&tx_ring[i]); 30005d063aaSEmil Tantilov if (err) { 301dee1ad47SJeff Kirsher while (i) { 302dee1ad47SJeff Kirsher i--; 30305d063aaSEmil Tantilov ixgbevf_free_tx_resources(&tx_ring[i]); 304dee1ad47SJeff Kirsher } 305eb022d05SAlexander Duyck 306eb022d05SAlexander Duyck vfree(tx_ring); 307eb022d05SAlexander Duyck tx_ring = NULL; 308eb022d05SAlexander Duyck 309eb022d05SAlexander Duyck goto clear_reset; 310dee1ad47SJeff Kirsher } 311dee1ad47SJeff Kirsher } 31221092e9cSTony Nguyen 31321092e9cSTony Nguyen for (j = 0; j < adapter->num_xdp_queues; i++, j++) { 31421092e9cSTony Nguyen /* clone ring and setup updated count */ 31521092e9cSTony Nguyen tx_ring[i] = *adapter->xdp_ring[j]; 31621092e9cSTony Nguyen tx_ring[i].count = new_tx_count; 31721092e9cSTony Nguyen err = ixgbevf_setup_tx_resources(&tx_ring[i]); 31821092e9cSTony Nguyen if (err) { 31921092e9cSTony Nguyen while (i) { 32021092e9cSTony Nguyen i--; 32121092e9cSTony Nguyen ixgbevf_free_tx_resources(&tx_ring[i]); 32221092e9cSTony Nguyen } 32321092e9cSTony Nguyen 32421092e9cSTony Nguyen vfree(tx_ring); 32521092e9cSTony Nguyen tx_ring = NULL; 32621092e9cSTony Nguyen 32721092e9cSTony Nguyen goto clear_reset; 32821092e9cSTony Nguyen } 32921092e9cSTony Nguyen } 33005d063aaSEmil Tantilov } 331dee1ad47SJeff Kirsher 332eb022d05SAlexander Duyck if (new_rx_count != adapter->rx_ring_count) { 33342bc47b3SKees Cook rx_ring = vmalloc(array_size(sizeof(*rx_ring), 33442bc47b3SKees Cook adapter->num_rx_queues)); 335eb022d05SAlexander Duyck if (!rx_ring) { 336eb022d05SAlexander Duyck err = -ENOMEM; 337eb022d05SAlexander Duyck goto clear_reset; 338eb022d05SAlexander Duyck } 339eb022d05SAlexander Duyck 340dee1ad47SJeff Kirsher for (i = 0; i < adapter->num_rx_queues; i++) { 341eb022d05SAlexander Duyck /* clone ring and setup updated count */ 34287e70ab9SDon Skidmore rx_ring[i] = *adapter->rx_ring[i]; 343c7aec596STony Nguyen 344c7aec596STony Nguyen /* Clear copied XDP RX-queue info */ 345c7aec596STony Nguyen memset(&rx_ring[i].xdp_rxq, 0, 346c7aec596STony Nguyen sizeof(rx_ring[i].xdp_rxq)); 347c7aec596STony Nguyen 348dee1ad47SJeff Kirsher rx_ring[i].count = new_rx_count; 349c7aec596STony Nguyen err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]); 35005d063aaSEmil Tantilov if (err) { 351dee1ad47SJeff Kirsher while (i) { 352dee1ad47SJeff Kirsher i--; 35305d063aaSEmil Tantilov ixgbevf_free_rx_resources(&rx_ring[i]); 354dee1ad47SJeff Kirsher } 355dee1ad47SJeff Kirsher 356eb022d05SAlexander Duyck vfree(rx_ring); 357eb022d05SAlexander Duyck rx_ring = NULL; 358dee1ad47SJeff Kirsher 359dee1ad47SJeff Kirsher goto clear_reset; 360eb022d05SAlexander Duyck } 361eb022d05SAlexander Duyck } 36205d063aaSEmil Tantilov } 363dee1ad47SJeff Kirsher 364eb022d05SAlexander Duyck /* bring interface down to prepare for update */ 365eb022d05SAlexander Duyck ixgbevf_down(adapter); 366dee1ad47SJeff Kirsher 367eb022d05SAlexander Duyck /* Tx */ 368eb022d05SAlexander Duyck if (tx_ring) { 369eb022d05SAlexander Duyck for (i = 0; i < adapter->num_tx_queues; i++) { 37005d063aaSEmil Tantilov ixgbevf_free_tx_resources(adapter->tx_ring[i]); 37187e70ab9SDon Skidmore *adapter->tx_ring[i] = tx_ring[i]; 372eb022d05SAlexander Duyck } 373eb022d05SAlexander Duyck adapter->tx_ring_count = new_tx_count; 374dee1ad47SJeff Kirsher 37521092e9cSTony Nguyen for (j = 0; j < adapter->num_xdp_queues; i++, j++) { 37621092e9cSTony Nguyen ixgbevf_free_tx_resources(adapter->xdp_ring[j]); 37721092e9cSTony Nguyen *adapter->xdp_ring[j] = tx_ring[i]; 37821092e9cSTony Nguyen } 37921092e9cSTony Nguyen adapter->xdp_ring_count = new_tx_count; 38021092e9cSTony Nguyen 381eb022d05SAlexander Duyck vfree(tx_ring); 382eb022d05SAlexander Duyck tx_ring = NULL; 383eb022d05SAlexander Duyck } 384eb022d05SAlexander Duyck 385eb022d05SAlexander Duyck /* Rx */ 386eb022d05SAlexander Duyck if (rx_ring) { 387eb022d05SAlexander Duyck for (i = 0; i < adapter->num_rx_queues; i++) { 38805d063aaSEmil Tantilov ixgbevf_free_rx_resources(adapter->rx_ring[i]); 38987e70ab9SDon Skidmore *adapter->rx_ring[i] = rx_ring[i]; 390eb022d05SAlexander Duyck } 391eb022d05SAlexander Duyck adapter->rx_ring_count = new_rx_count; 392eb022d05SAlexander Duyck 393eb022d05SAlexander Duyck vfree(rx_ring); 394eb022d05SAlexander Duyck rx_ring = NULL; 395eb022d05SAlexander Duyck } 396eb022d05SAlexander Duyck 397eb022d05SAlexander Duyck /* restore interface using new values */ 398eb022d05SAlexander Duyck ixgbevf_up(adapter); 399dee1ad47SJeff Kirsher 400dee1ad47SJeff Kirsher clear_reset: 401eb022d05SAlexander Duyck /* free Tx resources if Rx error is encountered */ 402eb022d05SAlexander Duyck if (tx_ring) { 40321092e9cSTony Nguyen for (i = 0; 40421092e9cSTony Nguyen i < adapter->num_tx_queues + adapter->num_xdp_queues; i++) 40505d063aaSEmil Tantilov ixgbevf_free_tx_resources(&tx_ring[i]); 406eb022d05SAlexander Duyck vfree(tx_ring); 407eb022d05SAlexander Duyck } 408eb022d05SAlexander Duyck 409dee1ad47SJeff Kirsher clear_bit(__IXGBEVF_RESETTING, &adapter->state); 410dee1ad47SJeff Kirsher return err; 411dee1ad47SJeff Kirsher } 412dee1ad47SJeff Kirsher 413a02a5a53SEmil Tantilov static int ixgbevf_get_sset_count(struct net_device *netdev, int stringset) 414dee1ad47SJeff Kirsher { 415dee1ad47SJeff Kirsher switch (stringset) { 416dee1ad47SJeff Kirsher case ETH_SS_TEST: 417d72d6c19SEmil Tantilov return IXGBEVF_TEST_LEN; 418dee1ad47SJeff Kirsher case ETH_SS_STATS: 419a02a5a53SEmil Tantilov return IXGBEVF_STATS_LEN; 420bc04347fSEmil Tantilov case ETH_SS_PRIV_FLAGS: 421bc04347fSEmil Tantilov return IXGBEVF_PRIV_FLAGS_STR_LEN; 422dee1ad47SJeff Kirsher default: 423dee1ad47SJeff Kirsher return -EINVAL; 424dee1ad47SJeff Kirsher } 425dee1ad47SJeff Kirsher } 426dee1ad47SJeff Kirsher 427dee1ad47SJeff Kirsher static void ixgbevf_get_ethtool_stats(struct net_device *netdev, 428dee1ad47SJeff Kirsher struct ethtool_stats *stats, u64 *data) 429dee1ad47SJeff Kirsher { 430dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 431d72d6c19SEmil Tantilov struct rtnl_link_stats64 temp; 432d72d6c19SEmil Tantilov const struct rtnl_link_stats64 *net_stats; 433a02a5a53SEmil Tantilov unsigned int start; 434a02a5a53SEmil Tantilov struct ixgbevf_ring *ring; 435a02a5a53SEmil Tantilov int i, j; 436d72d6c19SEmil Tantilov char *p; 437d72d6c19SEmil Tantilov 438dee1ad47SJeff Kirsher ixgbevf_update_stats(adapter); 439d72d6c19SEmil Tantilov net_stats = dev_get_stats(netdev, &temp); 440d72d6c19SEmil Tantilov for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { 441d72d6c19SEmil Tantilov switch (ixgbevf_gstrings_stats[i].type) { 442d72d6c19SEmil Tantilov case NETDEV_STATS: 443d72d6c19SEmil Tantilov p = (char *)net_stats + 444d72d6c19SEmil Tantilov ixgbevf_gstrings_stats[i].stat_offset; 445d72d6c19SEmil Tantilov break; 446d72d6c19SEmil Tantilov case IXGBEVF_STATS: 447d72d6c19SEmil Tantilov p = (char *)adapter + 448d72d6c19SEmil Tantilov ixgbevf_gstrings_stats[i].stat_offset; 449d72d6c19SEmil Tantilov break; 450d72d6c19SEmil Tantilov default: 451d72d6c19SEmil Tantilov data[i] = 0; 452d72d6c19SEmil Tantilov continue; 45344bd741eSDon Skidmore } 454d72d6c19SEmil Tantilov 455d72d6c19SEmil Tantilov data[i] = (ixgbevf_gstrings_stats[i].sizeof_stat == 456d72d6c19SEmil Tantilov sizeof(u64)) ? *(u64 *)p : *(u32 *)p; 457dee1ad47SJeff Kirsher } 458a02a5a53SEmil Tantilov 459a02a5a53SEmil Tantilov /* populate Tx queue data */ 460a02a5a53SEmil Tantilov for (j = 0; j < adapter->num_tx_queues; j++) { 461a02a5a53SEmil Tantilov ring = adapter->tx_ring[j]; 462a02a5a53SEmil Tantilov if (!ring) { 463a02a5a53SEmil Tantilov data[i++] = 0; 464a02a5a53SEmil Tantilov data[i++] = 0; 465a02a5a53SEmil Tantilov continue; 466a02a5a53SEmil Tantilov } 467a02a5a53SEmil Tantilov 468a02a5a53SEmil Tantilov do { 469a02a5a53SEmil Tantilov start = u64_stats_fetch_begin_irq(&ring->syncp); 470a02a5a53SEmil Tantilov data[i] = ring->stats.packets; 471a02a5a53SEmil Tantilov data[i + 1] = ring->stats.bytes; 472a02a5a53SEmil Tantilov } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 473a02a5a53SEmil Tantilov i += 2; 474a02a5a53SEmil Tantilov } 475a02a5a53SEmil Tantilov 4762eb34bafSTony Nguyen /* populate XDP queue data */ 4772eb34bafSTony Nguyen for (j = 0; j < adapter->num_xdp_queues; j++) { 4782eb34bafSTony Nguyen ring = adapter->xdp_ring[j]; 4792eb34bafSTony Nguyen if (!ring) { 4802eb34bafSTony Nguyen data[i++] = 0; 4812eb34bafSTony Nguyen data[i++] = 0; 4822eb34bafSTony Nguyen continue; 4832eb34bafSTony Nguyen } 4842eb34bafSTony Nguyen 4852eb34bafSTony Nguyen do { 4862eb34bafSTony Nguyen start = u64_stats_fetch_begin_irq(&ring->syncp); 4872eb34bafSTony Nguyen data[i] = ring->stats.packets; 4882eb34bafSTony Nguyen data[i + 1] = ring->stats.bytes; 4892eb34bafSTony Nguyen } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 4902eb34bafSTony Nguyen i += 2; 4912eb34bafSTony Nguyen } 4922eb34bafSTony Nguyen 493a02a5a53SEmil Tantilov /* populate Rx queue data */ 494a02a5a53SEmil Tantilov for (j = 0; j < adapter->num_rx_queues; j++) { 495a02a5a53SEmil Tantilov ring = adapter->rx_ring[j]; 496a02a5a53SEmil Tantilov if (!ring) { 497a02a5a53SEmil Tantilov data[i++] = 0; 498a02a5a53SEmil Tantilov data[i++] = 0; 499a02a5a53SEmil Tantilov continue; 500a02a5a53SEmil Tantilov } 501a02a5a53SEmil Tantilov 502a02a5a53SEmil Tantilov do { 503a02a5a53SEmil Tantilov start = u64_stats_fetch_begin_irq(&ring->syncp); 504a02a5a53SEmil Tantilov data[i] = ring->stats.packets; 505a02a5a53SEmil Tantilov data[i + 1] = ring->stats.bytes; 506a02a5a53SEmil Tantilov } while (u64_stats_fetch_retry_irq(&ring->syncp, start)); 507a02a5a53SEmil Tantilov i += 2; 508a02a5a53SEmil Tantilov } 509dee1ad47SJeff Kirsher } 510dee1ad47SJeff Kirsher 511dee1ad47SJeff Kirsher static void ixgbevf_get_strings(struct net_device *netdev, u32 stringset, 512dee1ad47SJeff Kirsher u8 *data) 513dee1ad47SJeff Kirsher { 514a02a5a53SEmil Tantilov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 515dee1ad47SJeff Kirsher char *p = (char *)data; 516dee1ad47SJeff Kirsher int i; 517dee1ad47SJeff Kirsher 518dee1ad47SJeff Kirsher switch (stringset) { 519dee1ad47SJeff Kirsher case ETH_SS_TEST: 520dee1ad47SJeff Kirsher memcpy(data, *ixgbe_gstrings_test, 521d72d6c19SEmil Tantilov IXGBEVF_TEST_LEN * ETH_GSTRING_LEN); 522dee1ad47SJeff Kirsher break; 523dee1ad47SJeff Kirsher case ETH_SS_STATS: 524d72d6c19SEmil Tantilov for (i = 0; i < IXGBEVF_GLOBAL_STATS_LEN; i++) { 525d72d6c19SEmil Tantilov memcpy(p, ixgbevf_gstrings_stats[i].stat_string, 526dee1ad47SJeff Kirsher ETH_GSTRING_LEN); 527dee1ad47SJeff Kirsher p += ETH_GSTRING_LEN; 528dee1ad47SJeff Kirsher } 529a02a5a53SEmil Tantilov 530a02a5a53SEmil Tantilov for (i = 0; i < adapter->num_tx_queues; i++) { 531a02a5a53SEmil Tantilov sprintf(p, "tx_queue_%u_packets", i); 532a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 533a02a5a53SEmil Tantilov sprintf(p, "tx_queue_%u_bytes", i); 534a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 535a02a5a53SEmil Tantilov } 5362eb34bafSTony Nguyen for (i = 0; i < adapter->num_xdp_queues; i++) { 5372eb34bafSTony Nguyen sprintf(p, "xdp_queue_%u_packets", i); 5382eb34bafSTony Nguyen p += ETH_GSTRING_LEN; 5392eb34bafSTony Nguyen sprintf(p, "xdp_queue_%u_bytes", i); 5402eb34bafSTony Nguyen p += ETH_GSTRING_LEN; 5412eb34bafSTony Nguyen } 542a02a5a53SEmil Tantilov for (i = 0; i < adapter->num_rx_queues; i++) { 543a02a5a53SEmil Tantilov sprintf(p, "rx_queue_%u_packets", i); 544a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 545a02a5a53SEmil Tantilov sprintf(p, "rx_queue_%u_bytes", i); 546a02a5a53SEmil Tantilov p += ETH_GSTRING_LEN; 547a02a5a53SEmil Tantilov } 548dee1ad47SJeff Kirsher break; 549bc04347fSEmil Tantilov case ETH_SS_PRIV_FLAGS: 550bc04347fSEmil Tantilov memcpy(data, ixgbevf_priv_flags_strings, 551bc04347fSEmil Tantilov IXGBEVF_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN); 552bc04347fSEmil Tantilov break; 553dee1ad47SJeff Kirsher } 554dee1ad47SJeff Kirsher } 555dee1ad47SJeff Kirsher 556dee1ad47SJeff Kirsher static int ixgbevf_link_test(struct ixgbevf_adapter *adapter, u64 *data) 557dee1ad47SJeff Kirsher { 558dee1ad47SJeff Kirsher struct ixgbe_hw *hw = &adapter->hw; 559dee1ad47SJeff Kirsher bool link_up; 560dee1ad47SJeff Kirsher u32 link_speed = 0; 561dee1ad47SJeff Kirsher *data = 0; 562dee1ad47SJeff Kirsher 563dee1ad47SJeff Kirsher hw->mac.ops.check_link(hw, &link_speed, &link_up, true); 564dee1ad47SJeff Kirsher if (!link_up) 565dee1ad47SJeff Kirsher *data = 1; 566dee1ad47SJeff Kirsher 567dee1ad47SJeff Kirsher return *data; 568dee1ad47SJeff Kirsher } 569dee1ad47SJeff Kirsher 570dee1ad47SJeff Kirsher /* ethtool register test data */ 571dee1ad47SJeff Kirsher struct ixgbevf_reg_test { 572dee1ad47SJeff Kirsher u16 reg; 573dee1ad47SJeff Kirsher u8 array_len; 574dee1ad47SJeff Kirsher u8 test_type; 575dee1ad47SJeff Kirsher u32 mask; 576dee1ad47SJeff Kirsher u32 write; 577dee1ad47SJeff Kirsher }; 578dee1ad47SJeff Kirsher 579dee1ad47SJeff Kirsher /* In the hardware, registers are laid out either singly, in arrays 580dee1ad47SJeff Kirsher * spaced 0x40 bytes apart, or in contiguous tables. We assume 581dee1ad47SJeff Kirsher * most tests take place on arrays or single registers (handled 582dee1ad47SJeff Kirsher * as a single-element array) and special-case the tables. 583dee1ad47SJeff Kirsher * Table tests are always pattern tests. 584dee1ad47SJeff Kirsher * 585dee1ad47SJeff Kirsher * We also make provision for some required setup steps by specifying 586dee1ad47SJeff Kirsher * registers to be written without any read-back testing. 587dee1ad47SJeff Kirsher */ 588dee1ad47SJeff Kirsher 589dee1ad47SJeff Kirsher #define PATTERN_TEST 1 590dee1ad47SJeff Kirsher #define SET_READ_TEST 2 591dee1ad47SJeff Kirsher #define WRITE_NO_TEST 3 592dee1ad47SJeff Kirsher #define TABLE32_TEST 4 593dee1ad47SJeff Kirsher #define TABLE64_TEST_LO 5 594dee1ad47SJeff Kirsher #define TABLE64_TEST_HI 6 595dee1ad47SJeff Kirsher 596dee1ad47SJeff Kirsher /* default VF register test */ 597dee1ad47SJeff Kirsher static const struct ixgbevf_reg_test reg_test_vf[] = { 598dee1ad47SJeff Kirsher { IXGBE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, 599dee1ad47SJeff Kirsher { IXGBE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 600dee1ad47SJeff Kirsher { IXGBE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, 601dee1ad47SJeff Kirsher { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, IXGBE_RXDCTL_ENABLE }, 602dee1ad47SJeff Kirsher { IXGBE_VFRDT(0), 2, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF }, 603dee1ad47SJeff Kirsher { IXGBE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, 0 }, 604dee1ad47SJeff Kirsher { IXGBE_VFTDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF }, 605dee1ad47SJeff Kirsher { IXGBE_VFTDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, 606dee1ad47SJeff Kirsher { IXGBE_VFTDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFF80 }, 607db99d95cSMark Rustad { .reg = 0 } 608dee1ad47SJeff Kirsher }; 609dee1ad47SJeff Kirsher 610dee1ad47SJeff Kirsher static const u32 register_test_patterns[] = { 611dee1ad47SJeff Kirsher 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF 612dee1ad47SJeff Kirsher }; 613dee1ad47SJeff Kirsher 614388b2e4cSMark Rustad static bool reg_pattern_test(struct ixgbevf_adapter *adapter, u64 *data, 615388b2e4cSMark Rustad int reg, u32 mask, u32 write) 616388b2e4cSMark Rustad { 617388b2e4cSMark Rustad u32 pat, val, before; 618388b2e4cSMark Rustad 61926597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 62026597802SMark Rustad *data = 1; 62126597802SMark Rustad return true; 62226597802SMark Rustad } 623388b2e4cSMark Rustad for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) { 62432c74949SMark Rustad before = ixgbevf_read_reg(&adapter->hw, reg); 625388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, 626388b2e4cSMark Rustad register_test_patterns[pat] & write); 62732c74949SMark Rustad val = ixgbevf_read_reg(&adapter->hw, reg); 628388b2e4cSMark Rustad if (val != (register_test_patterns[pat] & write & mask)) { 629388b2e4cSMark Rustad hw_dbg(&adapter->hw, 630388b2e4cSMark Rustad "pattern test reg %04X failed: got 0x%08X expected 0x%08X\n", 631388b2e4cSMark Rustad reg, val, 632388b2e4cSMark Rustad register_test_patterns[pat] & write & mask); 633388b2e4cSMark Rustad *data = reg; 634388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 635388b2e4cSMark Rustad return true; 636388b2e4cSMark Rustad } 637388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 638388b2e4cSMark Rustad } 639388b2e4cSMark Rustad return false; 640dee1ad47SJeff Kirsher } 641dee1ad47SJeff Kirsher 642388b2e4cSMark Rustad static bool reg_set_and_check(struct ixgbevf_adapter *adapter, u64 *data, 643388b2e4cSMark Rustad int reg, u32 mask, u32 write) 644388b2e4cSMark Rustad { 645388b2e4cSMark Rustad u32 val, before; 646388b2e4cSMark Rustad 64726597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 64826597802SMark Rustad *data = 1; 64926597802SMark Rustad return true; 65026597802SMark Rustad } 65132c74949SMark Rustad before = ixgbevf_read_reg(&adapter->hw, reg); 652388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, write & mask); 65332c74949SMark Rustad val = ixgbevf_read_reg(&adapter->hw, reg); 654388b2e4cSMark Rustad if ((write & mask) != (val & mask)) { 655388b2e4cSMark Rustad pr_err("set/check reg %04X test failed: got 0x%08X expected 0x%08X\n", 656388b2e4cSMark Rustad reg, (val & mask), write & mask); 657388b2e4cSMark Rustad *data = reg; 658388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 659388b2e4cSMark Rustad return true; 660388b2e4cSMark Rustad } 661388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, reg, before); 662388b2e4cSMark Rustad return false; 663dee1ad47SJeff Kirsher } 664dee1ad47SJeff Kirsher 665dee1ad47SJeff Kirsher static int ixgbevf_reg_test(struct ixgbevf_adapter *adapter, u64 *data) 666dee1ad47SJeff Kirsher { 667dee1ad47SJeff Kirsher const struct ixgbevf_reg_test *test; 668dee1ad47SJeff Kirsher u32 i; 669dee1ad47SJeff Kirsher 67026597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 67126597802SMark Rustad dev_err(&adapter->pdev->dev, 67226597802SMark Rustad "Adapter removed - register test blocked\n"); 67326597802SMark Rustad *data = 1; 67426597802SMark Rustad return 1; 67526597802SMark Rustad } 676dee1ad47SJeff Kirsher test = reg_test_vf; 677dee1ad47SJeff Kirsher 678dec0d8e4SJeff Kirsher /* Perform the register test, looping through the test table 679dee1ad47SJeff Kirsher * until we either fail or reach the null entry. 680dee1ad47SJeff Kirsher */ 681dee1ad47SJeff Kirsher while (test->reg) { 682dee1ad47SJeff Kirsher for (i = 0; i < test->array_len; i++) { 683388b2e4cSMark Rustad bool b = false; 684388b2e4cSMark Rustad 685dee1ad47SJeff Kirsher switch (test->test_type) { 686dee1ad47SJeff Kirsher case PATTERN_TEST: 687388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 688388b2e4cSMark Rustad test->reg + (i * 0x40), 689dee1ad47SJeff Kirsher test->mask, 690dee1ad47SJeff Kirsher test->write); 691dee1ad47SJeff Kirsher break; 692dee1ad47SJeff Kirsher case SET_READ_TEST: 693388b2e4cSMark Rustad b = reg_set_and_check(adapter, data, 694388b2e4cSMark Rustad test->reg + (i * 0x40), 695dee1ad47SJeff Kirsher test->mask, 696dee1ad47SJeff Kirsher test->write); 697dee1ad47SJeff Kirsher break; 698dee1ad47SJeff Kirsher case WRITE_NO_TEST: 699388b2e4cSMark Rustad ixgbe_write_reg(&adapter->hw, 700388b2e4cSMark Rustad test->reg + (i * 0x40), 701388b2e4cSMark Rustad test->write); 702dee1ad47SJeff Kirsher break; 703dee1ad47SJeff Kirsher case TABLE32_TEST: 704388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 705388b2e4cSMark Rustad test->reg + (i * 4), 706dee1ad47SJeff Kirsher test->mask, 707dee1ad47SJeff Kirsher test->write); 708dee1ad47SJeff Kirsher break; 709dee1ad47SJeff Kirsher case TABLE64_TEST_LO: 710388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 711388b2e4cSMark Rustad test->reg + (i * 8), 712dee1ad47SJeff Kirsher test->mask, 713dee1ad47SJeff Kirsher test->write); 714dee1ad47SJeff Kirsher break; 715dee1ad47SJeff Kirsher case TABLE64_TEST_HI: 716388b2e4cSMark Rustad b = reg_pattern_test(adapter, data, 717388b2e4cSMark Rustad test->reg + 4 + (i * 8), 718dee1ad47SJeff Kirsher test->mask, 719dee1ad47SJeff Kirsher test->write); 720dee1ad47SJeff Kirsher break; 721dee1ad47SJeff Kirsher } 722388b2e4cSMark Rustad if (b) 723388b2e4cSMark Rustad return 1; 724dee1ad47SJeff Kirsher } 725dee1ad47SJeff Kirsher test++; 726dee1ad47SJeff Kirsher } 727dee1ad47SJeff Kirsher 728dee1ad47SJeff Kirsher *data = 0; 729dee1ad47SJeff Kirsher return *data; 730dee1ad47SJeff Kirsher } 731dee1ad47SJeff Kirsher 732dee1ad47SJeff Kirsher static void ixgbevf_diag_test(struct net_device *netdev, 733dee1ad47SJeff Kirsher struct ethtool_test *eth_test, u64 *data) 734dee1ad47SJeff Kirsher { 735dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 736dee1ad47SJeff Kirsher bool if_running = netif_running(netdev); 737dee1ad47SJeff Kirsher 73826597802SMark Rustad if (IXGBE_REMOVED(adapter->hw.hw_addr)) { 73926597802SMark Rustad dev_err(&adapter->pdev->dev, 74026597802SMark Rustad "Adapter removed - test blocked\n"); 74126597802SMark Rustad data[0] = 1; 74226597802SMark Rustad data[1] = 1; 74326597802SMark Rustad eth_test->flags |= ETH_TEST_FL_FAILED; 74426597802SMark Rustad return; 74526597802SMark Rustad } 746dee1ad47SJeff Kirsher set_bit(__IXGBEVF_TESTING, &adapter->state); 747dee1ad47SJeff Kirsher if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 748dee1ad47SJeff Kirsher /* Offline tests */ 749dee1ad47SJeff Kirsher 750dee1ad47SJeff Kirsher hw_dbg(&adapter->hw, "offline testing starting\n"); 751dee1ad47SJeff Kirsher 752dee1ad47SJeff Kirsher /* Link test performed before hardware reset so autoneg doesn't 753dec0d8e4SJeff Kirsher * interfere with test result 754dec0d8e4SJeff Kirsher */ 755dee1ad47SJeff Kirsher if (ixgbevf_link_test(adapter, &data[1])) 756dee1ad47SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED; 757dee1ad47SJeff Kirsher 758dee1ad47SJeff Kirsher if (if_running) 759dee1ad47SJeff Kirsher /* indicate we're in test mode */ 760324d0867SStefan Assmann ixgbevf_close(netdev); 761dee1ad47SJeff Kirsher else 762dee1ad47SJeff Kirsher ixgbevf_reset(adapter); 763dee1ad47SJeff Kirsher 764dee1ad47SJeff Kirsher hw_dbg(&adapter->hw, "register testing starting\n"); 765dee1ad47SJeff Kirsher if (ixgbevf_reg_test(adapter, &data[0])) 766dee1ad47SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED; 767dee1ad47SJeff Kirsher 768dee1ad47SJeff Kirsher ixgbevf_reset(adapter); 769dee1ad47SJeff Kirsher 770dee1ad47SJeff Kirsher clear_bit(__IXGBEVF_TESTING, &adapter->state); 771dee1ad47SJeff Kirsher if (if_running) 772324d0867SStefan Assmann ixgbevf_open(netdev); 773dee1ad47SJeff Kirsher } else { 774dee1ad47SJeff Kirsher hw_dbg(&adapter->hw, "online testing starting\n"); 775dee1ad47SJeff Kirsher /* Online tests */ 776dee1ad47SJeff Kirsher if (ixgbevf_link_test(adapter, &data[1])) 777dee1ad47SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED; 778dee1ad47SJeff Kirsher 779dee1ad47SJeff Kirsher /* Online tests aren't run; pass by default */ 780dee1ad47SJeff Kirsher data[0] = 0; 781dee1ad47SJeff Kirsher 782dee1ad47SJeff Kirsher clear_bit(__IXGBEVF_TESTING, &adapter->state); 783dee1ad47SJeff Kirsher } 784dee1ad47SJeff Kirsher msleep_interruptible(4 * 1000); 785dee1ad47SJeff Kirsher } 786dee1ad47SJeff Kirsher 787dee1ad47SJeff Kirsher static int ixgbevf_nway_reset(struct net_device *netdev) 788dee1ad47SJeff Kirsher { 789dee1ad47SJeff Kirsher struct ixgbevf_adapter *adapter = netdev_priv(netdev); 790dee1ad47SJeff Kirsher 79177d5dfcaSAlexander Duyck if (netif_running(netdev)) 792dee1ad47SJeff Kirsher ixgbevf_reinit_locked(adapter); 793dee1ad47SJeff Kirsher 794dee1ad47SJeff Kirsher return 0; 795dee1ad47SJeff Kirsher } 796dee1ad47SJeff Kirsher 7973849623eSJacob Keller static int ixgbevf_get_coalesce(struct net_device *netdev, 7983849623eSJacob Keller struct ethtool_coalesce *ec) 7993849623eSJacob Keller { 8003849623eSJacob Keller struct ixgbevf_adapter *adapter = netdev_priv(netdev); 8013849623eSJacob Keller 8023849623eSJacob Keller /* only valid if in constant ITR mode */ 8033849623eSJacob Keller if (adapter->rx_itr_setting <= 1) 8043849623eSJacob Keller ec->rx_coalesce_usecs = adapter->rx_itr_setting; 8053849623eSJacob Keller else 8063849623eSJacob Keller ec->rx_coalesce_usecs = adapter->rx_itr_setting >> 2; 8073849623eSJacob Keller 808dec0d8e4SJeff Kirsher /* if in mixed Tx/Rx queues per vector mode, report only Rx settings */ 8093849623eSJacob Keller if (adapter->q_vector[0]->tx.count && adapter->q_vector[0]->rx.count) 8103849623eSJacob Keller return 0; 8113849623eSJacob Keller 8123849623eSJacob Keller /* only valid if in constant ITR mode */ 8133849623eSJacob Keller if (adapter->tx_itr_setting <= 1) 8143849623eSJacob Keller ec->tx_coalesce_usecs = adapter->tx_itr_setting; 8153849623eSJacob Keller else 8163849623eSJacob Keller ec->tx_coalesce_usecs = adapter->tx_itr_setting >> 2; 8173849623eSJacob Keller 8183849623eSJacob Keller return 0; 8193849623eSJacob Keller } 8203849623eSJacob Keller 8213849623eSJacob Keller static int ixgbevf_set_coalesce(struct net_device *netdev, 8223849623eSJacob Keller struct ethtool_coalesce *ec) 8233849623eSJacob Keller { 8243849623eSJacob Keller struct ixgbevf_adapter *adapter = netdev_priv(netdev); 8253849623eSJacob Keller struct ixgbevf_q_vector *q_vector; 8263849623eSJacob Keller int num_vectors, i; 8273849623eSJacob Keller u16 tx_itr_param, rx_itr_param; 8283849623eSJacob Keller 829dec0d8e4SJeff Kirsher /* don't accept Tx specific changes if we've got mixed RxTx vectors */ 830dec0d8e4SJeff Kirsher if (adapter->q_vector[0]->tx.count && 831dec0d8e4SJeff Kirsher adapter->q_vector[0]->rx.count && ec->tx_coalesce_usecs) 8323849623eSJacob Keller return -EINVAL; 8333849623eSJacob Keller 8343849623eSJacob Keller if ((ec->rx_coalesce_usecs > (IXGBE_MAX_EITR >> 2)) || 8353849623eSJacob Keller (ec->tx_coalesce_usecs > (IXGBE_MAX_EITR >> 2))) 8363849623eSJacob Keller return -EINVAL; 8373849623eSJacob Keller 8383849623eSJacob Keller if (ec->rx_coalesce_usecs > 1) 8393849623eSJacob Keller adapter->rx_itr_setting = ec->rx_coalesce_usecs << 2; 8403849623eSJacob Keller else 8413849623eSJacob Keller adapter->rx_itr_setting = ec->rx_coalesce_usecs; 8423849623eSJacob Keller 8433849623eSJacob Keller if (adapter->rx_itr_setting == 1) 8443849623eSJacob Keller rx_itr_param = IXGBE_20K_ITR; 8453849623eSJacob Keller else 8463849623eSJacob Keller rx_itr_param = adapter->rx_itr_setting; 8473849623eSJacob Keller 8483849623eSJacob Keller if (ec->tx_coalesce_usecs > 1) 8493849623eSJacob Keller adapter->tx_itr_setting = ec->tx_coalesce_usecs << 2; 8503849623eSJacob Keller else 8513849623eSJacob Keller adapter->tx_itr_setting = ec->tx_coalesce_usecs; 8523849623eSJacob Keller 8533849623eSJacob Keller if (adapter->tx_itr_setting == 1) 8548a9ca110SAlexander Duyck tx_itr_param = IXGBE_12K_ITR; 8553849623eSJacob Keller else 8563849623eSJacob Keller tx_itr_param = adapter->tx_itr_setting; 8573849623eSJacob Keller 8583849623eSJacob Keller num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 8593849623eSJacob Keller 8603849623eSJacob Keller for (i = 0; i < num_vectors; i++) { 8613849623eSJacob Keller q_vector = adapter->q_vector[i]; 8623849623eSJacob Keller if (q_vector->tx.count && !q_vector->rx.count) 863dec0d8e4SJeff Kirsher /* Tx only */ 8643849623eSJacob Keller q_vector->itr = tx_itr_param; 8653849623eSJacob Keller else 866dec0d8e4SJeff Kirsher /* Rx only or mixed */ 8673849623eSJacob Keller q_vector->itr = rx_itr_param; 8683849623eSJacob Keller ixgbevf_write_eitr(q_vector); 8693849623eSJacob Keller } 8703849623eSJacob Keller 8713849623eSJacob Keller return 0; 8723849623eSJacob Keller } 8733849623eSJacob Keller 874b6411739SVlad Zolotarov static int ixgbevf_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, 875b6411739SVlad Zolotarov u32 *rules __always_unused) 876b6411739SVlad Zolotarov { 877b6411739SVlad Zolotarov struct ixgbevf_adapter *adapter = netdev_priv(dev); 878b6411739SVlad Zolotarov 879b6411739SVlad Zolotarov switch (info->cmd) { 880b6411739SVlad Zolotarov case ETHTOOL_GRXRINGS: 881b6411739SVlad Zolotarov info->data = adapter->num_rx_queues; 882b6411739SVlad Zolotarov return 0; 883b6411739SVlad Zolotarov default: 884b6411739SVlad Zolotarov hw_dbg(&adapter->hw, "Command parameters not supported\n"); 885b6411739SVlad Zolotarov return -EOPNOTSUPP; 886b6411739SVlad Zolotarov } 887b6411739SVlad Zolotarov } 888b6411739SVlad Zolotarov 889b6411739SVlad Zolotarov static u32 ixgbevf_get_rxfh_indir_size(struct net_device *netdev) 890b6411739SVlad Zolotarov { 891b6411739SVlad Zolotarov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 892b6411739SVlad Zolotarov 8939cba434fSEmil Tantilov if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) 8949cba434fSEmil Tantilov return IXGBEVF_X550_VFRETA_SIZE; 895b6411739SVlad Zolotarov 8969cba434fSEmil Tantilov return IXGBEVF_82599_RETA_SIZE; 897b6411739SVlad Zolotarov } 898b6411739SVlad Zolotarov 899b6411739SVlad Zolotarov static u32 ixgbevf_get_rxfh_key_size(struct net_device *netdev) 900b6411739SVlad Zolotarov { 901b6411739SVlad Zolotarov return IXGBEVF_RSS_HASH_KEY_SIZE; 902b6411739SVlad Zolotarov } 903b6411739SVlad Zolotarov 904b6411739SVlad Zolotarov static int ixgbevf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, 905b6411739SVlad Zolotarov u8 *hfunc) 906b6411739SVlad Zolotarov { 907b6411739SVlad Zolotarov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 908b6411739SVlad Zolotarov int err = 0; 909b6411739SVlad Zolotarov 910b6411739SVlad Zolotarov if (hfunc) 911b6411739SVlad Zolotarov *hfunc = ETH_RSS_HASH_TOP; 912b6411739SVlad Zolotarov 9139cba434fSEmil Tantilov if (adapter->hw.mac.type >= ixgbe_mac_X550_vf) { 9149cba434fSEmil Tantilov if (key) 915e60ae003STony Nguyen memcpy(key, adapter->rss_key, 916e60ae003STony Nguyen ixgbevf_get_rxfh_key_size(netdev)); 9179cba434fSEmil Tantilov 9189cba434fSEmil Tantilov if (indir) { 9199cba434fSEmil Tantilov int i; 9209cba434fSEmil Tantilov 9219cba434fSEmil Tantilov for (i = 0; i < IXGBEVF_X550_VFRETA_SIZE; i++) 9229cba434fSEmil Tantilov indir[i] = adapter->rss_indir_tbl[i]; 9239cba434fSEmil Tantilov } 9249cba434fSEmil Tantilov } else { 9259cba434fSEmil Tantilov /* If neither indirection table nor hash key was requested 9269cba434fSEmil Tantilov * - just return a success avoiding taking any locks. 927b6411739SVlad Zolotarov */ 928b6411739SVlad Zolotarov if (!indir && !key) 929b6411739SVlad Zolotarov return 0; 930b6411739SVlad Zolotarov 931b6411739SVlad Zolotarov spin_lock_bh(&adapter->mbx_lock); 932b6411739SVlad Zolotarov if (indir) 933b6411739SVlad Zolotarov err = ixgbevf_get_reta_locked(&adapter->hw, indir, 934b6411739SVlad Zolotarov adapter->num_rx_queues); 935b6411739SVlad Zolotarov 936b6411739SVlad Zolotarov if (!err && key) 937b6411739SVlad Zolotarov err = ixgbevf_get_rss_key_locked(&adapter->hw, key); 938b6411739SVlad Zolotarov 939b6411739SVlad Zolotarov spin_unlock_bh(&adapter->mbx_lock); 9409cba434fSEmil Tantilov } 941b6411739SVlad Zolotarov 942b6411739SVlad Zolotarov return err; 943b6411739SVlad Zolotarov } 944b6411739SVlad Zolotarov 945bc04347fSEmil Tantilov static u32 ixgbevf_get_priv_flags(struct net_device *netdev) 946bc04347fSEmil Tantilov { 947bc04347fSEmil Tantilov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 948bc04347fSEmil Tantilov u32 priv_flags = 0; 949bc04347fSEmil Tantilov 950bc04347fSEmil Tantilov if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) 951bc04347fSEmil Tantilov priv_flags |= IXGBEVF_PRIV_FLAGS_LEGACY_RX; 952bc04347fSEmil Tantilov 953bc04347fSEmil Tantilov return priv_flags; 954bc04347fSEmil Tantilov } 955bc04347fSEmil Tantilov 956bc04347fSEmil Tantilov static int ixgbevf_set_priv_flags(struct net_device *netdev, u32 priv_flags) 957bc04347fSEmil Tantilov { 958bc04347fSEmil Tantilov struct ixgbevf_adapter *adapter = netdev_priv(netdev); 959bc04347fSEmil Tantilov unsigned int flags = adapter->flags; 960bc04347fSEmil Tantilov 961bc04347fSEmil Tantilov flags &= ~IXGBEVF_FLAGS_LEGACY_RX; 962bc04347fSEmil Tantilov if (priv_flags & IXGBEVF_PRIV_FLAGS_LEGACY_RX) 963bc04347fSEmil Tantilov flags |= IXGBEVF_FLAGS_LEGACY_RX; 964bc04347fSEmil Tantilov 965bc04347fSEmil Tantilov if (flags != adapter->flags) { 966bc04347fSEmil Tantilov adapter->flags = flags; 967bc04347fSEmil Tantilov 968bc04347fSEmil Tantilov /* reset interface to repopulate queues */ 969bc04347fSEmil Tantilov if (netif_running(netdev)) 970bc04347fSEmil Tantilov ixgbevf_reinit_locked(adapter); 971bc04347fSEmil Tantilov } 972bc04347fSEmil Tantilov 973bc04347fSEmil Tantilov return 0; 974bc04347fSEmil Tantilov } 975bc04347fSEmil Tantilov 976b47aca13SStephen Hemminger static const struct ethtool_ops ixgbevf_ethtool_ops = { 977dee1ad47SJeff Kirsher .get_drvinfo = ixgbevf_get_drvinfo, 978dee1ad47SJeff Kirsher .get_regs_len = ixgbevf_get_regs_len, 979dee1ad47SJeff Kirsher .get_regs = ixgbevf_get_regs, 980dee1ad47SJeff Kirsher .nway_reset = ixgbevf_nway_reset, 981dee1ad47SJeff Kirsher .get_link = ethtool_op_get_link, 982dee1ad47SJeff Kirsher .get_ringparam = ixgbevf_get_ringparam, 983dee1ad47SJeff Kirsher .set_ringparam = ixgbevf_set_ringparam, 984dee1ad47SJeff Kirsher .get_msglevel = ixgbevf_get_msglevel, 985dee1ad47SJeff Kirsher .set_msglevel = ixgbevf_set_msglevel, 986dee1ad47SJeff Kirsher .self_test = ixgbevf_diag_test, 987dee1ad47SJeff Kirsher .get_sset_count = ixgbevf_get_sset_count, 988dee1ad47SJeff Kirsher .get_strings = ixgbevf_get_strings, 989dee1ad47SJeff Kirsher .get_ethtool_stats = ixgbevf_get_ethtool_stats, 9903849623eSJacob Keller .get_coalesce = ixgbevf_get_coalesce, 9913849623eSJacob Keller .set_coalesce = ixgbevf_set_coalesce, 992b6411739SVlad Zolotarov .get_rxnfc = ixgbevf_get_rxnfc, 993b6411739SVlad Zolotarov .get_rxfh_indir_size = ixgbevf_get_rxfh_indir_size, 994b6411739SVlad Zolotarov .get_rxfh_key_size = ixgbevf_get_rxfh_key_size, 995b6411739SVlad Zolotarov .get_rxfh = ixgbevf_get_rxfh, 9969668c936SPhilippe Reynes .get_link_ksettings = ixgbevf_get_link_ksettings, 997bc04347fSEmil Tantilov .get_priv_flags = ixgbevf_get_priv_flags, 998bc04347fSEmil Tantilov .set_priv_flags = ixgbevf_set_priv_flags, 999dee1ad47SJeff Kirsher }; 1000dee1ad47SJeff Kirsher 1001dee1ad47SJeff Kirsher void ixgbevf_set_ethtool_ops(struct net_device *netdev) 1002dee1ad47SJeff Kirsher { 10037ad24ea4SWilfried Klaebe netdev->ethtool_ops = &ixgbevf_ethtool_ops; 1004dee1ad47SJeff Kirsher } 1005