summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc/mcdi.c
diff options
context:
space:
mode:
authorJon Cooper <jcooper@solarflare.com>2013-09-16 15:18:51 +0200
committerBen Hutchings <bhutchings@solarflare.com>2013-12-12 23:05:48 +0100
commit74cd60a4d7b4f686146efd7ed211974691f0c2c1 (patch)
treed6454c540ab6a192f8147173e3cf73e669de28c4 /drivers/net/ethernet/sfc/mcdi.c
parentsfc: Update MCDI protocol definitions (diff)
downloadlinux-74cd60a4d7b4f686146efd7ed211974691f0c2c1.tar.xz
linux-74cd60a4d7b4f686146efd7ed211974691f0c2c1.zip
sfc: Add MC BISTs to ethtool offline self test on EF10
To run BISTs the MC goes down in to a special mode where it will only respond to MCDI from the testing PF, and TX, RX and event queues are torn down. Other PFs get a message as it goes down to tell them it's going down. When the other PFs get this message, they check the soft status register to tell when the MC has rebooted after BIST mode and they can start recovery. [bwh: Convert the test result to 1 or -1 as for earlier NICs] Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc/mcdi.c')
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 25f91c0ca6a6..da14e2428944 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -543,6 +543,9 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
if (rc)
return rc;
+ if (efx->mc_bist_for_other_fn)
+ return -ENETDOWN;
+
efx_mcdi_acquire_sync(mcdi);
efx_mcdi_send_request(efx, cmd, inbuf, inlen);
return 0;
@@ -581,6 +584,9 @@ efx_mcdi_rpc_async(struct efx_nic *efx, unsigned int cmd,
if (rc)
return rc;
+ if (efx->mc_bist_for_other_fn)
+ return -ENETDOWN;
+
async = kmalloc(sizeof(*async) + ALIGN(max(inlen, outlen), 4),
GFP_ATOMIC);
if (!async)
@@ -834,6 +840,30 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
spin_unlock(&mcdi->iface_lock);
}
+/* The MC is going down in to BIST mode. set the BIST flag to block
+ * new MCDI, cancel any outstanding MCDI and and schedule a BIST-type reset
+ * (which doesn't actually execute a reset, it waits for the controlling
+ * function to reset it).
+ */
+static void efx_mcdi_ev_bist(struct efx_nic *efx)
+{
+ struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+ spin_lock(&mcdi->iface_lock);
+ efx->mc_bist_for_other_fn = true;
+ if (efx_mcdi_complete_sync(mcdi)) {
+ if (mcdi->mode == MCDI_MODE_EVENTS) {
+ mcdi->resprc = -EIO;
+ mcdi->resp_hdr_len = 0;
+ mcdi->resp_data_len = 0;
+ ++mcdi->credits;
+ }
+ }
+ mcdi->new_epoch = true;
+ efx_schedule_reset(efx, RESET_TYPE_MC_BIST);
+ spin_unlock(&mcdi->iface_lock);
+}
+
/* Called from falcon_process_eventq for MCDI events */
void efx_mcdi_process_event(struct efx_channel *channel,
efx_qword_t *event)
@@ -875,6 +905,10 @@ void efx_mcdi_process_event(struct efx_channel *channel,
netif_info(efx, hw, efx->net_dev, "MC Reboot\n");
efx_mcdi_ev_death(efx, -EIO);
break;
+ case MCDI_EVENT_CODE_MC_BIST:
+ netif_info(efx, hw, efx->net_dev, "MC entered BIST mode\n");
+ efx_mcdi_ev_bist(efx);
+ break;
case MCDI_EVENT_CODE_MAC_STATS_DMA:
/* MAC stats are gather lazily. We can ignore this. */
break;