diff options
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.h | 2 |
2 files changed, 15 insertions, 6 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 381063484ee4..63121adbc3bb 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -26,9 +26,10 @@ /* A reboot/assertion causes the MCDI status word to be set after the * command word is set or a REBOOT event is sent. If we notice a reboot - * via these mechanisms then wait 10ms for the status word to be set. */ + * via these mechanisms then wait 20ms for the status word to be set. + */ #define MCDI_STATUS_DELAY_US 100 -#define MCDI_STATUS_DELAY_COUNT 100 +#define MCDI_STATUS_DELAY_COUNT 200 #define MCDI_STATUS_SLEEP_MS \ (MCDI_STATUS_DELAY_US * MCDI_STATUS_DELAY_COUNT / 1000) @@ -56,6 +57,7 @@ int efx_mcdi_init(struct efx_nic *efx) mcdi->mode = MCDI_MODE_POLL; (void) efx_mcdi_poll_reboot(efx); + mcdi->new_epoch = true; /* Recover from a failed assertion before probing */ return efx_mcdi_handle_assertion(efx); @@ -85,24 +87,26 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd, if (efx->type->mcdi_max_ver == 1) { /* MCDI v1 */ - EFX_POPULATE_DWORD_6(hdr[0], + EFX_POPULATE_DWORD_7(hdr[0], MCDI_HEADER_RESPONSE, 0, MCDI_HEADER_RESYNC, 1, MCDI_HEADER_CODE, cmd, MCDI_HEADER_DATALEN, inlen, MCDI_HEADER_SEQ, seqno, - MCDI_HEADER_XFLAGS, xflags); + MCDI_HEADER_XFLAGS, xflags, + MCDI_HEADER_NOT_EPOCH, !mcdi->new_epoch); hdr_len = 4; } else { /* MCDI v2 */ BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V2); - EFX_POPULATE_DWORD_6(hdr[0], + EFX_POPULATE_DWORD_7(hdr[0], MCDI_HEADER_RESPONSE, 0, MCDI_HEADER_RESYNC, 1, MCDI_HEADER_CODE, MC_CMD_V2_EXTN, MCDI_HEADER_DATALEN, 0, MCDI_HEADER_SEQ, seqno, - MCDI_HEADER_XFLAGS, xflags); + MCDI_HEADER_XFLAGS, xflags, + MCDI_HEADER_NOT_EPOCH, !mcdi->new_epoch); EFX_POPULATE_DWORD_2(hdr[1], MC_CMD_V2_EXTN_IN_EXTENDED_CMD, cmd, MC_CMD_V2_EXTN_IN_ACTUAL_LEN, inlen); @@ -373,6 +377,7 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, spin_unlock_bh(&mcdi->iface_lock); efx_mcdi_copyin(efx, cmd, inbuf, inlen); + mcdi->new_epoch = false; return 0; } @@ -435,6 +440,7 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, if (rc == -EIO || rc == -EINTR) { msleep(MCDI_STATUS_SLEEP_MS); efx_mcdi_poll_reboot(efx); + mcdi->new_epoch = true; } } @@ -530,6 +536,7 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc) break; udelay(MCDI_STATUS_DELAY_US); } + mcdi->new_epoch = true; } spin_unlock(&mcdi->iface_lock); diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 5f67ac3f2c8a..303d9e88a27f 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -36,6 +36,7 @@ enum efx_mcdi_mode { * @state: Request handling state. Waited for by @wq. * @mode: Poll for mcdi completion, or wait for an mcdi_event. * @wq: Wait queue for threads waiting for @state != %MCDI_STATE_RUNNING + * @new_epoch: Indicates start of day or start of MC reboot recovery * @iface_lock: Serialises access to all the following fields * @seqno: The next sequence number to use for mcdi requests. * @credits: Number of spurious MCDI completion events allowed before we @@ -49,6 +50,7 @@ struct efx_mcdi_iface { enum efx_mcdi_mode mode; wait_queue_head_t wq; spinlock_t iface_lock; + bool new_epoch; unsigned int credits; unsigned int seqno; int resprc; |