Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /****************************************************************************
0003  * Driver for Solarflare network controllers and boards
0004  * Copyright 2005-2006 Fen Systems Ltd.
0005  * Copyright 2006-2013 Solarflare Communications Inc.
0006  */
0007 
0008 #include <linux/netdevice.h>
0009 #include <linux/ethtool.h>
0010 #include <linux/rtnetlink.h>
0011 #include <linux/in.h>
0012 #include "net_driver.h"
0013 #include "workarounds.h"
0014 #include "selftest.h"
0015 #include "efx.h"
0016 #include "efx_channels.h"
0017 #include "rx_common.h"
0018 #include "tx_common.h"
0019 #include "ethtool_common.h"
0020 #include "filter.h"
0021 #include "nic.h"
0022 
0023 #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB
0024 
0025 /**************************************************************************
0026  *
0027  * Ethtool operations
0028  *
0029  **************************************************************************
0030  */
0031 
0032 /* Identify device by flashing LEDs */
0033 static int efx_ethtool_phys_id(struct net_device *net_dev,
0034                    enum ethtool_phys_id_state state)
0035 {
0036     struct efx_nic *efx = efx_netdev_priv(net_dev);
0037     enum efx_led_mode mode = EFX_LED_DEFAULT;
0038 
0039     switch (state) {
0040     case ETHTOOL_ID_ON:
0041         mode = EFX_LED_ON;
0042         break;
0043     case ETHTOOL_ID_OFF:
0044         mode = EFX_LED_OFF;
0045         break;
0046     case ETHTOOL_ID_INACTIVE:
0047         mode = EFX_LED_DEFAULT;
0048         break;
0049     case ETHTOOL_ID_ACTIVE:
0050         return 1;   /* cycle on/off once per second */
0051     }
0052 
0053     return efx_mcdi_set_id_led(efx, mode);
0054 }
0055 
0056 static int efx_ethtool_get_regs_len(struct net_device *net_dev)
0057 {
0058     return efx_nic_get_regs_len(efx_netdev_priv(net_dev));
0059 }
0060 
0061 static void efx_ethtool_get_regs(struct net_device *net_dev,
0062                  struct ethtool_regs *regs, void *buf)
0063 {
0064     struct efx_nic *efx = efx_netdev_priv(net_dev);
0065 
0066     regs->version = efx->type->revision;
0067     efx_nic_get_regs(efx, buf);
0068 }
0069 
0070 /*
0071  * Each channel has a single IRQ and moderation timer, started by any
0072  * completion (or other event).  Unless the module parameter
0073  * separate_tx_channels is set, IRQs and moderation are therefore
0074  * shared between RX and TX completions.  In this case, when RX IRQ
0075  * moderation is explicitly changed then TX IRQ moderation is
0076  * automatically changed too, but otherwise we fail if the two values
0077  * are requested to be different.
0078  *
0079  * The hardware does not support a limit on the number of completions
0080  * before an IRQ, so we do not use the max_frames fields.  We should
0081  * report and require that max_frames == (usecs != 0), but this would
0082  * invalidate existing user documentation.
0083  *
0084  * The hardware does not have distinct settings for interrupt
0085  * moderation while the previous IRQ is being handled, so we should
0086  * not use the 'irq' fields.  However, an earlier developer
0087  * misunderstood the meaning of the 'irq' fields and the driver did
0088  * not support the standard fields.  To avoid invalidating existing
0089  * user documentation, we report and accept changes through either the
0090  * standard or 'irq' fields.  If both are changed at the same time, we
0091  * prefer the standard field.
0092  *
0093  * We implement adaptive IRQ moderation, but use a different algorithm
0094  * from that assumed in the definition of struct ethtool_coalesce.
0095  * Therefore we do not use any of the adaptive moderation parameters
0096  * in it.
0097  */
0098 
0099 static int efx_ethtool_get_coalesce(struct net_device *net_dev,
0100                     struct ethtool_coalesce *coalesce,
0101                     struct kernel_ethtool_coalesce *kernel_coal,
0102                     struct netlink_ext_ack *extack)
0103 {
0104     struct efx_nic *efx = efx_netdev_priv(net_dev);
0105     unsigned int tx_usecs, rx_usecs;
0106     bool rx_adaptive;
0107 
0108     efx_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &rx_adaptive);
0109 
0110     coalesce->tx_coalesce_usecs = tx_usecs;
0111     coalesce->tx_coalesce_usecs_irq = tx_usecs;
0112     coalesce->rx_coalesce_usecs = rx_usecs;
0113     coalesce->rx_coalesce_usecs_irq = rx_usecs;
0114     coalesce->use_adaptive_rx_coalesce = rx_adaptive;
0115 
0116     return 0;
0117 }
0118 
0119 static int efx_ethtool_set_coalesce(struct net_device *net_dev,
0120                     struct ethtool_coalesce *coalesce,
0121                     struct kernel_ethtool_coalesce *kernel_coal,
0122                     struct netlink_ext_ack *extack)
0123 {
0124     struct efx_nic *efx = efx_netdev_priv(net_dev);
0125     struct efx_channel *channel;
0126     unsigned int tx_usecs, rx_usecs;
0127     bool adaptive, rx_may_override_tx;
0128     int rc;
0129 
0130     efx_get_irq_moderation(efx, &tx_usecs, &rx_usecs, &adaptive);
0131 
0132     if (coalesce->rx_coalesce_usecs != rx_usecs)
0133         rx_usecs = coalesce->rx_coalesce_usecs;
0134     else
0135         rx_usecs = coalesce->rx_coalesce_usecs_irq;
0136 
0137     adaptive = coalesce->use_adaptive_rx_coalesce;
0138 
0139     /* If channels are shared, TX IRQ moderation can be quietly
0140      * overridden unless it is changed from its old value.
0141      */
0142     rx_may_override_tx = (coalesce->tx_coalesce_usecs == tx_usecs &&
0143                   coalesce->tx_coalesce_usecs_irq == tx_usecs);
0144     if (coalesce->tx_coalesce_usecs != tx_usecs)
0145         tx_usecs = coalesce->tx_coalesce_usecs;
0146     else
0147         tx_usecs = coalesce->tx_coalesce_usecs_irq;
0148 
0149     rc = efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive,
0150                      rx_may_override_tx);
0151     if (rc != 0)
0152         return rc;
0153 
0154     efx_for_each_channel(channel, efx)
0155         efx->type->push_irq_moderation(channel);
0156 
0157     return 0;
0158 }
0159 
0160 static void
0161 efx_ethtool_get_ringparam(struct net_device *net_dev,
0162               struct ethtool_ringparam *ring,
0163               struct kernel_ethtool_ringparam *kernel_ring,
0164               struct netlink_ext_ack *extack)
0165 {
0166     struct efx_nic *efx = efx_netdev_priv(net_dev);
0167 
0168     ring->rx_max_pending = EFX_MAX_DMAQ_SIZE;
0169     ring->tx_max_pending = EFX_TXQ_MAX_ENT(efx);
0170     ring->rx_pending = efx->rxq_entries;
0171     ring->tx_pending = efx->txq_entries;
0172 }
0173 
0174 static int
0175 efx_ethtool_set_ringparam(struct net_device *net_dev,
0176               struct ethtool_ringparam *ring,
0177               struct kernel_ethtool_ringparam *kernel_ring,
0178               struct netlink_ext_ack *extack)
0179 {
0180     struct efx_nic *efx = efx_netdev_priv(net_dev);
0181     u32 txq_entries;
0182 
0183     if (ring->rx_mini_pending || ring->rx_jumbo_pending ||
0184         ring->rx_pending > EFX_MAX_DMAQ_SIZE ||
0185         ring->tx_pending > EFX_TXQ_MAX_ENT(efx))
0186         return -EINVAL;
0187 
0188     if (ring->rx_pending < EFX_RXQ_MIN_ENT) {
0189         netif_err(efx, drv, efx->net_dev,
0190               "RX queues cannot be smaller than %u\n",
0191               EFX_RXQ_MIN_ENT);
0192         return -EINVAL;
0193     }
0194 
0195     txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx));
0196     if (txq_entries != ring->tx_pending)
0197         netif_warn(efx, drv, efx->net_dev,
0198                "increasing TX queue size to minimum of %u\n",
0199                txq_entries);
0200 
0201     return efx_realloc_channels(efx, ring->rx_pending, txq_entries);
0202 }
0203 
0204 static void efx_ethtool_get_wol(struct net_device *net_dev,
0205                 struct ethtool_wolinfo *wol)
0206 {
0207     struct efx_nic *efx = efx_netdev_priv(net_dev);
0208     return efx->type->get_wol(efx, wol);
0209 }
0210 
0211 
0212 static int efx_ethtool_set_wol(struct net_device *net_dev,
0213                    struct ethtool_wolinfo *wol)
0214 {
0215     struct efx_nic *efx = efx_netdev_priv(net_dev);
0216     return efx->type->set_wol(efx, wol->wolopts);
0217 }
0218 
0219 static void efx_ethtool_get_fec_stats(struct net_device *net_dev,
0220                       struct ethtool_fec_stats *fec_stats)
0221 {
0222     struct efx_nic *efx = efx_netdev_priv(net_dev);
0223 
0224     if (efx->type->get_fec_stats)
0225         efx->type->get_fec_stats(efx, fec_stats);
0226 }
0227 
0228 static int efx_ethtool_get_ts_info(struct net_device *net_dev,
0229                    struct ethtool_ts_info *ts_info)
0230 {
0231     struct efx_nic *efx = efx_netdev_priv(net_dev);
0232 
0233     /* Software capabilities */
0234     ts_info->so_timestamping = (SOF_TIMESTAMPING_RX_SOFTWARE |
0235                     SOF_TIMESTAMPING_SOFTWARE);
0236     ts_info->phc_index = -1;
0237 
0238     efx_ptp_get_ts_info(efx, ts_info);
0239     return 0;
0240 }
0241 
0242 const struct ethtool_ops efx_ethtool_ops = {
0243     .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
0244                      ETHTOOL_COALESCE_USECS_IRQ |
0245                      ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
0246     .get_drvinfo        = efx_ethtool_get_drvinfo,
0247     .get_regs_len       = efx_ethtool_get_regs_len,
0248     .get_regs       = efx_ethtool_get_regs,
0249     .get_msglevel       = efx_ethtool_get_msglevel,
0250     .set_msglevel       = efx_ethtool_set_msglevel,
0251     .get_link       = ethtool_op_get_link,
0252     .get_coalesce       = efx_ethtool_get_coalesce,
0253     .set_coalesce       = efx_ethtool_set_coalesce,
0254     .get_ringparam      = efx_ethtool_get_ringparam,
0255     .set_ringparam      = efx_ethtool_set_ringparam,
0256     .get_pauseparam         = efx_ethtool_get_pauseparam,
0257     .set_pauseparam         = efx_ethtool_set_pauseparam,
0258     .get_sset_count     = efx_ethtool_get_sset_count,
0259     .self_test      = efx_ethtool_self_test,
0260     .get_strings        = efx_ethtool_get_strings,
0261     .set_phys_id        = efx_ethtool_phys_id,
0262     .get_ethtool_stats  = efx_ethtool_get_stats,
0263     .get_wol                = efx_ethtool_get_wol,
0264     .set_wol                = efx_ethtool_set_wol,
0265     .reset          = efx_ethtool_reset,
0266     .get_rxnfc      = efx_ethtool_get_rxnfc,
0267     .set_rxnfc      = efx_ethtool_set_rxnfc,
0268     .get_rxfh_indir_size    = efx_ethtool_get_rxfh_indir_size,
0269     .get_rxfh_key_size  = efx_ethtool_get_rxfh_key_size,
0270     .get_rxfh       = efx_ethtool_get_rxfh,
0271     .set_rxfh       = efx_ethtool_set_rxfh,
0272     .get_rxfh_context   = efx_ethtool_get_rxfh_context,
0273     .set_rxfh_context   = efx_ethtool_set_rxfh_context,
0274     .get_ts_info        = efx_ethtool_get_ts_info,
0275     .get_module_info    = efx_ethtool_get_module_info,
0276     .get_module_eeprom  = efx_ethtool_get_module_eeprom,
0277     .get_link_ksettings = efx_ethtool_get_link_ksettings,
0278     .set_link_ksettings = efx_ethtool_set_link_ksettings,
0279     .get_fec_stats      = efx_ethtool_get_fec_stats,
0280     .get_fecparam       = efx_ethtool_get_fecparam,
0281     .set_fecparam       = efx_ethtool_set_fecparam,
0282 };