2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2008-04-27 12:55:59 +01:00
/****************************************************************************
2013-08-29 23:32:48 +01:00
* Driver for Solarflare network controllers and boards
2008-04-27 12:55:59 +01:00
* Copyright 2005 - 2006 Fen Systems Ltd .
2013-08-29 23:32:48 +01:00
* Copyright 2006 - 2013 Solarflare Communications Inc .
2008-04-27 12:55:59 +01:00
*/
# include <linux/netdevice.h>
# include <linux/ethtool.h>
# include <linux/rtnetlink.h>
2010-12-07 19:11:26 +00:00
# include <linux/in.h>
2008-04-27 12:55:59 +01:00
# include "net_driver.h"
2008-12-12 21:50:46 -08:00
# include "workarounds.h"
2008-05-07 13:36:19 +01:00
# include "selftest.h"
2008-04-27 12:55:59 +01:00
# include "efx.h"
2020-01-08 16:10:32 +00:00
# include "efx_channels.h"
# include "rx_common.h"
# include "tx_common.h"
2020-01-10 13:27:32 +00:00
# include "ethtool_common.h"
2010-09-20 08:43:42 +00:00
# include "filter.h"
2009-11-29 15:12:08 +00:00
# include "nic.h"
2008-04-27 12:55:59 +01:00
2008-09-01 12:47:16 +01:00
# define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB
2008-04-27 12:55:59 +01:00
/**************************************************************************
*
* Ethtool operations
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/* Identify device by flashing LEDs */
2011-04-02 00:43:46 +01:00
static int efx_ethtool_phys_id ( struct net_device * net_dev ,
enum ethtool_phys_id_state state )
2008-04-27 12:55:59 +01:00
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2011-04-13 13:09:10 +00:00
enum efx_led_mode mode = EFX_LED_DEFAULT ;
2008-04-27 12:55:59 +01:00
2011-04-02 00:43:46 +01:00
switch ( state ) {
case ETHTOOL_ID_ON :
mode = EFX_LED_ON ;
break ;
case ETHTOOL_ID_OFF :
mode = EFX_LED_OFF ;
break ;
case ETHTOOL_ID_INACTIVE :
mode = EFX_LED_DEFAULT ;
break ;
2011-04-13 13:09:10 +00:00
case ETHTOOL_ID_ACTIVE :
return 1 ; /* cycle on/off once per second */
2011-04-02 00:43:46 +01:00
}
2009-11-23 16:03:45 +00:00
2020-08-28 18:51:04 +01:00
return efx_mcdi_set_id_led ( efx , mode ) ;
2008-04-27 12:55:59 +01:00
}
2010-06-21 03:06:53 +00:00
static int efx_ethtool_get_regs_len ( struct net_device * net_dev )
{
2022-06-28 14:59:45 +01:00
return efx_nic_get_regs_len ( efx_netdev_priv ( net_dev ) ) ;
2010-06-21 03:06:53 +00:00
}
static void efx_ethtool_get_regs ( struct net_device * net_dev ,
struct ethtool_regs * regs , void * buf )
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2010-06-21 03:06:53 +00:00
regs - > version = efx - > type - > revision ;
efx_nic_get_regs ( efx , buf ) ;
}
2011-09-05 07:42:25 +00:00
/*
* Each channel has a single IRQ and moderation timer , started by any
* completion ( or other event ) . Unless the module parameter
* separate_tx_channels is set , IRQs and moderation are therefore
* shared between RX and TX completions . In this case , when RX IRQ
* moderation is explicitly changed then TX IRQ moderation is
* automatically changed too , but otherwise we fail if the two values
* are requested to be different .
*
2011-09-05 07:43:49 +00:00
* The hardware does not support a limit on the number of completions
* before an IRQ , so we do not use the max_frames fields . We should
* report and require that max_frames = = ( usecs ! = 0 ) , but this would
* invalidate existing user documentation .
*
* The hardware does not have distinct settings for interrupt
* moderation while the previous IRQ is being handled , so we should
* not use the ' irq ' fields . However , an earlier developer
* misunderstood the meaning of the ' irq ' fields and the driver did
* not support the standard fields . To avoid invalidating existing
* user documentation , we report and accept changes through either the
* standard or ' irq ' fields . If both are changed at the same time , we
* prefer the standard field .
*
2011-09-05 07:42:25 +00:00
* We implement adaptive IRQ moderation , but use a different algorithm
* from that assumed in the definition of struct ethtool_coalesce .
* Therefore we do not use any of the adaptive moderation parameters
* in it .
*/
2008-04-27 12:55:59 +01:00
static int efx_ethtool_get_coalesce ( struct net_device * net_dev ,
2021-08-20 15:35:18 +08:00
struct ethtool_coalesce * coalesce ,
struct kernel_ethtool_coalesce * kernel_coal ,
struct netlink_ext_ack * extack )
2008-04-27 12:55:59 +01:00
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2011-09-05 07:42:25 +00:00
unsigned int tx_usecs , rx_usecs ;
bool rx_adaptive ;
2008-04-27 12:55:59 +01:00
2011-09-05 07:42:25 +00:00
efx_get_irq_moderation ( efx , & tx_usecs , & rx_usecs , & rx_adaptive ) ;
2008-04-27 12:55:59 +01:00
2011-09-05 07:43:49 +00:00
coalesce - > tx_coalesce_usecs = tx_usecs ;
2011-09-05 07:42:25 +00:00
coalesce - > tx_coalesce_usecs_irq = tx_usecs ;
2011-09-05 07:43:49 +00:00
coalesce - > rx_coalesce_usecs = rx_usecs ;
2011-09-05 07:42:25 +00:00
coalesce - > rx_coalesce_usecs_irq = rx_usecs ;
coalesce - > use_adaptive_rx_coalesce = rx_adaptive ;
2009-10-23 08:32:13 +00:00
2008-04-27 12:55:59 +01:00
return 0 ;
}
static int efx_ethtool_set_coalesce ( struct net_device * net_dev ,
2021-08-20 15:35:18 +08:00
struct ethtool_coalesce * coalesce ,
struct kernel_ethtool_coalesce * kernel_coal ,
struct netlink_ext_ack * extack )
2008-04-27 12:55:59 +01:00
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2008-04-27 12:55:59 +01:00
struct efx_channel * channel ;
2011-09-05 07:41:44 +00:00
unsigned int tx_usecs , rx_usecs ;
2011-09-05 07:43:04 +00:00
bool adaptive , rx_may_override_tx ;
int rc ;
2008-04-27 12:55:59 +01:00
2011-09-05 07:42:25 +00:00
efx_get_irq_moderation ( efx , & tx_usecs , & rx_usecs , & adaptive ) ;
2011-09-05 07:43:49 +00:00
if ( coalesce - > rx_coalesce_usecs ! = rx_usecs )
rx_usecs = coalesce - > rx_coalesce_usecs ;
else
rx_usecs = coalesce - > rx_coalesce_usecs_irq ;
2009-03-20 13:30:37 +00:00
adaptive = coalesce - > use_adaptive_rx_coalesce ;
2008-04-27 12:55:59 +01:00
2011-09-05 07:42:25 +00:00
/* If channels are shared, TX IRQ moderation can be quietly
* overridden unless it is changed from its old value .
*/
2011-09-05 07:43:49 +00:00
rx_may_override_tx = ( coalesce - > tx_coalesce_usecs = = tx_usecs & &
coalesce - > tx_coalesce_usecs_irq = = tx_usecs ) ;
if ( coalesce - > tx_coalesce_usecs ! = tx_usecs )
tx_usecs = coalesce - > tx_coalesce_usecs ;
else
tx_usecs = coalesce - > tx_coalesce_usecs_irq ;
2008-04-27 12:55:59 +01:00
2011-09-05 07:43:04 +00:00
rc = efx_init_irq_moderation ( efx , tx_usecs , rx_usecs , adaptive ,
rx_may_override_tx ) ;
if ( rc ! = 0 )
return rc ;
2008-04-27 12:55:59 +01:00
efx_for_each_channel ( channel , efx )
2009-11-29 03:42:31 +00:00
efx - > type - > push_irq_moderation ( channel ) ;
2008-04-27 12:55:59 +01:00
return 0 ;
}
2021-11-18 20:12:43 +08:00
static void
efx_ethtool_get_ringparam ( struct net_device * net_dev ,
struct ethtool_ringparam * ring ,
struct kernel_ethtool_ringparam * kernel_ring ,
struct netlink_ext_ack * extack )
2010-09-10 06:42:33 +00:00
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2010-09-10 06:42:33 +00:00
ring - > rx_max_pending = EFX_MAX_DMAQ_SIZE ;
2014-01-23 14:35:48 +00:00
ring - > tx_max_pending = EFX_TXQ_MAX_ENT ( efx ) ;
2010-09-10 06:42:33 +00:00
ring - > rx_pending = efx - > rxq_entries ;
ring - > tx_pending = efx - > txq_entries ;
}
2021-11-18 20:12:43 +08:00
static int
efx_ethtool_set_ringparam ( struct net_device * net_dev ,
struct ethtool_ringparam * ring ,
struct kernel_ethtool_ringparam * kernel_ring ,
struct netlink_ext_ack * extack )
2010-09-10 06:42:33 +00:00
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2012-07-30 15:57:44 +00:00
u32 txq_entries ;
2010-09-10 06:42:33 +00:00
if ( ring - > rx_mini_pending | | ring - > rx_jumbo_pending | |
ring - > rx_pending > EFX_MAX_DMAQ_SIZE | |
2014-01-23 14:35:48 +00:00
ring - > tx_pending > EFX_TXQ_MAX_ENT ( efx ) )
2010-09-10 06:42:33 +00:00
return - EINVAL ;
2012-07-30 15:57:44 +00:00
if ( ring - > rx_pending < EFX_RXQ_MIN_ENT ) {
2010-09-10 06:42:33 +00:00
netif_err ( efx , drv , efx - > net_dev ,
2012-07-30 15:57:44 +00:00
" RX queues cannot be smaller than %u \n " ,
EFX_RXQ_MIN_ENT ) ;
2010-09-10 06:42:33 +00:00
return - EINVAL ;
}
2012-07-30 15:57:44 +00:00
txq_entries = max ( ring - > tx_pending , EFX_TXQ_MIN_ENT ( efx ) ) ;
if ( txq_entries ! = ring - > tx_pending )
netif_warn ( efx , drv , efx - > net_dev ,
" increasing TX queue size to minimum of %u \n " ,
txq_entries ) ;
return efx_realloc_channels ( efx , ring - > rx_pending , txq_entries ) ;
2010-09-10 06:42:33 +00:00
}
2009-11-29 03:43:07 +00:00
static void efx_ethtool_get_wol ( struct net_device * net_dev ,
struct ethtool_wolinfo * wol )
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2009-11-29 03:43:07 +00:00
return efx - > type - > get_wol ( efx , wol ) ;
}
static int efx_ethtool_set_wol ( struct net_device * net_dev ,
struct ethtool_wolinfo * wol )
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2009-11-29 03:43:07 +00:00
return efx - > type - > set_wol ( efx , wol - > wolopts ) ;
}
2021-04-15 15:53:17 -07:00
static void efx_ethtool_get_fec_stats ( struct net_device * net_dev ,
struct ethtool_fec_stats * fec_stats )
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2021-04-15 15:53:17 -07:00
if ( efx - > type - > get_fec_stats )
efx - > type - > get_fec_stats ( efx , fec_stats ) ;
}
2013-07-03 14:07:40 +08:00
static int efx_ethtool_get_ts_info ( struct net_device * net_dev ,
struct ethtool_ts_info * ts_info )
2013-04-08 17:34:58 +01:00
{
2022-06-28 14:59:45 +01:00
struct efx_nic * efx = efx_netdev_priv ( net_dev ) ;
2013-04-08 17:34:58 +01:00
/* Software capabilities */
ts_info - > so_timestamping = ( SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE ) ;
ts_info - > phc_index = - 1 ;
efx_ptp_get_ts_info ( efx , ts_info ) ;
return 0 ;
}
2009-09-02 01:03:33 -07:00
const struct ethtool_ops efx_ethtool_ops = {
2020-03-16 13:47:04 -07:00
. supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_USECS_IRQ |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX ,
2008-04-27 12:55:59 +01:00
. get_drvinfo = efx_ethtool_get_drvinfo ,
2010-06-21 03:06:53 +00:00
. get_regs_len = efx_ethtool_get_regs_len ,
. get_regs = efx_ethtool_get_regs ,
2010-06-23 11:30:07 +00:00
. get_msglevel = efx_ethtool_get_msglevel ,
. set_msglevel = efx_ethtool_set_msglevel ,
2010-12-09 12:10:25 +00:00
. get_link = ethtool_op_get_link ,
2008-04-27 12:55:59 +01:00
. get_coalesce = efx_ethtool_get_coalesce ,
. set_coalesce = efx_ethtool_set_coalesce ,
2010-09-10 06:42:33 +00:00
. get_ringparam = efx_ethtool_get_ringparam ,
. set_ringparam = efx_ethtool_set_ringparam ,
2008-04-27 12:55:59 +01:00
. get_pauseparam = efx_ethtool_get_pauseparam ,
. set_pauseparam = efx_ethtool_set_pauseparam ,
2008-09-01 12:48:12 +01:00
. get_sset_count = efx_ethtool_get_sset_count ,
2008-05-07 13:36:19 +01:00
. self_test = efx_ethtool_self_test ,
2008-04-27 12:55:59 +01:00
. get_strings = efx_ethtool_get_strings ,
2011-04-02 00:43:46 +01:00
. set_phys_id = efx_ethtool_phys_id ,
2008-04-27 12:55:59 +01:00
. get_ethtool_stats = efx_ethtool_get_stats ,
2009-11-29 03:43:07 +00:00
. get_wol = efx_ethtool_get_wol ,
. set_wol = efx_ethtool_set_wol ,
2009-11-29 03:43:15 +00:00
. reset = efx_ethtool_reset ,
2010-06-30 05:06:28 +00:00
. get_rxnfc = efx_ethtool_get_rxnfc ,
2012-01-03 12:05:47 +00:00
. set_rxnfc = efx_ethtool_set_rxnfc ,
2011-12-15 13:55:01 +00:00
. get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size ,
2017-01-17 12:01:53 +00:00
. get_rxfh_key_size = efx_ethtool_get_rxfh_key_size ,
2014-05-15 01:25:27 +01:00
. get_rxfh = efx_ethtool_get_rxfh ,
. set_rxfh = efx_ethtool_set_rxfh ,
2018-03-08 15:45:17 +00:00
. get_rxfh_context = efx_ethtool_get_rxfh_context ,
. set_rxfh_context = efx_ethtool_set_rxfh_context ,
2013-04-08 17:34:58 +01:00
. get_ts_info = efx_ethtool_get_ts_info ,
2012-05-01 18:50:43 +01:00
. get_module_info = efx_ethtool_get_module_info ,
. get_module_eeprom = efx_ethtool_get_module_eeprom ,
2016-12-15 00:12:53 +01:00
. get_link_ksettings = efx_ethtool_get_link_ksettings ,
. set_link_ksettings = efx_ethtool_set_link_ksettings ,
2021-04-15 15:53:17 -07:00
. get_fec_stats = efx_ethtool_get_fec_stats ,
2018-03-14 14:21:26 +00:00
. get_fecparam = efx_ethtool_get_fecparam ,
. set_fecparam = efx_ethtool_set_fecparam ,
2008-04-27 12:55:59 +01:00
} ;