diff options
author | Steve Hodgson <shodgson@solarflare.com> | 2010-06-01 07:17:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-02 05:21:06 -0400 |
commit | fd371e32fe53f137a0f940d61772bda92180007b (patch) | |
tree | c2ce5d564aae698ecc643d8af42696e374a60728 /drivers/net/sfc/efx.c | |
parent | 319ba649af30321ea221740833785b46e1fe6af3 (diff) |
sfc: Workaround flush failures on Falcon B0
Under certain conditions a PHY may backpressure Falcon B0
in such a way that flushes timeout. In normal circumstances
the phy poller would fix the PHY, and the flush could complete.
But efx_nic_flush_queues() is always called after efx_stop_all(),
so the poller has been stopped. Even if this weren't the case,
how long would we have to wait for the poller to fix this? And
several callers of efx_nic_flush_queues() are about to reset
the device anyway - so we don't need to do anything.
Work around this bug by scheduling a reset. Ensure that the
MAC is never rewired back into the datapath before the reset
runs (we already ignore all rx events anyway).
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/efx.c')
-rw-r--r-- | drivers/net/sfc/efx.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 0319000379e..d1a1d32e73e 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "nic.h" | 27 | #include "nic.h" |
28 | 28 | ||
29 | #include "mcdi.h" | 29 | #include "mcdi.h" |
30 | #include "workarounds.h" | ||
30 | 31 | ||
31 | /************************************************************************** | 32 | /************************************************************************** |
32 | * | 33 | * |
@@ -556,10 +557,18 @@ static void efx_fini_channels(struct efx_nic *efx) | |||
556 | BUG_ON(efx->port_enabled); | 557 | BUG_ON(efx->port_enabled); |
557 | 558 | ||
558 | rc = efx_nic_flush_queues(efx); | 559 | rc = efx_nic_flush_queues(efx); |
559 | if (rc) | 560 | if (rc && EFX_WORKAROUND_7803(efx)) { |
561 | /* Schedule a reset to recover from the flush failure. The | ||
562 | * descriptor caches reference memory we're about to free, | ||
563 | * but falcon_reconfigure_mac_wrapper() won't reconnect | ||
564 | * the MACs because of the pending reset. */ | ||
565 | EFX_ERR(efx, "Resetting to recover from flush failure\n"); | ||
566 | efx_schedule_reset(efx, RESET_TYPE_ALL); | ||
567 | } else if (rc) { | ||
560 | EFX_ERR(efx, "failed to flush queues\n"); | 568 | EFX_ERR(efx, "failed to flush queues\n"); |
561 | else | 569 | } else { |
562 | EFX_LOG(efx, "successfully flushed all queues\n"); | 570 | EFX_LOG(efx, "successfully flushed all queues\n"); |
571 | } | ||
563 | 572 | ||
564 | efx_for_each_channel(channel, efx) { | 573 | efx_for_each_channel(channel, efx) { |
565 | EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel); | 574 | EFX_LOG(channel->efx, "shut down chan %d\n", channel->channel); |