From 18e83e4cd144e30fb38bf1f714914182c6c8bced Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Jan 2012 19:05:20 +0000 Subject: sfc: Const-qualify static data as appropriate, partly prompted by checkpatch Fix the following warnings: WARNING: struct dev_pm_ops should normally be const WARNING: static const char * array should probably be static const char * const Similarly const-qualify struct i2c_board_info, struct i2c_algo_bit_data, struct efx_ethtool_stat, struct efx_mtd_ops and struct siena_nvram_type_info. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/falcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/ethernet/sfc/falcon.c') diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 8ae1ebd35397..5c7548959dd7 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -89,7 +89,7 @@ static int falcon_getscl(void *data) return EFX_OWORD_FIELD(reg, FRF_AB_GPIO0_IN); } -static struct i2c_algo_bit_data falcon_i2c_bit_operations = { +static const struct i2c_algo_bit_data falcon_i2c_bit_operations = { .setsda = falcon_setsda, .setscl = falcon_setscl, .getsda = falcon_getsda, -- cgit v1.2.3 From 710b208dc2687fdb3370110d54a67fb2288835eb Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 3 Sep 2011 00:15:00 +0100 Subject: sfc: Merge efx_mac_operations into efx_nic_type No NICs need to switch efx_mac_operations at run-time, and the MAC operations are fairly closely bound to NIC types. Move efx_mac_operations::reconfigure to efx_nic_type::reconfigure_mac and efx_mac_operations::check_fault fo efx_nic_type::check_mac_fault. Change callers to call through efx->type or directly if the NIC type is known. Remove efx_mac_operations::update_stats. The implementations for Falcon used to fetch MAC statistics synchronously and this was used by efx_register_netdev() to clear statistics after running self-tests. However, it now only converts statistics that have already been fetched (and that only for Falcon), and the call from efx_register_netdev() has no effect. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 17 ++++++----------- drivers/net/ethernet/sfc/ethtool.c | 4 ++-- drivers/net/ethernet/sfc/falcon.c | 15 ++++++++------- drivers/net/ethernet/sfc/falcon_xmac.c | 13 +++---------- drivers/net/ethernet/sfc/mac.h | 21 --------------------- drivers/net/ethernet/sfc/mcdi.h | 4 ++++ drivers/net/ethernet/sfc/mcdi_mac.c | 12 ++---------- drivers/net/ethernet/sfc/net_driver.h | 21 ++++----------------- drivers/net/ethernet/sfc/nic.h | 3 +++ drivers/net/ethernet/sfc/selftest.c | 2 +- drivers/net/ethernet/sfc/siena.c | 4 ++-- 11 files changed, 35 insertions(+), 81 deletions(-) delete mode 100644 drivers/net/ethernet/sfc/mac.h (limited to 'drivers/net/ethernet/sfc/falcon.c') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 8f4cbb642bf2..1d20e01c6aea 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -900,7 +900,7 @@ static void efx_mac_work(struct work_struct *data) mutex_lock(&efx->mac_lock); if (efx->port_enabled) { efx->type->push_multicast_hash(efx); - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); } mutex_unlock(&efx->mac_lock); } @@ -941,7 +941,7 @@ static int efx_init_port(struct efx_nic *efx) /* Reconfigure the MAC before creating dma queues (required for * Falcon/A1 where RX_INGR_EN/TX_DRAIN_EN isn't supported) */ - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); /* Ensure the PHY advertises the correct flow control settings */ rc = efx->phy_op->reconfigure(efx); @@ -969,7 +969,7 @@ static void efx_start_port(struct efx_nic *efx) /* efx_mac_work() might have been scheduled after efx_stop_port(), * and then cancelled by efx_flush_all() */ efx->type->push_multicast_hash(efx); - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); } @@ -1807,7 +1807,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) /* Reconfigure the MAC before enabling the dma queues so that * the RX buffers don't overflow */ net_dev->mtu = new_mtu; - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); efx_init_channels(efx); @@ -1835,7 +1835,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) /* Reconfigure the MAC */ mutex_lock(&efx->mac_lock); - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); return 0; @@ -1949,10 +1949,6 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->netdev_ops = &efx_netdev_ops; SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); - /* Clear MAC statistics */ - efx->mac_op->update_stats(efx); - memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); - rtnl_lock(); rc = dev_alloc_name(net_dev, net_dev->name); @@ -2069,7 +2065,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) "could not restore PHY settings\n"); } - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); efx_init_channels(efx); efx_restore_filters(efx); @@ -2274,7 +2270,6 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type, efx->net_dev = net_dev; spin_lock_init(&efx->stats_lock); mutex_init(&efx->mac_lock); - efx->mac_op = type->default_mac_ops; efx->phy_op = &efx_dummy_phy_operations; efx->mdio.dev = net_dev; INIT_WORK(&efx->mac_work, efx_mac_work); diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 55a25b14d304..1a7f7ba27bea 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -750,7 +750,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, /* Recover by resetting the EM block */ falcon_stop_nic_stats(efx); falcon_drain_tx_fifo(efx); - efx->mac_op->reconfigure(efx); + falcon_reconfigure_xmac(efx); falcon_start_nic_stats(efx); } else { /* Schedule a reset to recover */ @@ -775,7 +775,7 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev, /* Reconfigure the MAC. The PHY *may* generate a link state change event * if the user just changed the advertised capabilities, but there's no * harm doing this twice */ - efx->mac_op->reconfigure(efx); + efx->type->reconfigure_mac(efx); out: mutex_unlock(&efx->mac_lock); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 5c7548959dd7..1a8a316bb538 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -19,7 +19,6 @@ #include "net_driver.h" #include "bitfield.h" #include "efx.h" -#include "mac.h" #include "spi.h" #include "nic.h" #include "regs.h" @@ -613,7 +612,7 @@ static void falcon_stats_complete(struct efx_nic *efx) nic_data->stats_pending = false; if (*nic_data->stats_dma_done == FALCON_STATS_DONE) { rmb(); /* read the done flag before the stats */ - efx->mac_op->update_stats(efx); + falcon_update_stats_xmac(efx); } else { netif_err(efx, hw, efx->net_dev, "timed out waiting for statistics\n"); @@ -670,7 +669,7 @@ static int falcon_reconfigure_port(struct efx_nic *efx) falcon_reset_macs(efx); efx->phy_op->reconfigure(efx); - rc = efx->mac_op->reconfigure(efx); + rc = falcon_reconfigure_xmac(efx); BUG_ON(rc); falcon_start_nic_stats(efx); @@ -1218,7 +1217,7 @@ static void falcon_monitor(struct efx_nic *efx) falcon_deconfigure_mac_wrapper(efx); falcon_reset_macs(efx); - rc = efx->mac_op->reconfigure(efx); + rc = falcon_reconfigure_xmac(efx); BUG_ON(rc); falcon_start_nic_stats(efx); @@ -1676,7 +1675,7 @@ static void falcon_update_nic_stats(struct efx_nic *efx) *nic_data->stats_dma_done == FALCON_STATS_DONE) { nic_data->stats_pending = false; rmb(); /* read the done flag before the stats */ - efx->mac_op->update_stats(efx); + falcon_update_stats_xmac(efx); } } @@ -1769,11 +1768,12 @@ const struct efx_nic_type falcon_a1_nic_type = { .push_irq_moderation = falcon_push_irq_moderation, .push_multicast_hash = falcon_push_multicast_hash, .reconfigure_port = falcon_reconfigure_port, + .reconfigure_mac = falcon_reconfigure_xmac, + .check_mac_fault = falcon_xmac_check_fault, .get_wol = falcon_get_wol, .set_wol = falcon_set_wol, .resume_wol = efx_port_dummy_op_void, .test_nvram = falcon_test_nvram, - .default_mac_ops = &falcon_xmac_operations, .revision = EFX_REV_FALCON_A1, .mem_map_size = 0x20000, @@ -1811,12 +1811,13 @@ const struct efx_nic_type falcon_b0_nic_type = { .push_irq_moderation = falcon_push_irq_moderation, .push_multicast_hash = falcon_push_multicast_hash, .reconfigure_port = falcon_reconfigure_port, + .reconfigure_mac = falcon_reconfigure_xmac, + .check_mac_fault = falcon_xmac_check_fault, .get_wol = falcon_get_wol, .set_wol = falcon_set_wol, .resume_wol = efx_port_dummy_op_void, .test_registers = falcon_b0_test_registers, .test_nvram = falcon_test_nvram, - .default_mac_ops = &falcon_xmac_operations, .revision = EFX_REV_FALCON_B0, /* Map everything up to and including the RSS indirection diff --git a/drivers/net/ethernet/sfc/falcon_xmac.c b/drivers/net/ethernet/sfc/falcon_xmac.c index 57434593f07b..6106ef15dee3 100644 --- a/drivers/net/ethernet/sfc/falcon_xmac.c +++ b/drivers/net/ethernet/sfc/falcon_xmac.c @@ -14,7 +14,6 @@ #include "nic.h" #include "regs.h" #include "io.h" -#include "mac.h" #include "mdio_10g.h" #include "workarounds.h" @@ -270,12 +269,12 @@ static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries) return mac_up; } -static bool falcon_xmac_check_fault(struct efx_nic *efx) +bool falcon_xmac_check_fault(struct efx_nic *efx) { return !falcon_xmac_link_ok_retry(efx, 5); } -static int falcon_reconfigure_xmac(struct efx_nic *efx) +int falcon_reconfigure_xmac(struct efx_nic *efx) { struct falcon_nic_data *nic_data = efx->nic_data; @@ -290,7 +289,7 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx) return 0; } -static void falcon_update_stats_xmac(struct efx_nic *efx) +void falcon_update_stats_xmac(struct efx_nic *efx) { struct efx_mac_stats *mac_stats = &efx->mac_stats; @@ -361,9 +360,3 @@ void falcon_poll_xmac(struct efx_nic *efx) nic_data->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); falcon_ack_status_intr(efx); } - -const struct efx_mac_operations falcon_xmac_operations = { - .reconfigure = falcon_reconfigure_xmac, - .update_stats = falcon_update_stats_xmac, - .check_fault = falcon_xmac_check_fault, -}; diff --git a/drivers/net/ethernet/sfc/mac.h b/drivers/net/ethernet/sfc/mac.h deleted file mode 100644 index d6a255d0856b..000000000000 --- a/drivers/net/ethernet/sfc/mac.h +++ /dev/null @@ -1,21 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2009 Solarflare Communications Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. - */ - -#ifndef EFX_MAC_H -#define EFX_MAC_H - -#include "net_driver.h" - -extern const struct efx_mac_operations falcon_xmac_operations; -extern const struct efx_mac_operations efx_mcdi_mac_operations; -extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, - u32 dma_len, int enable, int clear); - -#endif diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index aced2a7856fc..c59667bf64ac 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -126,5 +126,9 @@ extern int efx_mcdi_wol_filter_set_magic(struct efx_nic *efx, extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out); extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id); extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx); +extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, + u32 dma_len, int enable, int clear); +extern int efx_mcdi_mac_reconfigure(struct efx_nic *efx); +extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx); #endif /* EFX_MCDI_H */ diff --git a/drivers/net/ethernet/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c index 85fe24f86396..4907062b24a2 100644 --- a/drivers/net/ethernet/sfc/mcdi_mac.c +++ b/drivers/net/ethernet/sfc/mcdi_mac.c @@ -9,7 +9,6 @@ #include "net_driver.h" #include "efx.h" -#include "mac.h" #include "mcdi.h" #include "mcdi_pcol.h" @@ -115,7 +114,7 @@ fail: return rc; } -static int efx_mcdi_mac_reconfigure(struct efx_nic *efx) +int efx_mcdi_mac_reconfigure(struct efx_nic *efx) { int rc; @@ -130,16 +129,9 @@ static int efx_mcdi_mac_reconfigure(struct efx_nic *efx) } -static bool efx_mcdi_mac_check_fault(struct efx_nic *efx) +bool efx_mcdi_mac_check_fault(struct efx_nic *efx) { u32 faults; int rc = efx_mcdi_get_mac_faults(efx, &faults); return (rc != 0) || (faults != 0); } - - -const struct efx_mac_operations efx_mcdi_mac_operations = { - .reconfigure = efx_mcdi_mac_reconfigure, - .update_stats = efx_port_dummy_op_void, - .check_fault = efx_mcdi_mac_check_fault, -}; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index b6040141ef79..aa5a321a1419 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -473,18 +473,6 @@ static inline bool efx_link_state_equal(const struct efx_link_state *left, left->fc == right->fc && left->speed == right->speed; } -/** - * struct efx_mac_operations - Efx MAC operations table - * @reconfigure: Reconfigure MAC. Serialised by the mac_lock - * @update_stats: Update statistics - * @check_fault: Check fault state. True if fault present. - */ -struct efx_mac_operations { - int (*reconfigure) (struct efx_nic *efx); - void (*update_stats) (struct efx_nic *efx); - bool (*check_fault)(struct efx_nic *efx); -}; - /** * struct efx_phy_operations - Efx PHY operations table * @probe: Probe PHY and initialise efx->mdio.mode_support, efx->mdio.mmds, @@ -676,7 +664,6 @@ struct efx_filter_state; * @port_initialized: Port initialized? * @net_dev: Operating system network device. Consider holding the rtnl lock * @stats_buffer: DMA buffer for statistics - * @mac_op: MAC interface * @phy_type: PHY type * @phy_op: PHY interface * @phy_data: PHY private data (including PHY-specific stats) @@ -767,8 +754,6 @@ struct efx_nic { struct efx_buffer stats_buffer; - const struct efx_mac_operations *mac_op; - unsigned int phy_type; const struct efx_phy_operations *phy_op; void *phy_data; @@ -843,12 +828,13 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @push_irq_moderation: Apply interrupt moderation value * @push_multicast_hash: Apply multicast hash table * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY + * @reconfigure_mac: Reconfigure MAC only. Serialised by the mac_lock + * @check_mac_fault: Check MAC fault state. True if fault present. * @get_wol: Get WoL configuration from driver state * @set_wol: Push WoL configuration to the NIC * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume) * @test_registers: Test read/write functionality of control registers * @test_nvram: Test validity of NVRAM contents - * @default_mac_ops: efx_mac_operations to set at startup * @revision: Hardware architecture revision * @mem_map_size: Memory BAR mapped size * @txd_ptr_tbl_base: TX descriptor ring base address @@ -888,12 +874,13 @@ struct efx_nic_type { void (*push_irq_moderation)(struct efx_channel *channel); void (*push_multicast_hash)(struct efx_nic *efx); int (*reconfigure_port)(struct efx_nic *efx); + int (*reconfigure_mac)(struct efx_nic *efx); + bool (*check_mac_fault)(struct efx_nic *efx); void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol); int (*set_wol)(struct efx_nic *efx, u32 type); void (*resume_wol)(struct efx_nic *efx); int (*test_registers)(struct efx_nic *efx); int (*test_nvram)(struct efx_nic *efx); - const struct efx_mac_operations *default_mac_ops; int revision; unsigned int mem_map_size; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 5fb24d3aa3ca..cfda6ded24fe 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -189,6 +189,9 @@ extern bool efx_nic_event_present(struct efx_channel *channel); /* MAC/PHY */ extern void falcon_drain_tx_fifo(struct efx_nic *efx); extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx); +extern bool falcon_xmac_check_fault(struct efx_nic *efx); +extern int falcon_reconfigure_xmac(struct efx_nic *efx); +extern void falcon_update_stats_xmac(struct efx_nic *efx); /* Interrupts and test events */ extern int efx_nic_init_interrupt(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 5226d9857f30..9df2a7942509 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -569,7 +569,7 @@ static int efx_wait_for_link(struct efx_nic *efx) mutex_lock(&efx->mac_lock); link_up = link_state->up; if (link_up) - link_up = !efx->mac_op->check_fault(efx); + link_up = !efx->type->check_mac_fault(efx); mutex_unlock(&efx->mac_lock); if (link_up) { diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 4d5d619feaa6..775b6784cbdb 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -18,7 +18,6 @@ #include "bitfield.h" #include "efx.h" #include "nic.h" -#include "mac.h" #include "spi.h" #include "regs.h" #include "io.h" @@ -631,13 +630,14 @@ const struct efx_nic_type siena_a0_nic_type = { .set_id_led = efx_mcdi_set_id_led, .push_irq_moderation = siena_push_irq_moderation, .push_multicast_hash = siena_push_multicast_hash, + .reconfigure_mac = efx_mcdi_mac_reconfigure, + .check_mac_fault = efx_mcdi_mac_check_fault, .reconfigure_port = efx_mcdi_phy_reconfigure, .get_wol = siena_get_wol, .set_wol = siena_set_wol, .resume_wol = siena_init_wol, .test_registers = siena_test_registers, .test_nvram = efx_mcdi_nvram_test_all, - .default_mac_ops = &efx_mcdi_mac_operations, .revision = EFX_REV_SIENA_A0, .mem_map_size = (FR_CZ_MC_TREG_SMEM + -- cgit v1.2.3 From 30b81cda9516878906b44fed16aac9df1dbb89c7 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 13 Sep 2011 19:47:48 +0100 Subject: sfc: Remove efx_nic_type::push_multicast_hash operation Both implementations of efx_nic_type::reconfigure_mac operation push the multicast hash filter to the hardware. It is therefore redundant to call efx_nic_type::push_multicast_hash as well. efx_mcdi_mac_reconfigure() also uses this operation, but the implementation for Siena just uses MCDI anyway. Merge that into efx_mcdi_mac_reconfigure(). Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 5 +---- drivers/net/ethernet/sfc/falcon.c | 2 -- drivers/net/ethernet/sfc/mcdi_mac.c | 10 ++++++---- drivers/net/ethernet/sfc/net_driver.h | 5 ++--- drivers/net/ethernet/sfc/siena.c | 10 ---------- 5 files changed, 9 insertions(+), 23 deletions(-) (limited to 'drivers/net/ethernet/sfc/falcon.c') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 1d20e01c6aea..de162474c3c5 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -898,10 +898,8 @@ static void efx_mac_work(struct work_struct *data) struct efx_nic *efx = container_of(data, struct efx_nic, mac_work); mutex_lock(&efx->mac_lock); - if (efx->port_enabled) { - efx->type->push_multicast_hash(efx); + if (efx->port_enabled) efx->type->reconfigure_mac(efx); - } mutex_unlock(&efx->mac_lock); } @@ -968,7 +966,6 @@ static void efx_start_port(struct efx_nic *efx) /* efx_mac_work() might have been scheduled after efx_stop_port(), * and then cancelled by efx_flush_all() */ - efx->type->push_multicast_hash(efx); efx->type->reconfigure_mac(efx); mutex_unlock(&efx->mac_lock); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 1a8a316bb538..fe21c7e349b6 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -1766,7 +1766,6 @@ const struct efx_nic_type falcon_a1_nic_type = { .stop_stats = falcon_stop_nic_stats, .set_id_led = falcon_set_id_led, .push_irq_moderation = falcon_push_irq_moderation, - .push_multicast_hash = falcon_push_multicast_hash, .reconfigure_port = falcon_reconfigure_port, .reconfigure_mac = falcon_reconfigure_xmac, .check_mac_fault = falcon_xmac_check_fault, @@ -1809,7 +1808,6 @@ const struct efx_nic_type falcon_b0_nic_type = { .stop_stats = falcon_stop_nic_stats, .set_id_led = falcon_set_id_led, .push_irq_moderation = falcon_push_irq_moderation, - .push_multicast_hash = falcon_push_multicast_hash, .reconfigure_port = falcon_reconfigure_port, .reconfigure_mac = falcon_reconfigure_xmac, .check_mac_fault = falcon_xmac_check_fault, diff --git a/drivers/net/ethernet/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c index 559d79861faf..f67cf921bd1b 100644 --- a/drivers/net/ethernet/sfc/mcdi_mac.c +++ b/drivers/net/ethernet/sfc/mcdi_mac.c @@ -115,12 +115,14 @@ int efx_mcdi_mac_reconfigure(struct efx_nic *efx) { int rc; + WARN_ON(!mutex_is_locked(&efx->mac_lock)); + rc = efx_mcdi_set_mac(efx); if (rc != 0) return rc; - /* Restore the multicast hash registers. */ - efx->type->push_multicast_hash(efx); - - return 0; + return efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH, + efx->multicast_hash.byte, + sizeof(efx->multicast_hash), + NULL, 0, NULL); } diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index aa5a321a1419..a88e95f58b0a 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -826,9 +826,9 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @stop_stats: Stop the regular fetching of statistics * @set_id_led: Set state of identifying LED or revert to automatic function * @push_irq_moderation: Apply interrupt moderation value - * @push_multicast_hash: Apply multicast hash table * @reconfigure_port: Push loopback/power/txdis changes to the MAC and PHY - * @reconfigure_mac: Reconfigure MAC only. Serialised by the mac_lock + * @reconfigure_mac: Push MAC address, MTU, flow control and filter settings + * to the hardware. Serialised by the mac_lock. * @check_mac_fault: Check MAC fault state. True if fault present. * @get_wol: Get WoL configuration from driver state * @set_wol: Push WoL configuration to the NIC @@ -872,7 +872,6 @@ struct efx_nic_type { void (*stop_stats)(struct efx_nic *efx); void (*set_id_led)(struct efx_nic *efx, enum efx_led_mode mode); void (*push_irq_moderation)(struct efx_channel *channel); - void (*push_multicast_hash)(struct efx_nic *efx); int (*reconfigure_port)(struct efx_nic *efx); int (*reconfigure_mac)(struct efx_nic *efx); bool (*check_mac_fault)(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 775b6784cbdb..d681f2597e74 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -52,15 +52,6 @@ static void siena_push_irq_moderation(struct efx_channel *channel) channel->channel); } -static void siena_push_multicast_hash(struct efx_nic *efx) -{ - WARN_ON(!mutex_is_locked(&efx->mac_lock)); - - efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH, - efx->multicast_hash.byte, sizeof(efx->multicast_hash), - NULL, 0, NULL); -} - static int siena_mdio_write(struct net_device *net_dev, int prtad, int devad, u16 addr, u16 value) { @@ -629,7 +620,6 @@ const struct efx_nic_type siena_a0_nic_type = { .stop_stats = siena_stop_nic_stats, .set_id_led = efx_mcdi_set_id_led, .push_irq_moderation = siena_push_irq_moderation, - .push_multicast_hash = siena_push_multicast_hash, .reconfigure_mac = efx_mcdi_mac_reconfigure, .check_mac_fault = efx_mcdi_mac_check_fault, .reconfigure_port = efx_mcdi_phy_reconfigure, -- cgit v1.2.3 From cc180b69c009ec52f67a56d96b9073b9f774b323 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 8 Dec 2011 19:51:47 +0000 Subject: sfc: Correct interrupt timer quantum for Siena (normal and turbo mode) We currently assume that the timer quantum for Siena is 5 us, the same as for Falcon. This is not correct; timer ticks are generated on a rota which takes a minimum of 768 cycles (each event delivery or other timer change will delay it by 3 cycles). The timer quantum should be 6.144 or 3.072 us depending on whether turbo mode is active. Replace EFX_IRQ_MOD_RESOLUTION with a timer_quantum_ns field in struct efx_nic, initialised by the efx_nic_type::probe function. While we're at it, replace EFX_IRQ_MOD_MAX with a timer_period_max field in struct efx_nic_type. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 31 ++++++++++++++++++++++--------- drivers/net/ethernet/sfc/falcon.c | 6 ++++-- drivers/net/ethernet/sfc/net_driver.h | 4 ++++ drivers/net/ethernet/sfc/nic.h | 3 --- drivers/net/ethernet/sfc/siena.c | 13 ++++++++++--- 5 files changed, 40 insertions(+), 17 deletions(-) (limited to 'drivers/net/ethernet/sfc/falcon.c') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index de162474c3c5..9d4ab5e5e1fa 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1513,13 +1513,13 @@ static void efx_remove_all(struct efx_nic *efx) * **************************************************************************/ -static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int resolution) +static unsigned int irq_mod_ticks(unsigned int usecs, unsigned int quantum_ns) { if (usecs == 0) return 0; - if (usecs < resolution) + if (usecs * 1000 < quantum_ns) return 1; /* never round down to 0 */ - return usecs / resolution; + return usecs * 1000 / quantum_ns; } /* Set interrupt moderation parameters */ @@ -1528,14 +1528,20 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, bool rx_may_override_tx) { struct efx_channel *channel; - unsigned tx_ticks = irq_mod_ticks(tx_usecs, EFX_IRQ_MOD_RESOLUTION); - unsigned rx_ticks = irq_mod_ticks(rx_usecs, EFX_IRQ_MOD_RESOLUTION); + unsigned int irq_mod_max = DIV_ROUND_UP(efx->type->timer_period_max * + efx->timer_quantum_ns, + 1000); + unsigned int tx_ticks; + unsigned int rx_ticks; EFX_ASSERT_RESET_SERIALISED(efx); - if (tx_ticks > EFX_IRQ_MOD_MAX || rx_ticks > EFX_IRQ_MOD_MAX) + if (tx_usecs > irq_mod_max || rx_usecs > irq_mod_max) return -EINVAL; + tx_ticks = irq_mod_ticks(tx_usecs, efx->timer_quantum_ns); + rx_ticks = irq_mod_ticks(rx_usecs, efx->timer_quantum_ns); + if (tx_ticks != rx_ticks && efx->tx_channel_offset == 0 && !rx_may_override_tx) { netif_err(efx, drv, efx->net_dev, "Channels are shared. " @@ -1558,8 +1564,14 @@ int efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, unsigned int *rx_usecs, bool *rx_adaptive) { + /* We must round up when converting ticks to microseconds + * because we round down when converting the other way. + */ + *rx_adaptive = efx->irq_rx_adaptive; - *rx_usecs = efx->irq_rx_moderation * EFX_IRQ_MOD_RESOLUTION; + *rx_usecs = DIV_ROUND_UP(efx->irq_rx_moderation * + efx->timer_quantum_ns, + 1000); /* If channels are shared between RX and TX, so is IRQ * moderation. Otherwise, IRQ moderation is the same for all @@ -1568,9 +1580,10 @@ void efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, if (efx->tx_channel_offset == 0) *tx_usecs = *rx_usecs; else - *tx_usecs = + *tx_usecs = DIV_ROUND_UP( efx->channel[efx->tx_channel_offset]->irq_moderation * - EFX_IRQ_MOD_RESOLUTION; + efx->timer_quantum_ns, + 1000); } /************************************************************************** diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index fe21c7e349b6..0b7880b0b8fc 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -103,8 +103,6 @@ static void falcon_push_irq_moderation(struct efx_channel *channel) efx_dword_t timer_cmd; struct efx_nic *efx = channel->efx; - BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_AB_TC_TIMER_VAL_WIDTH)); - /* Set timer register */ if (channel->irq_moderation) { EFX_POPULATE_DWORD_2(timer_cmd, @@ -1471,6 +1469,8 @@ static int falcon_probe_nic(struct efx_nic *efx) goto fail5; } + efx->timer_quantum_ns = 4968; /* 621 cycles */ + /* Initialise I2C adapter */ board = falcon_board(efx); board->i2c_adap.owner = THIS_MODULE; @@ -1785,6 +1785,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .rx_buffer_padding = 0x24, .max_interrupt_mode = EFX_INT_MODE_MSI, .phys_addr_channels = 4, + .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM, @@ -1836,6 +1837,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy * interrupt handler only supports 32 * channels */ + .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 4cbd997e378b..8ce4d068bba5 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -624,6 +624,7 @@ struct efx_filter_state; * @membase_phys: Memory BAR value as physical address * @membase: Memory BAR value * @interrupt_mode: Interrupt mode + * @timer_quantum_ns: Interrupt timer quantum, in nanoseconds * @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues * @irq_rx_moderation: IRQ moderation time for RX event queues * @msg_enable: Log message enable flags @@ -706,6 +707,7 @@ struct efx_nic { void __iomem *membase; enum efx_int_mode interrupt_mode; + unsigned int timer_quantum_ns; bool irq_rx_adaptive; unsigned int irq_rx_moderation; u32 msg_enable; @@ -845,6 +847,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * from &enum efx_init_mode. * @phys_addr_channels: Number of channels with physically addressed * descriptors + * @timer_period_max: Maximum period of interrupt timer (in ticks) * @tx_dc_base: Base address in SRAM of TX queue descriptor caches * @rx_dc_base: Base address in SRAM of RX queue descriptor caches * @offload_features: net_device feature flags for protocol offload @@ -889,6 +892,7 @@ struct efx_nic_type { unsigned int rx_buffer_padding; unsigned int max_interrupt_mode; unsigned int phys_addr_channels; + unsigned int timer_period_max; unsigned int tx_dc_base; unsigned int rx_dc_base; netdev_features_t offload_features; diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index cfda6ded24fe..a3ccd0b9d78d 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -205,9 +205,6 @@ extern irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx); extern irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id); extern void falcon_irq_ack_a1(struct efx_nic *efx); -#define EFX_IRQ_MOD_RESOLUTION 5 -#define EFX_IRQ_MOD_MAX 0x1000 - /* Global Resources */ extern int efx_nic_flush_queues(struct efx_nic *efx); extern void falcon_start_nic_stats(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 65cb5e4f4264..f05425842b31 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -35,8 +35,6 @@ static void siena_push_irq_moderation(struct efx_channel *channel) { efx_dword_t timer_cmd; - BUILD_BUG_ON(EFX_IRQ_MOD_MAX > (1 << FRF_CZ_TC_TIMER_VAL_WIDTH)); - if (channel->irq_moderation) EFX_POPULATE_DWORD_2(timer_cmd, FRF_CZ_TC_TIMER_MODE, @@ -216,7 +214,15 @@ static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) static int siena_probe_nvconfig(struct efx_nic *efx) { - return efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL, NULL); + u32 caps = 0; + int rc; + + rc = efx_mcdi_get_board_cfg(efx, efx->net_dev->perm_addr, NULL, &caps); + + efx->timer_quantum_ns = + (caps & (1 << MC_CMD_CAPABILITIES_TURBO_ACTIVE_LBN)) ? + 3072 : 6144; /* 768 cycles */ + return rc; } static int siena_probe_nic(struct efx_nic *efx) @@ -644,6 +650,7 @@ const struct efx_nic_type siena_a0_nic_type = { .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy * interrupt handler only supports 32 * channels */ + .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH, .tx_dc_base = 0x88000, .rx_dc_base = 0x68000, .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | -- cgit v1.2.3 From f70d1847348e9548a9a56e4434946315bca297c8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 6 Jan 2012 01:08:24 +0000 Subject: Partly revert "sfc: Handle serious errors in exactly one interrupt handler" This reverts commit 6369545945b90daa1a73fca174da9194c398417c in drivers/net/ethernet/sfc/falcon.c. Unlike the INT_ISR0 register on later controller revisions, the NET_IVEC_INT_Q bits written to memory are only ever set for interrupting event queues, not for any other interrupt sources. By definition there can only be one legacy interrupt handler per function, so there is no need to worry about detecting a fatal interrupt more than once. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/falcon.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers/net/ethernet/sfc/falcon.c') diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 0b7880b0b8fc..b4e91edec0fa 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -174,19 +174,16 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); + /* Check to see if we have a serious error condition */ + syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); + if (unlikely(syserr)) + return efx_nic_fatal_interrupt(efx); + /* Determine interrupting queues, clear interrupt status * register and acknowledge the device interrupt. */ BUILD_BUG_ON(FSF_AZ_NET_IVEC_INT_Q_WIDTH > EFX_MAX_CHANNELS); queues = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_INT_Q); - - /* Check to see if we have a serious error condition */ - if (queues & (1U << efx->fatal_irq_level)) { - syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); - if (unlikely(syserr)) - return efx_nic_fatal_interrupt(efx); - } - EFX_ZERO_OWORD(*int_ker); wmb(); /* Ensure the vector is cleared before interrupt ack */ falcon_irq_ack_a1(efx); -- cgit v1.2.3 From 1646a6f352a6f70fcca828589ed04797aa09d494 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Jan 2012 20:14:10 +0000 Subject: sfc: Clean up test interrupt handling Interrupts are normally generated by the event queues, moderated by timers. However, they may also be triggered by detection of a 'fatal' error condition (e.g. memory parity error) or by the host writing to certain CSR fields as part of a self-test. The IRQ level/index used for these on Falcon rev B0 and Siena is set by the KER_INT_LEVE_SEL field and cached by the driver in efx_nic::fatal_irq_level. Since this value is also relevant to self-tests rename the field to just 'irq_level'. Avoid unnecessary cache traffic by using a per-channel 'last_irq_cpu' field and only writing to the per-controller field when the interrupt matches efx_nic::irq_level. Remove the volatile qualifier and use ACCESS_ONCE in the places we read these fields. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.h | 6 ++++++ drivers/net/ethernet/sfc/falcon.c | 4 ++-- drivers/net/ethernet/sfc/net_driver.h | 15 ++++++++------- drivers/net/ethernet/sfc/nic.c | 27 +++++++++++++-------------- drivers/net/ethernet/sfc/selftest.c | 12 +++++++----- 5 files changed, 36 insertions(+), 28 deletions(-) (limited to 'drivers/net/ethernet/sfc/falcon.c') diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index a3541ac6ea01..e0b66d158d79 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -145,6 +145,12 @@ static inline void efx_schedule_channel(struct efx_channel *channel) napi_schedule(&channel->napi_str); } +static inline void efx_schedule_channel_irq(struct efx_channel *channel) +{ + channel->last_irq_cpu = raw_smp_processor_id(); + efx_schedule_channel(channel); +} + extern void efx_link_status_changed(struct efx_nic *efx); extern void efx_link_set_advertising(struct efx_nic *efx, u32); extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8); diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index b4e91edec0fa..98285115df10 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -189,9 +189,9 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) falcon_irq_ack_a1(efx); if (queues & 1) - efx_schedule_channel(efx_get_channel(efx, 0)); + efx_schedule_channel_irq(efx_get_channel(efx, 0)); if (queues & 2) - efx_schedule_channel(efx_get_channel(efx, 1)); + efx_schedule_channel_irq(efx_get_channel(efx, 1)); return IRQ_HANDLED; } /************************************************************************** diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 8ce4d068bba5..a4cf8cb8180c 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -325,6 +325,7 @@ enum efx_rx_alloc_method { * @eventq_mask: Event queue pointer mask * @eventq_read_ptr: Event queue read pointer * @last_eventq_read_ptr: Last event queue read pointer value. + * @last_irq_cpu: Last CPU to handle interrupt for this channel * @irq_count: Number of IRQs since last adaptive moderation decision * @irq_mod_score: IRQ moderation score * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors @@ -355,6 +356,7 @@ struct efx_channel { unsigned int eventq_read_ptr; unsigned int last_eventq_read_ptr; + int last_irq_cpu; unsigned int irq_count; unsigned int irq_mod_score; #ifdef CONFIG_RFS_ACCEL @@ -648,7 +650,7 @@ struct efx_filter_state; * @int_error_expire: Time at which error count will be expired * @irq_status: Interrupt status buffer * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0 - * @fatal_irq_level: IRQ level (bit number) used for serious errors + * @irq_level: IRQ level/index for IRQs not triggered by an event queue * @mtd_list: List of MTDs attached to the NIC * @nic_data: Hardware dependent state * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, @@ -679,10 +681,9 @@ struct efx_filter_state; * @loopback_selftest: Offline self-test private state * @monitor_work: Hardware monitor workitem * @biu_lock: BIU (bus interface unit) lock - * @last_irq_cpu: Last CPU to handle interrupt. - * This register is written with the SMP processor ID whenever an - * interrupt is handled. It is used by efx_nic_test_interrupt() - * to verify that an interrupt has occurred. + * @last_irq_cpu: Last CPU to handle a possible test interrupt. This + * field is used by efx_test_interrupts() to verify that an + * interrupt has occurred. * @n_rx_nodesc_drop_cnt: RX no descriptor drop count * @mac_stats: MAC statistics. These include all statistics the MACs * can provide. Generic code converts these into a standard @@ -735,7 +736,7 @@ struct efx_nic { struct efx_buffer irq_status; unsigned irq_zero_count; - unsigned fatal_irq_level; + unsigned irq_level; #ifdef CONFIG_SFC_MTD struct list_head mtd_list; @@ -779,7 +780,7 @@ struct efx_nic { struct delayed_work monitor_work ____cacheline_aligned_in_smp; spinlock_t biu_lock; - volatile signed int last_irq_cpu; + int last_irq_cpu; unsigned n_rx_nodesc_drop_cnt; struct efx_mac_stats mac_stats; spinlock_t stats_lock; diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index bf07bd0488cf..de7aa1c8ebda 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -1311,7 +1311,7 @@ static inline void efx_nic_interrupts(struct efx_nic *efx, efx_oword_t int_en_reg_ker; EFX_POPULATE_OWORD_3(int_en_reg_ker, - FRF_AZ_KER_INT_LEVE_SEL, efx->fatal_irq_level, + FRF_AZ_KER_INT_LEVE_SEL, efx->irq_level, FRF_AZ_KER_INT_KER, force, FRF_AZ_DRV_INT_EN_KER, enabled); efx_writeo(efx, &int_en_reg_ker, FR_AZ_INT_EN_KER); @@ -1427,11 +1427,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) efx_readd(efx, ®, FR_BZ_INT_ISR0); queues = EFX_EXTRACT_DWORD(reg, 0, 31); - /* Check to see if we have a serious error condition */ - if (queues & (1U << efx->fatal_irq_level)) { + /* Handle non-event-queue sources */ + if (queues & (1U << efx->irq_level)) { syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); if (unlikely(syserr)) return efx_nic_fatal_interrupt(efx); + efx->last_irq_cpu = raw_smp_processor_id(); } if (queues != 0) { @@ -1441,7 +1442,7 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) /* Schedule processing of any interrupting queues */ efx_for_each_channel(channel, efx) { if (queues & 1) - efx_schedule_channel(channel); + efx_schedule_channel_irq(channel); queues >>= 1; } result = IRQ_HANDLED; @@ -1458,18 +1459,16 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id) efx_for_each_channel(channel, efx) { event = efx_event(channel, channel->eventq_read_ptr); if (efx_event_present(event)) - efx_schedule_channel(channel); + efx_schedule_channel_irq(channel); else efx_nic_eventq_read_ack(channel); } } - if (result == IRQ_HANDLED) { - efx->last_irq_cpu = raw_smp_processor_id(); + if (result == IRQ_HANDLED) netif_vdbg(efx, intr, efx->net_dev, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); - } return result; } @@ -1488,20 +1487,20 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id) efx_oword_t *int_ker = efx->irq_status.addr; int syserr; - efx->last_irq_cpu = raw_smp_processor_id(); netif_vdbg(efx, intr, efx->net_dev, "IRQ %d on CPU %d status " EFX_OWORD_FMT "\n", irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker)); - /* Check to see if we have a serious error condition */ - if (channel->channel == efx->fatal_irq_level) { + /* Handle non-event-queue sources */ + if (channel->channel == efx->irq_level) { syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT); if (unlikely(syserr)) return efx_nic_fatal_interrupt(efx); + efx->last_irq_cpu = raw_smp_processor_id(); } /* Schedule processing of the channel */ - efx_schedule_channel(channel); + efx_schedule_channel_irq(channel); return IRQ_HANDLED; } @@ -1640,10 +1639,10 @@ void efx_nic_init_common(struct efx_nic *efx) if (EFX_WORKAROUND_17213(efx) && !EFX_INT_MODE_USE_MSI(efx)) /* Use an interrupt level unused by event queues */ - efx->fatal_irq_level = 0x1f; + efx->irq_level = 0x1f; else /* Use a valid MSI-X vector */ - efx->fatal_irq_level = 0; + efx->irq_level = 0; /* Enable all the genuinely fatal interrupts. (They are still * masked by the overall interrupt mask, controlled by diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 0f8478924475..7def480570c3 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -130,6 +130,8 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) static int efx_test_interrupts(struct efx_nic *efx, struct efx_self_tests *tests) { + int cpu; + netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n"); tests->interrupt = -1; @@ -142,7 +144,8 @@ static int efx_test_interrupts(struct efx_nic *efx, /* Wait for arrival of test interrupt. */ netif_dbg(efx, drv, efx->net_dev, "waiting for test interrupt\n"); schedule_timeout_uninterruptible(HZ / 10); - if (efx->last_irq_cpu >= 0) + cpu = ACCESS_ONCE(efx->last_irq_cpu); + if (cpu >= 0) goto success; netif_err(efx, drv, efx->net_dev, "timed out waiting for interrupt\n"); @@ -150,8 +153,7 @@ static int efx_test_interrupts(struct efx_nic *efx, success: netif_dbg(efx, drv, efx->net_dev, "%s test interrupt seen on CPU%d\n", - INT_MODE(efx), - efx->last_irq_cpu); + INT_MODE(efx), cpu); tests->interrupt = 1; return 0; } @@ -165,7 +167,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, bool napi_ran, dma_seen, int_seen; read_ptr = channel->eventq_read_ptr; - channel->efx->last_irq_cpu = -1; + channel->last_irq_cpu = -1; smp_wmb(); efx_nic_generate_test_event(channel); @@ -182,7 +184,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel, } else { napi_ran = false; dma_seen = efx_nic_event_present(channel); - int_seen = efx->last_irq_cpu >= 0; + int_seen = ACCESS_ONCE(channel->last_irq_cpu) >= 0; } napi_enable(&channel->napi_str); efx_nic_eventq_read_ack(channel); -- cgit v1.2.3 From 28e47c498a931200125e299e9d60d22e27b4ab0d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 15 Feb 2012 01:58:49 +0000 Subject: sfc: Allocate SRAM between buffer table and descriptor caches at init time Each port has a block of 64-bit SRAM that is divided between buffer table and descriptor cache regions at initialisation time. Currently we use a fixed allocation, but it needs to be changed to support larger numbers of queues. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 2 ++ drivers/net/ethernet/sfc/falcon.c | 12 ++++++++---- drivers/net/ethernet/sfc/net_driver.h | 13 +++++++++---- drivers/net/ethernet/sfc/nic.c | 23 +++++++++++++++++++---- drivers/net/ethernet/sfc/nic.h | 2 ++ drivers/net/ethernet/sfc/siena.c | 12 ++++++++++-- 6 files changed, 50 insertions(+), 14 deletions(-) (limited to 'drivers/net/ethernet/sfc/falcon.c') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index e943ffbe5e2a..c9c306aef2d9 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1420,6 +1420,8 @@ static int efx_probe_nic(struct efx_nic *efx) if (rc) goto fail; + efx->type->dimension_resources(efx); + if (efx->n_channels > 1) get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key)); for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++) diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 98285115df10..3a1ca2bd1548 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -1333,6 +1333,12 @@ out: return rc; } +static void falcon_dimension_resources(struct efx_nic *efx) +{ + efx->rx_dc_base = 0x20000; + efx->tx_dc_base = 0x26000; +} + /* Probe all SPI devices on the NIC */ static void falcon_probe_spi_devices(struct efx_nic *efx) { @@ -1749,6 +1755,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .probe = falcon_probe_nic, .remove = falcon_remove_nic, .init = falcon_init_nic, + .dimension_resources = falcon_dimension_resources, .fini = efx_port_dummy_op_void, .monitor = falcon_monitor, .map_reset_reason = falcon_map_reset_reason, @@ -1783,8 +1790,6 @@ const struct efx_nic_type falcon_a1_nic_type = { .max_interrupt_mode = EFX_INT_MODE_MSI, .phys_addr_channels = 4, .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, - .tx_dc_base = 0x130000, - .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM, }; @@ -1792,6 +1797,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .probe = falcon_probe_nic, .remove = falcon_remove_nic, .init = falcon_init_nic, + .dimension_resources = falcon_dimension_resources, .fini = efx_port_dummy_op_void, .monitor = falcon_monitor, .map_reset_reason = falcon_map_reset_reason, @@ -1835,8 +1841,6 @@ const struct efx_nic_type falcon_b0_nic_type = { * interrupt handler only supports 32 * channels */ .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, - .tx_dc_base = 0x130000, - .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, }; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 94b0dcab897f..7870cefcb203 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -658,6 +658,9 @@ struct efx_filter_state; * should be allocated for this NIC * @rxq_entries: Size of receive queues requested by user. * @txq_entries: Size of transmit queues requested by user. + * @tx_dc_base: Base qword address in SRAM of TX queue descriptor caches + * @rx_dc_base: Base qword address in SRAM of RX queue descriptor caches + * @sram_lim_qw: Qword address limit of SRAM * @next_buffer_table: First available buffer table id * @n_channels: Number of channels in use * @n_rx_channels: Number of channels used for RX (= number of RX queues) @@ -753,6 +756,9 @@ struct efx_nic { unsigned rxq_entries; unsigned txq_entries; + unsigned tx_dc_base; + unsigned rx_dc_base; + unsigned sram_lim_qw; unsigned next_buffer_table; unsigned n_channels; unsigned n_rx_channels; @@ -839,6 +845,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @probe: Probe the controller * @remove: Free resources allocated by probe() * @init: Initialise the controller + * @dimension_resources: Dimension controller resources (buffer table, + * and VIs once the available interrupt resources are clear) * @fini: Shut down the controller * @monitor: Periodic function for polling link state and hardware monitor * @map_reset_reason: Map ethtool reset reason to a reset method @@ -878,8 +886,6 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @phys_addr_channels: Number of channels with physically addressed * descriptors * @timer_period_max: Maximum period of interrupt timer (in ticks) - * @tx_dc_base: Base address in SRAM of TX queue descriptor caches - * @rx_dc_base: Base address in SRAM of RX queue descriptor caches * @offload_features: net_device feature flags for protocol offload * features implemented in hardware */ @@ -887,6 +893,7 @@ struct efx_nic_type { int (*probe)(struct efx_nic *efx); void (*remove)(struct efx_nic *efx); int (*init)(struct efx_nic *efx); + void (*dimension_resources)(struct efx_nic *efx); void (*fini)(struct efx_nic *efx); void (*monitor)(struct efx_nic *efx); enum reset_type (*map_reset_reason)(enum reset_type reason); @@ -923,8 +930,6 @@ struct efx_nic_type { unsigned int max_interrupt_mode; unsigned int phys_addr_channels; unsigned int timer_period_max; - unsigned int tx_dc_base; - unsigned int rx_dc_base; netdev_features_t offload_features; }; diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 2bdfb6374ce8..747cf9439164 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -1609,6 +1609,23 @@ void efx_nic_fini_interrupt(struct efx_nic *efx) free_irq(efx->legacy_irq, efx); } +void efx_nic_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw) +{ + unsigned vi_count, buftbl_min; + + /* Account for the buffer table entries backing the datapath channels + * and the descriptor caches for those channels. + */ + buftbl_min = ((efx->n_rx_channels * EFX_MAX_DMAQ_SIZE + + efx->n_tx_channels * EFX_TXQ_TYPES * EFX_MAX_DMAQ_SIZE + + efx->n_channels * EFX_MAX_EVQ_SIZE) + * sizeof(efx_qword_t) / EFX_BUF_SIZE); + vi_count = max(efx->n_channels, efx->n_tx_channels * EFX_TXQ_TYPES); + + efx->tx_dc_base = sram_lim_qw - vi_count * TX_DC_ENTRIES; + efx->rx_dc_base = efx->tx_dc_base - vi_count * RX_DC_ENTRIES; +} + u32 efx_nic_fpga_ver(struct efx_nic *efx) { efx_oword_t altera_build; @@ -1621,11 +1638,9 @@ void efx_nic_init_common(struct efx_nic *efx) efx_oword_t temp; /* Set positions of descriptor caches in SRAM. */ - EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_TX_DC_BASE_ADR, - efx->type->tx_dc_base / 8); + EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_TX_DC_BASE_ADR, efx->tx_dc_base); efx_writeo(efx, &temp, FR_AZ_SRM_TX_DC_CFG); - EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_RX_DC_BASE_ADR, - efx->type->rx_dc_base / 8); + EFX_POPULATE_OWORD_1(temp, FRF_AZ_SRM_RX_DC_BASE_ADR, efx->rx_dc_base); efx_writeo(efx, &temp, FR_AZ_SRM_RX_DC_CFG); /* Set TX descriptor cache size. */ diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 1f53e2c7cfd7..5df7da8b8ebf 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -230,6 +230,8 @@ extern void falcon_start_nic_stats(struct efx_nic *efx); extern void falcon_stop_nic_stats(struct efx_nic *efx); extern void falcon_setup_xaui(struct efx_nic *efx); extern int falcon_reset_xaui(struct efx_nic *efx); +extern void +efx_nic_dimension_resources(struct efx_nic *efx, unsigned sram_lim_qw); extern void efx_nic_init_common(struct efx_nic *efx); extern void efx_nic_push_rx_indir_table(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index d3c4169e2a0b..657f3fa93bcf 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -225,6 +225,15 @@ static int siena_probe_nvconfig(struct efx_nic *efx) return rc; } +static void siena_dimension_resources(struct efx_nic *efx) +{ + /* Each port has a small block of internal SRAM dedicated to + * the buffer table and descriptor caches. In theory we can + * map both blocks to one port, but we don't. + */ + efx_nic_dimension_resources(efx, FR_CZ_BUF_FULL_TBL_ROWS / 2); +} + static int siena_probe_nic(struct efx_nic *efx) { struct siena_nic_data *nic_data; @@ -619,6 +628,7 @@ const struct efx_nic_type siena_a0_nic_type = { .probe = siena_probe_nic, .remove = siena_remove_nic, .init = siena_init_nic, + .dimension_resources = siena_dimension_resources, .fini = efx_port_dummy_op_void, .monitor = NULL, .map_reset_reason = siena_map_reset_reason, @@ -657,8 +667,6 @@ const struct efx_nic_type siena_a0_nic_type = { * interrupt handler only supports 32 * channels */ .timer_period_max = 1 << FRF_CZ_TC_TIMER_VAL_WIDTH, - .tx_dc_base = 0x88000, - .rx_dc_base = 0x68000, .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE), }; -- cgit v1.2.3