summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Stonehouse <rstonehouse@solarflare.com>2013-10-09 11:52:48 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-15 15:31:39 -0800
commit702a3e12068917c504f0f6e4b86d87ca553f5566 (patch)
tree3b312b88c5926b9817f17db3c566c79aff4826b7
parentd8203f8f29bae8d1beffa6faf0db4b1350177af2 (diff)
sfc: Poll for MCDI completion once before timeout occurs
[ Upstream commit 6b294b8efedaa7cf7507154148e2c79766ad6f96 ] There is an as-yet unexplained bug that sometimes prevents (or delays) the driver seeing the completion event for a completed MCDI request on the SFC9120. The requested configuration change will have happened but the driver assumes it to have failed, and this can result in further failures. We can mitigate this by polling for completion after unsuccessfully waiting for an event. Fixes: 8127d661e77f ('sfc: Add support for Solarflare SFC9100 family') Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 9f26e46ee283..4b0bd8a1514d 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -630,6 +630,16 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
rc = efx_mcdi_await_completion(efx);
if (rc != 0) {
+ netif_err(efx, hw, efx->net_dev,
+ "MC command 0x%x inlen %d mode %d timed out\n",
+ cmd, (int)inlen, mcdi->mode);
+
+ if (mcdi->mode == MCDI_MODE_EVENTS && efx_mcdi_poll_once(efx)) {
+ netif_err(efx, hw, efx->net_dev,
+ "MCDI request was completed without an event\n");
+ rc = 0;
+ }
+
/* Close the race with efx_mcdi_ev_cpl() executing just too late
* and completing a request we've just cancelled, by ensuring
* that the seqno check therein fails.
@@ -638,11 +648,9 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
++mcdi->seqno;
++mcdi->credits;
spin_unlock_bh(&mcdi->iface_lock);
+ }
- netif_err(efx, hw, efx->net_dev,
- "MC command 0x%x inlen %d mode %d timed out\n",
- cmd, (int)inlen, mcdi->mode);
- } else {
+ if (rc == 0) {
size_t hdr_len, data_len;
/* At the very least we need a memory barrier here to ensure