Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009 - 2018 Intel Corporation. */
0003 
0004 /* ethtool support for igbvf */
0005 
0006 #include <linux/netdevice.h>
0007 #include <linux/ethtool.h>
0008 #include <linux/pci.h>
0009 #include <linux/vmalloc.h>
0010 #include <linux/delay.h>
0011 
0012 #include "igbvf.h"
0013 #include <linux/if_vlan.h>
0014 
0015 struct igbvf_stats {
0016     char stat_string[ETH_GSTRING_LEN];
0017     int sizeof_stat;
0018     int stat_offset;
0019     int base_stat_offset;
0020 };
0021 
0022 #define IGBVF_STAT(current, base) \
0023         sizeof(((struct igbvf_adapter *)0)->current), \
0024         offsetof(struct igbvf_adapter, current), \
0025         offsetof(struct igbvf_adapter, base)
0026 
0027 static const struct igbvf_stats igbvf_gstrings_stats[] = {
0028     { "rx_packets", IGBVF_STAT(stats.gprc, stats.base_gprc) },
0029     { "tx_packets", IGBVF_STAT(stats.gptc, stats.base_gptc) },
0030     { "rx_bytes", IGBVF_STAT(stats.gorc, stats.base_gorc) },
0031     { "tx_bytes", IGBVF_STAT(stats.gotc, stats.base_gotc) },
0032     { "multicast", IGBVF_STAT(stats.mprc, stats.base_mprc) },
0033     { "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) },
0034     { "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) },
0035     { "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) },
0036     { "rx_long_byte_count", IGBVF_STAT(stats.gorc, stats.base_gorc) },
0037     { "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) },
0038     { "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) },
0039     { "rx_header_split", IGBVF_STAT(rx_hdr_split, zero_base) },
0040     { "alloc_rx_buff_failed", IGBVF_STAT(alloc_rx_buff_failed, zero_base) },
0041 };
0042 
0043 #define IGBVF_GLOBAL_STATS_LEN ARRAY_SIZE(igbvf_gstrings_stats)
0044 
0045 static const char igbvf_gstrings_test[][ETH_GSTRING_LEN] = {
0046     "Link test   (on/offline)"
0047 };
0048 
0049 #define IGBVF_TEST_LEN ARRAY_SIZE(igbvf_gstrings_test)
0050 
0051 static int igbvf_get_link_ksettings(struct net_device *netdev,
0052                     struct ethtool_link_ksettings *cmd)
0053 {
0054     struct igbvf_adapter *adapter = netdev_priv(netdev);
0055     struct e1000_hw *hw = &adapter->hw;
0056     u32 status;
0057 
0058     ethtool_link_ksettings_zero_link_mode(cmd, supported);
0059     ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full);
0060     ethtool_link_ksettings_zero_link_mode(cmd, advertising);
0061     ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full);
0062 
0063     cmd->base.port = -1;
0064 
0065     status = er32(STATUS);
0066     if (status & E1000_STATUS_LU) {
0067         if (status & E1000_STATUS_SPEED_1000)
0068             cmd->base.speed = SPEED_1000;
0069         else if (status & E1000_STATUS_SPEED_100)
0070             cmd->base.speed = SPEED_100;
0071         else
0072             cmd->base.speed = SPEED_10;
0073 
0074         if (status & E1000_STATUS_FD)
0075             cmd->base.duplex = DUPLEX_FULL;
0076         else
0077             cmd->base.duplex = DUPLEX_HALF;
0078     } else {
0079         cmd->base.speed = SPEED_UNKNOWN;
0080         cmd->base.duplex = DUPLEX_UNKNOWN;
0081     }
0082 
0083     cmd->base.autoneg = AUTONEG_DISABLE;
0084 
0085     return 0;
0086 }
0087 
0088 static int igbvf_set_link_ksettings(struct net_device *netdev,
0089                     const struct ethtool_link_ksettings *cmd)
0090 {
0091     return -EOPNOTSUPP;
0092 }
0093 
0094 static void igbvf_get_pauseparam(struct net_device *netdev,
0095                  struct ethtool_pauseparam *pause)
0096 {
0097 }
0098 
0099 static int igbvf_set_pauseparam(struct net_device *netdev,
0100                 struct ethtool_pauseparam *pause)
0101 {
0102     return -EOPNOTSUPP;
0103 }
0104 
0105 static u32 igbvf_get_msglevel(struct net_device *netdev)
0106 {
0107     struct igbvf_adapter *adapter = netdev_priv(netdev);
0108 
0109     return adapter->msg_enable;
0110 }
0111 
0112 static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
0113 {
0114     struct igbvf_adapter *adapter = netdev_priv(netdev);
0115 
0116     adapter->msg_enable = data;
0117 }
0118 
0119 static int igbvf_get_regs_len(struct net_device *netdev)
0120 {
0121 #define IGBVF_REGS_LEN 8
0122     return IGBVF_REGS_LEN * sizeof(u32);
0123 }
0124 
0125 static void igbvf_get_regs(struct net_device *netdev,
0126                struct ethtool_regs *regs, void *p)
0127 {
0128     struct igbvf_adapter *adapter = netdev_priv(netdev);
0129     struct e1000_hw *hw = &adapter->hw;
0130     u32 *regs_buff = p;
0131 
0132     memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
0133 
0134     regs->version = (1u << 24) |
0135             (adapter->pdev->revision << 16) |
0136             adapter->pdev->device;
0137 
0138     regs_buff[0] = er32(CTRL);
0139     regs_buff[1] = er32(STATUS);
0140 
0141     regs_buff[2] = er32(RDLEN(0));
0142     regs_buff[3] = er32(RDH(0));
0143     regs_buff[4] = er32(RDT(0));
0144 
0145     regs_buff[5] = er32(TDLEN(0));
0146     regs_buff[6] = er32(TDH(0));
0147     regs_buff[7] = er32(TDT(0));
0148 }
0149 
0150 static int igbvf_get_eeprom_len(struct net_device *netdev)
0151 {
0152     return 0;
0153 }
0154 
0155 static int igbvf_get_eeprom(struct net_device *netdev,
0156                 struct ethtool_eeprom *eeprom, u8 *bytes)
0157 {
0158     return -EOPNOTSUPP;
0159 }
0160 
0161 static int igbvf_set_eeprom(struct net_device *netdev,
0162                 struct ethtool_eeprom *eeprom, u8 *bytes)
0163 {
0164     return -EOPNOTSUPP;
0165 }
0166 
0167 static void igbvf_get_drvinfo(struct net_device *netdev,
0168                   struct ethtool_drvinfo *drvinfo)
0169 {
0170     struct igbvf_adapter *adapter = netdev_priv(netdev);
0171 
0172     strlcpy(drvinfo->driver,  igbvf_driver_name, sizeof(drvinfo->driver));
0173     strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
0174         sizeof(drvinfo->bus_info));
0175 }
0176 
0177 static void igbvf_get_ringparam(struct net_device *netdev,
0178                 struct ethtool_ringparam *ring,
0179                 struct kernel_ethtool_ringparam *kernel_ring,
0180                 struct netlink_ext_ack *extack)
0181 {
0182     struct igbvf_adapter *adapter = netdev_priv(netdev);
0183     struct igbvf_ring *tx_ring = adapter->tx_ring;
0184     struct igbvf_ring *rx_ring = adapter->rx_ring;
0185 
0186     ring->rx_max_pending = IGBVF_MAX_RXD;
0187     ring->tx_max_pending = IGBVF_MAX_TXD;
0188     ring->rx_pending = rx_ring->count;
0189     ring->tx_pending = tx_ring->count;
0190 }
0191 
0192 static int igbvf_set_ringparam(struct net_device *netdev,
0193                    struct ethtool_ringparam *ring,
0194                    struct kernel_ethtool_ringparam *kernel_ring,
0195                    struct netlink_ext_ack *extack)
0196 {
0197     struct igbvf_adapter *adapter = netdev_priv(netdev);
0198     struct igbvf_ring *temp_ring;
0199     int err = 0;
0200     u32 new_rx_count, new_tx_count;
0201 
0202     if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
0203         return -EINVAL;
0204 
0205     new_rx_count = max_t(u32, ring->rx_pending, IGBVF_MIN_RXD);
0206     new_rx_count = min_t(u32, new_rx_count, IGBVF_MAX_RXD);
0207     new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
0208 
0209     new_tx_count = max_t(u32, ring->tx_pending, IGBVF_MIN_TXD);
0210     new_tx_count = min_t(u32, new_tx_count, IGBVF_MAX_TXD);
0211     new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
0212 
0213     if ((new_tx_count == adapter->tx_ring->count) &&
0214         (new_rx_count == adapter->rx_ring->count)) {
0215         /* nothing to do */
0216         return 0;
0217     }
0218 
0219     while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
0220         usleep_range(1000, 2000);
0221 
0222     if (!netif_running(adapter->netdev)) {
0223         adapter->tx_ring->count = new_tx_count;
0224         adapter->rx_ring->count = new_rx_count;
0225         goto clear_reset;
0226     }
0227 
0228     temp_ring = vmalloc(sizeof(struct igbvf_ring));
0229     if (!temp_ring) {
0230         err = -ENOMEM;
0231         goto clear_reset;
0232     }
0233 
0234     igbvf_down(adapter);
0235 
0236     /* We can't just free everything and then setup again,
0237      * because the ISRs in MSI-X mode get passed pointers
0238      * to the Tx and Rx ring structs.
0239      */
0240     if (new_tx_count != adapter->tx_ring->count) {
0241         memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
0242 
0243         temp_ring->count = new_tx_count;
0244         err = igbvf_setup_tx_resources(adapter, temp_ring);
0245         if (err)
0246             goto err_setup;
0247 
0248         igbvf_free_tx_resources(adapter->tx_ring);
0249 
0250         memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
0251     }
0252 
0253     if (new_rx_count != adapter->rx_ring->count) {
0254         memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
0255 
0256         temp_ring->count = new_rx_count;
0257         err = igbvf_setup_rx_resources(adapter, temp_ring);
0258         if (err)
0259             goto err_setup;
0260 
0261         igbvf_free_rx_resources(adapter->rx_ring);
0262 
0263         memcpy(adapter->rx_ring, temp_ring, sizeof(struct igbvf_ring));
0264     }
0265 err_setup:
0266     igbvf_up(adapter);
0267     vfree(temp_ring);
0268 clear_reset:
0269     clear_bit(__IGBVF_RESETTING, &adapter->state);
0270     return err;
0271 }
0272 
0273 static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
0274 {
0275     struct e1000_hw *hw = &adapter->hw;
0276     *data = 0;
0277 
0278     spin_lock_bh(&hw->mbx_lock);
0279 
0280     hw->mac.ops.check_for_link(hw);
0281 
0282     spin_unlock_bh(&hw->mbx_lock);
0283 
0284     if (!(er32(STATUS) & E1000_STATUS_LU))
0285         *data = 1;
0286 
0287     return *data;
0288 }
0289 
0290 static void igbvf_diag_test(struct net_device *netdev,
0291                 struct ethtool_test *eth_test, u64 *data)
0292 {
0293     struct igbvf_adapter *adapter = netdev_priv(netdev);
0294 
0295     set_bit(__IGBVF_TESTING, &adapter->state);
0296 
0297     /* Link test performed before hardware reset so autoneg doesn't
0298      * interfere with test result
0299      */
0300     if (igbvf_link_test(adapter, &data[0]))
0301         eth_test->flags |= ETH_TEST_FL_FAILED;
0302 
0303     clear_bit(__IGBVF_TESTING, &adapter->state);
0304     msleep_interruptible(4 * 1000);
0305 }
0306 
0307 static void igbvf_get_wol(struct net_device *netdev,
0308               struct ethtool_wolinfo *wol)
0309 {
0310     wol->supported = 0;
0311     wol->wolopts = 0;
0312 }
0313 
0314 static int igbvf_set_wol(struct net_device *netdev,
0315              struct ethtool_wolinfo *wol)
0316 {
0317     return -EOPNOTSUPP;
0318 }
0319 
0320 static int igbvf_get_coalesce(struct net_device *netdev,
0321                   struct ethtool_coalesce *ec,
0322                   struct kernel_ethtool_coalesce *kernel_coal,
0323                   struct netlink_ext_ack *extack)
0324 {
0325     struct igbvf_adapter *adapter = netdev_priv(netdev);
0326 
0327     if (adapter->requested_itr <= 3)
0328         ec->rx_coalesce_usecs = adapter->requested_itr;
0329     else
0330         ec->rx_coalesce_usecs = adapter->current_itr >> 2;
0331 
0332     return 0;
0333 }
0334 
0335 static int igbvf_set_coalesce(struct net_device *netdev,
0336                   struct ethtool_coalesce *ec,
0337                   struct kernel_ethtool_coalesce *kernel_coal,
0338                   struct netlink_ext_ack *extack)
0339 {
0340     struct igbvf_adapter *adapter = netdev_priv(netdev);
0341     struct e1000_hw *hw = &adapter->hw;
0342 
0343     if ((ec->rx_coalesce_usecs >= IGBVF_MIN_ITR_USECS) &&
0344         (ec->rx_coalesce_usecs <= IGBVF_MAX_ITR_USECS)) {
0345         adapter->current_itr = ec->rx_coalesce_usecs << 2;
0346         adapter->requested_itr = 1000000000 /
0347                     (adapter->current_itr * 256);
0348     } else if ((ec->rx_coalesce_usecs == 3) ||
0349            (ec->rx_coalesce_usecs == 2)) {
0350         adapter->current_itr = IGBVF_START_ITR;
0351         adapter->requested_itr = ec->rx_coalesce_usecs;
0352     } else if (ec->rx_coalesce_usecs == 0) {
0353         /* The user's desire is to turn off interrupt throttling
0354          * altogether, but due to HW limitations, we can't do that.
0355          * Instead we set a very small value in EITR, which would
0356          * allow ~967k interrupts per second, but allow the adapter's
0357          * internal clocking to still function properly.
0358          */
0359         adapter->current_itr = 4;
0360         adapter->requested_itr = 1000000000 /
0361                     (adapter->current_itr * 256);
0362     } else {
0363         return -EINVAL;
0364     }
0365 
0366     writel(adapter->current_itr,
0367            hw->hw_addr + adapter->rx_ring->itr_register);
0368 
0369     return 0;
0370 }
0371 
0372 static int igbvf_nway_reset(struct net_device *netdev)
0373 {
0374     struct igbvf_adapter *adapter = netdev_priv(netdev);
0375 
0376     if (netif_running(netdev))
0377         igbvf_reinit_locked(adapter);
0378     return 0;
0379 }
0380 
0381 static void igbvf_get_ethtool_stats(struct net_device *netdev,
0382                     struct ethtool_stats *stats,
0383                     u64 *data)
0384 {
0385     struct igbvf_adapter *adapter = netdev_priv(netdev);
0386     int i;
0387 
0388     igbvf_update_stats(adapter);
0389     for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
0390         char *p = (char *)adapter +
0391               igbvf_gstrings_stats[i].stat_offset;
0392         char *b = (char *)adapter +
0393               igbvf_gstrings_stats[i].base_stat_offset;
0394         data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
0395                 sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
0396                 (*(u32 *)p - *(u32 *)b));
0397     }
0398 }
0399 
0400 static int igbvf_get_sset_count(struct net_device *dev, int stringset)
0401 {
0402     switch (stringset) {
0403     case ETH_SS_TEST:
0404         return IGBVF_TEST_LEN;
0405     case ETH_SS_STATS:
0406         return IGBVF_GLOBAL_STATS_LEN;
0407     default:
0408         return -EINVAL;
0409     }
0410 }
0411 
0412 static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
0413                   u8 *data)
0414 {
0415     u8 *p = data;
0416     int i;
0417 
0418     switch (stringset) {
0419     case ETH_SS_TEST:
0420         memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
0421         break;
0422     case ETH_SS_STATS:
0423         for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
0424             memcpy(p, igbvf_gstrings_stats[i].stat_string,
0425                    ETH_GSTRING_LEN);
0426             p += ETH_GSTRING_LEN;
0427         }
0428         break;
0429     }
0430 }
0431 
0432 static const struct ethtool_ops igbvf_ethtool_ops = {
0433     .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS,
0434     .get_drvinfo        = igbvf_get_drvinfo,
0435     .get_regs_len       = igbvf_get_regs_len,
0436     .get_regs       = igbvf_get_regs,
0437     .get_wol        = igbvf_get_wol,
0438     .set_wol        = igbvf_set_wol,
0439     .get_msglevel       = igbvf_get_msglevel,
0440     .set_msglevel       = igbvf_set_msglevel,
0441     .nway_reset     = igbvf_nway_reset,
0442     .get_link       = ethtool_op_get_link,
0443     .get_eeprom_len     = igbvf_get_eeprom_len,
0444     .get_eeprom     = igbvf_get_eeprom,
0445     .set_eeprom     = igbvf_set_eeprom,
0446     .get_ringparam      = igbvf_get_ringparam,
0447     .set_ringparam      = igbvf_set_ringparam,
0448     .get_pauseparam     = igbvf_get_pauseparam,
0449     .set_pauseparam     = igbvf_set_pauseparam,
0450     .self_test      = igbvf_diag_test,
0451     .get_sset_count     = igbvf_get_sset_count,
0452     .get_strings        = igbvf_get_strings,
0453     .get_ethtool_stats  = igbvf_get_ethtool_stats,
0454     .get_coalesce       = igbvf_get_coalesce,
0455     .set_coalesce       = igbvf_set_coalesce,
0456     .get_link_ksettings = igbvf_get_link_ksettings,
0457     .set_link_ksettings = igbvf_set_link_ksettings,
0458 };
0459 
0460 void igbvf_set_ethtool_ops(struct net_device *netdev)
0461 {
0462     netdev->ethtool_ops = &igbvf_ethtool_ops;
0463 }