From 4017dbdc14af1903dc9fcba4d08b89c02325069d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 24 Jun 2011 20:26:44 +0100 Subject: [PATCH 1/7] sfc: Fix loop condition for efx_filter_search() when !for_insert efx_filter_remove_filter() fails to remove inserted filters in some cases. For example: 1. Two filters A and B have specifications that result in an initial hash collision. 2. A is inserted first, followed by B. 3. An attempt to remove B first succeeds, but if A is removed first a subsequent attempt to remove B fails. When searching for an existing filter (!for_insert), efx_filter_search() must always continue to the maximum search depth for the given type rather than stopping at the first unused entry. Signed-off-by: Ben Hutchings --- drivers/net/sfc/filter.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c index f2fc2587c09d..054f0a3d45a9 100644 --- a/drivers/net/sfc/filter.c +++ b/drivers/net/sfc/filter.c @@ -335,28 +335,35 @@ static int efx_filter_search(struct efx_filter_table *table, bool for_insert, int *depth_required) { unsigned hash, incr, filter_idx, depth, depth_max; - struct efx_filter_spec *cmp; hash = efx_filter_hash(key); incr = efx_filter_increment(key); - depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ? - FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX); - for (depth = 1, filter_idx = hash & (table->size - 1); - depth <= depth_max && test_bit(filter_idx, table->used_bitmap); - ++depth) { - cmp = &table->spec[filter_idx]; - if (efx_filter_equal(spec, cmp)) - goto found; + filter_idx = hash & (table->size - 1); + depth = 1; + depth_max = (for_insert ? + (spec->priority <= EFX_FILTER_PRI_HINT ? + FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX) : + table->search_depth[spec->type]); + + for (;;) { + /* Return success if entry is used and matches this spec + * or entry is unused and we are trying to insert. + */ + if (test_bit(filter_idx, table->used_bitmap) ? + efx_filter_equal(spec, &table->spec[filter_idx]) : + for_insert) { + *depth_required = depth; + return filter_idx; + } + + /* Return failure if we reached the maximum search depth */ + if (depth == depth_max) + return for_insert ? -EBUSY : -ENOENT; + filter_idx = (filter_idx + incr) & (table->size - 1); + ++depth; } - if (!for_insert) - return -ENOENT; - if (depth > depth_max) - return -EBUSY; -found: - *depth_required = depth; - return filter_idx; } /* Construct/deconstruct external filter IDs */ From a7d529ae2158b5300e4aa16c21f1828bc864449b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 24 Jun 2011 20:46:31 +0100 Subject: [PATCH 2/7] sfc: Allow resets to be upgraded; use atomic ops for safety Currently an attempt to schedule any reset is ignored if a reset is already pending. This ignores the relative scopes - if the requested reset is greater in scope then the scheduled reset should be upgraded accordingly. There are also some race conditions which could lead to a reset request being lost. Deal with them by using atomic operations on a bitmask. This also makes tests on reset_pending easier to get right. Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 38 ++++++++++++++++-------------------- drivers/net/sfc/enum.h | 3 ++- drivers/net/sfc/falcon.c | 2 +- drivers/net/sfc/net_driver.h | 4 ++-- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index c914729f9554..9b4cfdb09516 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -229,8 +229,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget) struct efx_nic *efx = channel->efx; int spent; - if (unlikely(efx->reset_pending != RESET_TYPE_NONE || - !channel->enabled)) + if (unlikely(efx->reset_pending || !channel->enabled)) return 0; spent = efx_nic_process_eventq(channel, budget); @@ -1461,7 +1460,7 @@ static void efx_start_all(struct efx_nic *efx) * reset_pending [modified from an atomic context], we instead guarantee * that efx_mcdi_mode_poll() isn't reverted erroneously */ efx_mcdi_mode_event(efx); - if (efx->reset_pending != RESET_TYPE_NONE) + if (efx->reset_pending) efx_mcdi_mode_poll(efx); /* Start the hardware monitor if there is one. Otherwise (we're link @@ -2118,8 +2117,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) goto out; } - /* Allow resets to be rescheduled. */ - efx->reset_pending = RESET_TYPE_NONE; + /* Clear flags for the scopes we covered. We assume the NIC and + * driver are now quiescent so that there is no race here. + */ + efx->reset_pending &= -(1 << (method + 1)); /* Reinitialise bus-mastering, which may have been turned off before * the reset was scheduled. This is still appropriate, even in the @@ -2154,12 +2155,13 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) static void efx_reset_work(struct work_struct *data) { struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); + unsigned long pending = ACCESS_ONCE(efx->reset_pending); - if (efx->reset_pending == RESET_TYPE_NONE) + if (!pending) return; /* If we're not RUNNING then don't reset. Leave the reset_pending - * flag set so that efx_pci_probe_main will be retried */ + * flags set so that efx_pci_probe_main will be retried */ if (efx->state != STATE_RUNNING) { netif_info(efx, drv, efx->net_dev, "scheduled reset quenched. NIC not RUNNING\n"); @@ -2167,7 +2169,7 @@ static void efx_reset_work(struct work_struct *data) } rtnl_lock(); - (void)efx_reset(efx, efx->reset_pending); + (void)efx_reset(efx, fls(pending) - 1); rtnl_unlock(); } @@ -2175,12 +2177,6 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) { enum reset_type method; - if (efx->reset_pending != RESET_TYPE_NONE) { - netif_info(efx, drv, efx->net_dev, - "quenching already scheduled reset\n"); - return; - } - switch (type) { case RESET_TYPE_INVISIBLE: case RESET_TYPE_ALL: @@ -2208,7 +2204,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", RESET_TYPE(method)); - efx->reset_pending = method; + set_bit(method, &efx->reset_pending); /* efx_process_channel() will no longer read events once a * reset is scheduled. So switch back to poll'd MCDI completions. */ @@ -2288,7 +2284,6 @@ static int efx_init_struct(struct efx_nic *efx, const struct efx_nic_type *type, efx->pci_dev = pci_dev; efx->msg_enable = debug; efx->state = STATE_INIT; - efx->reset_pending = RESET_TYPE_NONE; strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); efx->net_dev = net_dev; @@ -2510,7 +2505,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, cancel_work_sync(&efx->reset_work); if (rc == 0) { - if (efx->reset_pending != RESET_TYPE_NONE) { + if (efx->reset_pending) { /* If there was a scheduled reset during * probe, the NIC is probably hosed anyway */ efx_pci_remove_main(efx); @@ -2521,11 +2516,12 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, } /* Retry if a recoverably reset event has been scheduled */ - if ((efx->reset_pending != RESET_TYPE_INVISIBLE) && - (efx->reset_pending != RESET_TYPE_ALL)) + if (efx->reset_pending & + ~(1 << RESET_TYPE_INVISIBLE | 1 << RESET_TYPE_ALL) || + !efx->reset_pending) goto fail3; - efx->reset_pending = RESET_TYPE_NONE; + efx->reset_pending = 0; } if (rc) { @@ -2609,7 +2605,7 @@ static int efx_pm_poweroff(struct device *dev) efx->type->fini(efx); - efx->reset_pending = RESET_TYPE_NONE; + efx->reset_pending = 0; pci_save_state(pci_dev); return pci_set_power_state(pci_dev, PCI_D3hot); diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h index 384cfe3b1be1..d725a8fbe1a6 100644 --- a/drivers/net/sfc/enum.h +++ b/drivers/net/sfc/enum.h @@ -134,6 +134,8 @@ enum efx_loopback_mode { * other valuesspecify reasons, which efx_schedule_reset() will choose * a method for. * + * Reset methods are numbered in order of increasing scope. + * * @RESET_TYPE_INVISIBLE: don't reset the PHYs or interrupts * @RESET_TYPE_ALL: reset everything but PCI core blocks * @RESET_TYPE_WORLD: reset everything, save & restore PCI config @@ -147,7 +149,6 @@ enum efx_loopback_mode { * @RESET_TYPE_MC_FAILURE: MC reboot/assertion */ enum reset_type { - RESET_TYPE_NONE = -1, RESET_TYPE_INVISIBLE = 0, RESET_TYPE_ALL = 1, RESET_TYPE_WORLD = 2, diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 60176e873d62..a4c7830ec9b0 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -536,7 +536,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) efx_oword_t reg; int link_speed, isolate; - isolate = (efx->reset_pending != RESET_TYPE_NONE); + isolate = !!ACCESS_ONCE(efx->reset_pending); switch (link_state->speed) { case 10000: link_speed = 3; break; diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index e8d5f03a89fe..c422eb2ce60a 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -645,7 +645,7 @@ struct efx_filter_state; * @irq_rx_moderation: IRQ moderation time for RX event queues * @msg_enable: Log message enable flags * @state: Device state flag. Serialised by the rtnl_lock. - * @reset_pending: Pending reset method (normally RESET_TYPE_NONE) + * @reset_pending: Bitmask for pending resets * @tx_queue: TX DMA queues * @rx_queue: RX DMA queues * @channel: Channels @@ -728,7 +728,7 @@ struct efx_nic { u32 msg_enable; enum nic_state state; - enum reset_type reset_pending; + unsigned long reset_pending; struct efx_channel *channel[EFX_MAX_CHANNELS]; char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6]; From 0e2a9c7cb941db993f481cdd6a99d70a302053e0 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 24 Jun 2011 20:50:07 +0100 Subject: [PATCH 3/7] sfc: Fix mapping of reset reasons and flags to methods There are certain hardware bugs that may occur on Falcon during normal operation, that require a reset to recover from. We try to minimise disruption by keeping the PHY running, following a reset sequence labelled as 'invisible'. Siena does not suffer from these hardware bugs, so we have not implemented an 'invisible' reset sequence. However, if a similar error does occur (due to a hardware fault or software bug) then the code shared with Falcon will wrongly assume that the PHY is not being reset. Since the mapping of reset reasons (internal) and flags (ethtool) to methods must differ significantly between NIC types, move it into per-NIC-type functions (replacing the insufficient reset_world_flags field). Signed-off-by: Ben Hutchings --- drivers/net/sfc/efx.c | 20 ++++----------- drivers/net/sfc/ethtool.c | 27 ++++---------------- drivers/net/sfc/falcon.c | 49 ++++++++++++++++++++++++++++++++++-- drivers/net/sfc/net_driver.h | 7 +++--- drivers/net/sfc/siena.c | 33 +++++++++++++++++++++++- 5 files changed, 93 insertions(+), 43 deletions(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 9b4cfdb09516..ff162df06bd0 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -2183,26 +2183,16 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) case RESET_TYPE_WORLD: case RESET_TYPE_DISABLE: method = type; + netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", + RESET_TYPE(method)); break; - case RESET_TYPE_RX_RECOVERY: - case RESET_TYPE_RX_DESC_FETCH: - case RESET_TYPE_TX_DESC_FETCH: - case RESET_TYPE_TX_SKIP: - method = RESET_TYPE_INVISIBLE; - break; - case RESET_TYPE_MC_FAILURE: default: - method = RESET_TYPE_ALL; - break; - } - - if (method != type) + method = efx->type->map_reset_reason(type); netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset for %s\n", RESET_TYPE(method), RESET_TYPE(type)); - else - netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", - RESET_TYPE(method)); + break; + } set_bit(method, &efx->reset_pending); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index d229027dc363..bc4643af6dd1 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -796,30 +796,13 @@ static int efx_ethtool_set_wol(struct net_device *net_dev, static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) { struct efx_nic *efx = netdev_priv(net_dev); - enum reset_type method; - enum { - ETH_RESET_EFX_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER | - ETH_RESET_OFFLOAD | ETH_RESET_MAC) - }; + int rc; - /* Check for minimal reset flags */ - if ((*flags & ETH_RESET_EFX_INVISIBLE) != ETH_RESET_EFX_INVISIBLE) - return -EINVAL; - *flags ^= ETH_RESET_EFX_INVISIBLE; - method = RESET_TYPE_INVISIBLE; + rc = efx->type->map_reset_flags(flags); + if (rc < 0) + return rc; - if (*flags & ETH_RESET_PHY) { - *flags ^= ETH_RESET_PHY; - method = RESET_TYPE_ALL; - } - - if ((*flags & efx->type->reset_world_flags) == - efx->type->reset_world_flags) { - *flags ^= efx->type->reset_world_flags; - method = RESET_TYPE_WORLD; - } - - return efx_reset(efx, method); + return efx_reset(efx, rc); } static int diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index a4c7830ec9b0..94bf4aaf984d 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1051,6 +1051,49 @@ static int falcon_b0_test_registers(struct efx_nic *efx) ************************************************************************** */ +static enum reset_type falcon_map_reset_reason(enum reset_type reason) +{ + switch (reason) { + case RESET_TYPE_RX_RECOVERY: + case RESET_TYPE_RX_DESC_FETCH: + case RESET_TYPE_TX_DESC_FETCH: + case RESET_TYPE_TX_SKIP: + /* These can occasionally occur due to hardware bugs. + * We try to reset without disrupting the link. + */ + return RESET_TYPE_INVISIBLE; + default: + return RESET_TYPE_ALL; + } +} + +static int falcon_map_reset_flags(u32 *flags) +{ + enum { + FALCON_RESET_INVISIBLE = (ETH_RESET_DMA | ETH_RESET_FILTER | + ETH_RESET_OFFLOAD | ETH_RESET_MAC), + FALCON_RESET_ALL = FALCON_RESET_INVISIBLE | ETH_RESET_PHY, + FALCON_RESET_WORLD = FALCON_RESET_ALL | ETH_RESET_IRQ, + }; + + if ((*flags & FALCON_RESET_WORLD) == FALCON_RESET_WORLD) { + *flags &= ~FALCON_RESET_WORLD; + return RESET_TYPE_WORLD; + } + + if ((*flags & FALCON_RESET_ALL) == FALCON_RESET_ALL) { + *flags &= ~FALCON_RESET_ALL; + return RESET_TYPE_ALL; + } + + if ((*flags & FALCON_RESET_INVISIBLE) == FALCON_RESET_INVISIBLE) { + *flags &= ~FALCON_RESET_INVISIBLE; + return RESET_TYPE_INVISIBLE; + } + + return -EINVAL; +} + /* Resets NIC to known state. This routine must be called in process * context and is allowed to sleep. */ static int __falcon_reset_hw(struct efx_nic *efx, enum reset_type method) @@ -1709,6 +1752,8 @@ const struct efx_nic_type falcon_a1_nic_type = { .init = falcon_init_nic, .fini = efx_port_dummy_op_void, .monitor = falcon_monitor, + .map_reset_reason = falcon_map_reset_reason, + .map_reset_flags = falcon_map_reset_flags, .reset = falcon_reset_hw, .probe_port = falcon_probe_port, .remove_port = falcon_remove_port, @@ -1741,7 +1786,6 @@ const struct efx_nic_type falcon_a1_nic_type = { .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM, - .reset_world_flags = ETH_RESET_IRQ, }; const struct efx_nic_type falcon_b0_nic_type = { @@ -1750,6 +1794,8 @@ const struct efx_nic_type falcon_b0_nic_type = { .init = falcon_init_nic, .fini = efx_port_dummy_op_void, .monitor = falcon_monitor, + .map_reset_reason = falcon_map_reset_reason, + .map_reset_flags = falcon_map_reset_flags, .reset = falcon_reset_hw, .probe_port = falcon_probe_port, .remove_port = falcon_remove_port, @@ -1791,6 +1837,5 @@ const struct efx_nic_type falcon_b0_nic_type = { .tx_dc_base = 0x130000, .rx_dc_base = 0x100000, .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, - .reset_world_flags = ETH_RESET_IRQ, }; diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index c422eb2ce60a..4597066741f1 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -828,6 +828,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @init: Initialise the controller * @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 + * @map_reset_flags: Map ethtool reset flags to a reset method, if possible * @reset: Reset the controller hardware and possibly the PHY. This will * be called while the controller is uninitialised. * @probe_port: Probe the MAC and PHY @@ -865,8 +867,6 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @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 - * @reset_world_flags: Flags for additional components covered by - * reset method RESET_TYPE_WORLD */ struct efx_nic_type { int (*probe)(struct efx_nic *efx); @@ -874,6 +874,8 @@ struct efx_nic_type { int (*init)(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); + int (*map_reset_flags)(u32 *flags); int (*reset)(struct efx_nic *efx, enum reset_type method); int (*probe_port)(struct efx_nic *efx); void (*remove_port)(struct efx_nic *efx); @@ -908,7 +910,6 @@ struct efx_nic_type { unsigned int tx_dc_base; unsigned int rx_dc_base; u32 offload_features; - u32 reset_world_flags; }; /************************************************************************** diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index a66818ed4011..442897b14270 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -177,6 +177,36 @@ static int siena_test_registers(struct efx_nic *efx) ************************************************************************** */ +static enum reset_type siena_map_reset_reason(enum reset_type reason) +{ + return RESET_TYPE_ALL; +} + +static int siena_map_reset_flags(u32 *flags) +{ + enum { + SIENA_RESET_PORT = (ETH_RESET_DMA | ETH_RESET_FILTER | + ETH_RESET_OFFLOAD | ETH_RESET_MAC | + ETH_RESET_PHY), + SIENA_RESET_MC = (SIENA_RESET_PORT | + ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT), + }; + + if ((*flags & SIENA_RESET_MC) == SIENA_RESET_MC) { + *flags &= ~SIENA_RESET_MC; + return RESET_TYPE_WORLD; + } + + if ((*flags & SIENA_RESET_PORT) == SIENA_RESET_PORT) { + *flags &= ~SIENA_RESET_PORT; + return RESET_TYPE_ALL; + } + + /* no invisible reset implemented */ + + return -EINVAL; +} + static int siena_reset_hw(struct efx_nic *efx, enum reset_type method) { int rc; @@ -605,6 +635,8 @@ const struct efx_nic_type siena_a0_nic_type = { .init = siena_init_nic, .fini = efx_port_dummy_op_void, .monitor = NULL, + .map_reset_reason = siena_map_reset_reason, + .map_reset_flags = siena_map_reset_flags, .reset = siena_reset_hw, .probe_port = siena_probe_port, .remove_port = siena_remove_port, @@ -641,5 +673,4 @@ const struct efx_nic_type siena_a0_nic_type = { .rx_dc_base = 0x68000, .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE), - .reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT, }; From a659b2a94d87add999229ecd9f2f56817d5d737b Mon Sep 17 00:00:00 2001 From: Steve Hodgson Date: Wed, 22 Jun 2011 12:11:33 +0100 Subject: [PATCH 4/7] sfc: Fix Siena mac statistics on big endian platforms [bwh: Use __force in the one place it's needed] Signed-off-by: Ben Hutchings --- drivers/net/sfc/siena.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 442897b14270..5735e84c69de 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c @@ -420,14 +420,13 @@ static void siena_remove_nic(struct efx_nic *efx) efx->nic_data = NULL; } -#define STATS_GENERATION_INVALID ((u64)(-1)) +#define STATS_GENERATION_INVALID ((__force __le64)(-1)) static int siena_try_update_nic_stats(struct efx_nic *efx) { - u64 *dma_stats; + __le64 *dma_stats; struct efx_mac_stats *mac_stats; - u64 generation_start; - u64 generation_end; + __le64 generation_start, generation_end; mac_stats = &efx->mac_stats; dma_stats = efx->stats_buffer.addr; @@ -438,7 +437,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx) rmb(); #define MAC_STAT(M, D) \ - mac_stats->M = dma_stats[MC_CMD_MAC_ ## D] + mac_stats->M = le64_to_cpu(dma_stats[MC_CMD_MAC_ ## D]) MAC_STAT(tx_bytes, TX_BYTES); MAC_STAT(tx_bad_bytes, TX_BAD_BYTES); @@ -508,7 +507,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx) MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS); mac_stats->rx_good_lt64 = 0; - efx->n_rx_nodesc_drop_cnt = dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]; + efx->n_rx_nodesc_drop_cnt = + le64_to_cpu(dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]); #undef MAC_STAT @@ -537,7 +537,7 @@ static void siena_update_nic_stats(struct efx_nic *efx) static void siena_start_nic_stats(struct efx_nic *efx) { - u64 *dma_stats = (u64 *)efx->stats_buffer.addr; + __le64 *dma_stats = efx->stats_buffer.addr; dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID; From 589327905cf0ce4402f7fb1ed29682f7ae68a82e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 25 Jun 2011 00:22:08 +0100 Subject: [PATCH 5/7] sfc: Fix assertions in efx_filter_rfs() This function is intended to assert (when DEBUG is defined) that the skb header area includes the header fields it's looking at, which RFS should already have pulled. But it uses pskb_may_pull(), which will attempt to pull more data if necesary. It must instead compare skb_headlen() with the required length. Signed-off-by: Ben Hutchings --- drivers/net/sfc/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c index 054f0a3d45a9..2b9636f96e05 100644 --- a/drivers/net/sfc/filter.c +++ b/drivers/net/sfc/filter.c @@ -657,11 +657,11 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb, return -EPROTONOSUPPORT; /* RFS must validate the IP header length before calling us */ - EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + sizeof(*ip))); + EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip)); ip = (const struct iphdr *)(skb->data + nhoff); if (ip_is_fragment(ip)) return -EPROTONOSUPPORT; - EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + 4 * ip->ihl + 4)); + EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4); ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl); efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index); From 851f186835c850cf51001369e4e22c0f9241e745 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Jul 2011 16:10:02 +0100 Subject: [PATCH 6/7] sfc: Remove 'Solarstorm' from Kconfig descriptions The 'Solarstorm' brand is being retired and it's redundant with the company name. Signed-off-by: Ben Hutchings --- drivers/net/sfc/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig index a65c98638398..db7b22eb686a 100644 --- a/drivers/net/sfc/Kconfig +++ b/drivers/net/sfc/Kconfig @@ -1,5 +1,5 @@ config SFC - tristate "Solarflare Solarstorm SFC4000/SFC9000-family support" + tristate "Solarflare SFC4000/SFC9000-family support" depends on PCI && INET select MDIO select CRC32 @@ -7,13 +7,13 @@ config SFC select I2C_ALGOBIT help This driver supports 10-gigabit Ethernet cards based on - the Solarflare Communications Solarstorm SFC4000 and - SFC9000-family controllers. + the Solarflare Communications SFC4000 and SFC9000-family + controllers. To compile this driver as a module, choose M here. The module will be called sfc. config SFC_MTD - bool "Solarflare Solarstorm SFC4000/SFC9000-family MTD support" + bool "Solarflare SFC4000/SFC9000-family MTD support" depends on SFC && MTD && !(SFC=y && MTD=m) default y help From ff79c8ac40a115adf5d94e1349f4a379ae156f55 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Jul 2011 16:21:24 +0100 Subject: [PATCH 7/7] sfc: Remove 'Communications' after 'Solarflare' in references to hardware Branding can now be abbreviated. Signed-off-by: Ben Hutchings --- drivers/net/sfc/Kconfig | 3 +-- drivers/net/sfc/efx.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig index db7b22eb686a..a3d5bb9e39dc 100644 --- a/drivers/net/sfc/Kconfig +++ b/drivers/net/sfc/Kconfig @@ -7,8 +7,7 @@ config SFC select I2C_ALGOBIT help This driver supports 10-gigabit Ethernet cards based on - the Solarflare Communications SFC4000 and SFC9000-family - controllers. + the Solarflare SFC4000 and SFC9000-family controllers. To compile this driver as a module, choose M here. The module will be called sfc. diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index ff162df06bd0..faca764aa21b 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -2476,7 +2476,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, goto fail1; netif_info(efx, probe, efx->net_dev, - "Solarflare Communications NIC detected\n"); + "Solarflare NIC detected\n"); /* Set up basic I/O (BAR mappings etc) */ rc = efx_init_io(efx);