Commit 14e9e262 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'sfc-ethtool-for-EF100-and-related-improvements'

Edward Cree says:

====================
sfc: ethtool for EF100 and related improvements

This series adds the ethtool support to the EF100 driver that was held
 back from the original submission as the lack of phy_ops caused issues.
Patch #2, removing the phy_op indirection, deals with this.  There are a
 lot of checkpatch warnings / xmastree violations but they're all in
 pure code movement so I've left the code as it is.
While patch #1 is technically a fix and possibly could go to 'net', I've
 put it in this series since it only becomes triggerable with the added
 'ethtool --reset' support.
====================
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 30ebaf8e 08bdbcae
......@@ -17,8 +17,49 @@
#include "ef100_ethtool.h"
#include "mcdi_functions.h"
/* This is the maximum number of descriptor rings supported by the QDMA */
#define EFX_EF100_MAX_DMAQ_SIZE 16384UL
static void ef100_ethtool_get_ringparam(struct net_device *net_dev,
struct ethtool_ringparam *ring)
{
struct efx_nic *efx = netdev_priv(net_dev);
ring->rx_max_pending = EFX_EF100_MAX_DMAQ_SIZE;
ring->tx_max_pending = EFX_EF100_MAX_DMAQ_SIZE;
ring->rx_pending = efx->rxq_entries;
ring->tx_pending = efx->txq_entries;
}
/* Ethtool options available
*/
const struct ethtool_ops ef100_ethtool_ops = {
.get_drvinfo = efx_ethtool_get_drvinfo,
.get_msglevel = efx_ethtool_get_msglevel,
.set_msglevel = efx_ethtool_set_msglevel,
.get_pauseparam = efx_ethtool_get_pauseparam,
.set_pauseparam = efx_ethtool_set_pauseparam,
.get_sset_count = efx_ethtool_get_sset_count,
.self_test = efx_ethtool_self_test,
.get_strings = efx_ethtool_get_strings,
.get_link_ksettings = efx_ethtool_get_link_ksettings,
.set_link_ksettings = efx_ethtool_set_link_ksettings,
.get_link = ethtool_op_get_link,
.get_ringparam = ef100_ethtool_get_ringparam,
.get_fecparam = efx_ethtool_get_fecparam,
.set_fecparam = efx_ethtool_set_fecparam,
.get_ethtool_stats = efx_ethtool_get_stats,
.get_rxnfc = efx_ethtool_get_rxnfc,
.set_rxnfc = efx_ethtool_set_rxnfc,
.reset = efx_ethtool_reset,
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_key_size = efx_ethtool_get_rxfh_key_size,
.get_rxfh = efx_ethtool_get_rxfh,
.set_rxfh = efx_ethtool_set_rxfh,
.get_rxfh_context = efx_ethtool_get_rxfh_context,
.set_rxfh_context = efx_ethtool_set_rxfh_context,
.get_module_info = efx_ethtool_get_module_info,
.get_module_eeprom = efx_ethtool_get_module_eeprom,
};
......@@ -217,9 +217,13 @@ static const struct net_device_ops ef100_netdev_ops = {
.ndo_open = ef100_net_open,
.ndo_stop = ef100_net_stop,
.ndo_start_xmit = ef100_hard_start_xmit,
.ndo_tx_timeout = efx_watchdog,
.ndo_get_stats64 = efx_net_stats,
.ndo_change_mtu = efx_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = efx_set_mac_address,
.ndo_set_rx_mode = efx_set_rx_mode, /* Lookout */
.ndo_set_features = efx_set_features,
.ndo_get_phys_port_id = efx_get_phys_port_id,
.ndo_get_phys_port_name = efx_get_phys_port_name,
#ifdef CONFIG_RFS_ACCEL
......
......@@ -428,24 +428,12 @@ static int ef100_reset(struct efx_nic *efx, enum reset_type reset_type)
__clear_bit(reset_type, &efx->reset_pending);
rc = dev_open(efx->net_dev, NULL);
} else if (reset_type == RESET_TYPE_ALL) {
/* A RESET_TYPE_ALL will cause filters to be removed, so we remove filters
* and reprobe after reset to avoid removing filters twice
*/
down_write(&efx->filter_sem);
ef100_filter_table_down(efx);
up_write(&efx->filter_sem);
rc = efx_mcdi_reset(efx, reset_type);
if (rc)
return rc;
netif_device_attach(efx->net_dev);
down_write(&efx->filter_sem);
rc = ef100_filter_table_up(efx);
up_write(&efx->filter_sem);
if (rc)
return rc;
rc = dev_open(efx->net_dev, NULL);
} else {
rc = 1; /* Leave the device closed */
......@@ -696,7 +684,7 @@ static unsigned int ef100_check_caps(const struct efx_nic *efx,
/* NIC level access functions
*/
#define EF100_OFFLOAD_FEATURES (NETIF_F_HW_CSUM | NETIF_F_RXCSUM | \
NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | \
NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_NTUPLE | \
NETIF_F_RXHASH | NETIF_F_RXFCS | NETIF_F_TSO_ECN | NETIF_F_RXALL | \
NETIF_F_TSO_MANGLEID | NETIF_F_HW_VLAN_CTAG_TX)
......@@ -769,6 +757,7 @@ const struct efx_nic_type ef100_pf_nic_type = {
.rx_restore_rss_contexts = efx_mcdi_rx_restore_rss_contexts,
.reconfigure_mac = ef100_reconfigure_mac,
.reconfigure_port = efx_mcdi_port_reconfigure,
.test_nvram = efx_new_mcdi_nvram_test_all,
.describe_stats = ef100_describe_stats,
.start_stats = efx_mcdi_mac_start_stats,
......@@ -1170,6 +1159,10 @@ static int ef100_probe_main(struct efx_nic *efx)
goto fail;
/* Reset (most) configuration for this function */
rc = efx_mcdi_reset(efx, RESET_TYPE_ALL);
if (rc)
goto fail;
/* Enable event logging */
rc = efx_mcdi_log_ctrl(efx, true, false, 0);
if (rc)
goto fail;
......
......@@ -33,7 +33,7 @@
#include "selftest.h"
#include "sriov.h"
#include "mcdi.h"
#include "mcdi_port_common.h"
#include "mcdi_pcol.h"
#include "workarounds.h"
......@@ -149,23 +149,17 @@ static int efx_init_port(struct efx_nic *efx)
mutex_lock(&efx->mac_lock);
rc = efx->phy_op->init(efx);
if (rc)
goto fail1;
efx->port_initialized = true;
/* Ensure the PHY advertises the correct flow control settings */
rc = efx->phy_op->reconfigure(efx);
rc = efx_mcdi_port_reconfigure(efx);
if (rc && rc != -EPERM)
goto fail2;
goto fail;
mutex_unlock(&efx->mac_lock);
return 0;
fail2:
efx->phy_op->fini(efx);
fail1:
fail:
mutex_unlock(&efx->mac_lock);
return rc;
}
......@@ -177,7 +171,6 @@ static void efx_fini_port(struct efx_nic *efx)
if (!efx->port_initialized)
return;
efx->phy_op->fini(efx);
efx->port_initialized = false;
efx->link_state.up = false;
......@@ -1229,7 +1222,7 @@ static int efx_pm_thaw(struct device *dev)
goto fail;
mutex_lock(&efx->mac_lock);
efx->phy_op->reconfigure(efx);
efx_mcdi_port_reconfigure(efx);
mutex_unlock(&efx->mac_lock);
efx_start_all(efx);
......@@ -1336,7 +1329,7 @@ static int __init efx_init_module(void)
{
int rc;
printk(KERN_INFO "Solarflare NET driver v" EFX_DRIVER_VERSION "\n");
printk(KERN_INFO "Solarflare NET driver\n");
rc = register_netdevice_notifier(&efx_netdev_notifier);
if (rc)
......@@ -1398,4 +1391,3 @@ MODULE_AUTHOR("Solarflare Communications and "
MODULE_DESCRIPTION("Solarflare network driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, efx_pci_table);
MODULE_VERSION(EFX_DRIVER_VERSION);
......@@ -19,6 +19,7 @@
#include "rx_common.h"
#include "tx_common.h"
#include "nic.h"
#include "mcdi_port_common.h"
#include "io.h"
#include "mcdi_pcol.h"
......@@ -544,7 +545,7 @@ void efx_start_all(struct efx_nic *efx)
* to poll now because we could have missed a change
*/
mutex_lock(&efx->mac_lock);
if (efx->phy_op->poll(efx))
if (efx_mcdi_phy_poll(efx))
efx_link_status_changed(efx);
mutex_unlock(&efx->mac_lock);
......@@ -714,9 +715,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
mutex_lock(&efx->mac_lock);
down_write(&efx->filter_sem);
mutex_lock(&efx->rss_lock);
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
method != RESET_TYPE_DATAPATH)
efx->phy_op->fini(efx);
efx->type->fini(efx);
}
......@@ -759,10 +757,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
method != RESET_TYPE_DATAPATH) {
rc = efx->phy_op->init(efx);
if (rc)
goto fail;
rc = efx->phy_op->reconfigure(efx);
rc = efx_mcdi_port_reconfigure(efx);
if (rc && rc != -EPERM)
netif_err(efx, drv, efx->net_dev,
"could not restore PHY settings\n");
......@@ -959,7 +954,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
/**************************************************************************
*
* Dummy PHY/MAC operations
* Dummy NIC operations
*
* Can be used for some unimplemented operations
* Needed so all function pointers are valid and do not have to be tested
......@@ -972,18 +967,6 @@ int efx_port_dummy_op_int(struct efx_nic *efx)
}
void efx_port_dummy_op_void(struct efx_nic *efx) {}
static bool efx_port_dummy_op_poll(struct efx_nic *efx)
{
return false;
}
static const struct efx_phy_operations efx_dummy_phy_operations = {
.init = efx_port_dummy_op_int,
.reconfigure = efx_port_dummy_op_int,
.poll = efx_port_dummy_op_poll,
.fini = efx_port_dummy_op_void,
};
/**************************************************************************
*
* Data housekeeping
......@@ -1037,7 +1020,6 @@ int efx_init_struct(struct efx_nic *efx,
efx->rps_hash_table = kcalloc(EFX_ARFS_HASH_TABLE_SIZE,
sizeof(*efx->rps_hash_table), GFP_KERNEL);
#endif
efx->phy_op = &efx_dummy_phy_operations;
efx->mdio.dev = net_dev;
INIT_WORK(&efx->mac_work, efx_mac_work);
init_waitqueue_head(&efx->flush_wq);
......@@ -1104,17 +1086,7 @@ int efx_init_io(struct efx_nic *efx, int bar, dma_addr_t dma_mask,
pci_set_master(pci_dev);
/* Set the PCI DMA mask. Try all possibilities from our
* genuine mask down to 32 bits, because some architectures
* (e.g. x86_64 with iommu_sac_force set) will allow 40 bit
* masks event though they reject 46 bit masks.
*/
while (dma_mask > 0x7fffffffUL) {
rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask);
if (rc == 0)
break;
dma_mask >>= 1;
}
if (rc) {
netif_err(efx, probe, efx->net_dev,
"could not find a suitable DMA mask\n");
......
......@@ -15,6 +15,7 @@
#include "selftest.h"
#include "rx_common.h"
#include "ethtool_common.h"
#include "mcdi_port_common.h"
struct efx_sw_stat_desc {
const char *name;
......@@ -105,7 +106,6 @@ void efx_ethtool_get_drvinfo(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
efx_mcdi_print_fwver(efx, info->fw_version,
sizeof(info->fw_version));
strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
......@@ -221,7 +221,7 @@ int efx_ethtool_set_pauseparam(struct net_device *net_dev,
efx_link_set_wanted_fc(efx, wanted_fc);
if (efx->link_advertising[0] != old_adv ||
(efx->wanted_fc ^ old_fc) & EFX_FC_AUTO) {
rc = efx->phy_op->reconfigure(efx);
rc = efx_mcdi_port_reconfigure(efx);
if (rc) {
netif_err(efx, drv, efx->net_dev,
"Unable to advertise requested flow "
......@@ -372,20 +372,15 @@ int efx_ethtool_fill_self_tests(struct efx_nic *efx,
efx_fill_test(n++, strings, data, &tests->registers,
"core", 0, "registers", NULL);
if (efx->phy_op->run_tests != NULL) {
EFX_WARN_ON_PARANOID(efx->phy_op->test_name == NULL);
for (i = 0; true; ++i) {
const char *name;
EFX_WARN_ON_PARANOID(i >= EFX_MAX_PHY_TESTS);
name = efx->phy_op->test_name(efx, i);
name = efx_mcdi_phy_test_name(efx, i);
if (name == NULL)
break;
efx_fill_test(n++, strings, data, &tests->phy_ext[i],
"phy", 0, name, NULL);
}
efx_fill_test(n++, strings, data, &tests->phy_ext[i], "phy", 0, name, NULL);
}
/* Loopback tests */
......@@ -571,7 +566,7 @@ int efx_ethtool_get_link_ksettings(struct net_device *net_dev,
u32 supported;
mutex_lock(&efx->mac_lock);
efx->phy_op->get_link_ksettings(efx, cmd);
efx_mcdi_phy_get_link_ksettings(efx, cmd);
mutex_unlock(&efx->mac_lock);
/* Both MACs support pause frames (bidirectional and respond-only) */
......@@ -607,7 +602,7 @@ int efx_ethtool_set_link_ksettings(struct net_device *net_dev,
}
mutex_lock(&efx->mac_lock);
rc = efx->phy_op->set_link_ksettings(efx, cmd);
rc = efx_mcdi_phy_set_link_ksettings(efx, cmd);
mutex_unlock(&efx->mac_lock);
return rc;
}
......@@ -618,10 +613,8 @@ int efx_ethtool_get_fecparam(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
int rc;
if (!efx->phy_op || !efx->phy_op->get_fecparam)
return -EOPNOTSUPP;
mutex_lock(&efx->mac_lock);
rc = efx->phy_op->get_fecparam(efx, fecparam);
rc = efx_mcdi_phy_get_fecparam(efx, fecparam);
mutex_unlock(&efx->mac_lock);
return rc;
......@@ -633,10 +626,8 @@ int efx_ethtool_set_fecparam(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
int rc;
if (!efx->phy_op || !efx->phy_op->get_fecparam)
return -EOPNOTSUPP;
mutex_lock(&efx->mac_lock);
rc = efx->phy_op->set_fecparam(efx, fecparam);
rc = efx_mcdi_phy_set_fecparam(efx, fecparam);
mutex_unlock(&efx->mac_lock);
return rc;
......@@ -1332,11 +1323,8 @@ int efx_ethtool_get_module_eeprom(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
int ret;
if (!efx->phy_op || !efx->phy_op->get_module_eeprom)
return -EOPNOTSUPP;
mutex_lock(&efx->mac_lock);
ret = efx->phy_op->get_module_eeprom(efx, ee, data);
ret = efx_mcdi_phy_get_module_eeprom(efx, ee, data);
mutex_unlock(&efx->mac_lock);
return ret;
......@@ -1348,11 +1336,8 @@ int efx_ethtool_get_module_info(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
int ret;
if (!efx->phy_op || !efx->phy_op->get_module_info)
return -EOPNOTSUPP;
mutex_lock(&efx->mac_lock);
ret = efx->phy_op->get_module_info(efx, modinfo);
ret = efx_mcdi_phy_get_module_info(efx, modinfo);
mutex_unlock(&efx->mac_lock);
return ret;
......
......@@ -355,7 +355,6 @@ int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
int efx_mcdi_flush_rxqs(struct efx_nic *efx);
int efx_mcdi_port_reconfigure(struct efx_nic *efx);
void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
void efx_mcdi_mac_start_stats(struct efx_nic *efx);
void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
......
This diff is collapsed.
This diff is collapsed.
......@@ -41,13 +41,22 @@ u8 mcdi_to_ethtool_media(u32 media);
void efx_mcdi_phy_decode_link(struct efx_nic *efx,
struct efx_link_state *link_state,
u32 speed, u32 flags, u32 fcntl);
u32 ethtool_fec_caps_to_mcdi(u32 ethtool_cap);
u32 ethtool_fec_caps_to_mcdi(u32 supported_cap, u32 ethtool_cap);
u32 mcdi_fec_caps_to_ethtool(u32 caps, bool is_25g);
void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa);
bool efx_mcdi_phy_poll(struct efx_nic *efx);
int efx_mcdi_phy_get_fecparam(struct efx_nic *efx,
struct ethtool_fecparam *fec);
int efx_mcdi_phy_probe(struct efx_nic *efx);
void efx_mcdi_phy_remove(struct efx_nic *efx);
void efx_mcdi_phy_get_link_ksettings(struct efx_nic *efx, struct ethtool_link_ksettings *cmd);
int efx_mcdi_phy_set_link_ksettings(struct efx_nic *efx, const struct ethtool_link_ksettings *cmd);
int efx_mcdi_phy_get_fecparam(struct efx_nic *efx, struct ethtool_fecparam *fec);
int efx_mcdi_phy_set_fecparam(struct efx_nic *efx, const struct ethtool_fecparam *fec);
int efx_mcdi_phy_test_alive(struct efx_nic *efx);
int efx_mcdi_port_reconfigure(struct efx_nic *efx);
int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, unsigned flags);
const char *efx_mcdi_phy_test_name(struct efx_nic *efx, unsigned int index);
int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx, struct ethtool_eeprom *ee, u8 *data);
int efx_mcdi_phy_get_module_info(struct efx_nic *efx, struct ethtool_modinfo *modinfo);
int efx_mcdi_set_mac(struct efx_nic *efx);
int efx_mcdi_set_mtu(struct efx_nic *efx);
int efx_mcdi_mac_init_stats(struct efx_nic *efx);
......
......@@ -38,8 +38,6 @@
*
**************************************************************************/
#define EFX_DRIVER_VERSION "4.1"
#ifdef DEBUG
#define EFX_WARN_ON_ONCE_PARANOID(x) WARN_ON_ONCE(x)
#define EFX_WARN_ON_PARANOID(x) WARN_ON(x)
......@@ -657,51 +655,6 @@ static inline bool efx_link_state_equal(const struct efx_link_state *left,
left->fc == right->fc && left->speed == right->speed;
}
/**
* struct efx_phy_operations - Efx PHY operations table
* @probe: Probe PHY and initialise efx->mdio.mode_support, efx->mdio.mmds,
* efx->loopback_modes.
* @init: Initialise PHY
* @fini: Shut down PHY
* @reconfigure: Reconfigure PHY (e.g. for new link parameters)
* @poll: Update @link_state and report whether it changed.
* Serialised by the mac_lock.
* @get_link_ksettings: Get ethtool settings. Serialised by the mac_lock.
* @set_link_ksettings: Set ethtool settings. Serialised by the mac_lock.
* @get_fecparam: Get Forward Error Correction settings. Serialised by mac_lock.
* @set_fecparam: Set Forward Error Correction settings. Serialised by mac_lock.
* @set_npage_adv: Set abilities advertised in (Extended) Next Page
* (only needed where AN bit is set in mmds)
* @test_alive: Test that PHY is 'alive' (online)
* @test_name: Get the name of a PHY-specific test/result
* @run_tests: Run tests and record results as appropriate (offline).
* Flags are the ethtool tests flags.
*/
struct efx_phy_operations {
int (*probe) (struct efx_nic *efx);
int (*init) (struct efx_nic *efx);
void (*fini) (struct efx_nic *efx);
void (*remove) (struct efx_nic *efx);
int (*reconfigure) (struct efx_nic *efx);
bool (*poll) (struct efx_nic *efx);
void (*get_link_ksettings)(struct efx_nic *efx,
struct ethtool_link_ksettings *cmd);
int (*set_link_ksettings)(struct efx_nic *efx,
const struct ethtool_link_ksettings *cmd);
int (*get_fecparam)(struct efx_nic *efx, struct ethtool_fecparam *fec);
int (*set_fecparam)(struct efx_nic *efx,
const struct ethtool_fecparam *fec);
void (*set_npage_adv) (struct efx_nic *efx, u32);
int (*test_alive) (struct efx_nic *efx);
const char *(*test_name) (struct efx_nic *efx, unsigned int index);
int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
int (*get_module_eeprom) (struct efx_nic *efx,
struct ethtool_eeprom *ee,
u8 *data);
int (*get_module_info) (struct efx_nic *efx,
struct ethtool_modinfo *modinfo);
};
/**
* enum efx_phy_mode - PHY operating mode flags
* @PHY_MODE_NORMAL: on and should pass traffic
......@@ -920,7 +873,6 @@ struct efx_async_filter_insertion {
* field of %MC_CMD_GET_CAPABILITIES_V4 response, or %MC_CMD_MAC_NSTATS)
* @stats_buffer: DMA buffer for statistics
* @phy_type: PHY type
* @phy_op: PHY interface
* @phy_data: PHY private data (including PHY-specific stats)
* @mdio: PHY MDIO interface
* @mdio_bus: PHY MDIO bus ID (only used by Siena)
......@@ -1094,7 +1046,6 @@ struct efx_nic {
bool rx_nodesc_drops_prev_state;
unsigned int phy_type;
const struct efx_phy_operations *phy_op;
void *phy_data;
struct mdio_if_info mdio;
unsigned int mdio_bus;
......
......@@ -21,6 +21,7 @@
#include "efx_common.h"
#include "efx_channels.h"
#include "nic.h"
#include "mcdi_port_common.h"
#include "selftest.h"
#include "workarounds.h"
......@@ -99,10 +100,8 @@ static int efx_test_phy_alive(struct efx_nic *efx, struct efx_self_tests *tests)
{
int rc = 0;
if (efx->phy_op->test_alive) {
rc = efx->phy_op->test_alive(efx);
rc = efx_mcdi_phy_test_alive(efx);
tests->phy_alive = rc ? -1 : 1;
}
return rc;
}
......@@ -257,11 +256,8 @@ static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
{
int rc;
if (!efx->phy_op->run_tests)
return 0;
mutex_lock(&efx->mac_lock);
rc = efx->phy_op->run_tests(efx, tests->phy_ext, flags);
rc = efx_mcdi_phy_run_tests(efx, tests->phy_ext, flags);
mutex_unlock(&efx->mac_lock);
if (rc == -EPERM)
rc = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment