forked from Minki/linux
i40e: catch NVM write semaphore timeout and retry
In some circumstances, a multi-write transaction takes longer than the default 3 minute timeout on the write semaphore. If the write failed with an EBUSY status, this is likely the problem, so here we try to reacquire the semaphore then retry the write. We only do one retry, then give up. Change-ID: I1c8be60688acc2f39573839579baf601207c4a36 Signed-off-by: Shannon Nelson <shannon.nelson@intel.com> Tested-by: Jim Young <james.m.young@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
33c62b34e5
commit
2c47e351f6
@ -679,9 +679,11 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
|
|||||||
{
|
{
|
||||||
i40e_status status;
|
i40e_status status;
|
||||||
enum i40e_nvmupd_cmd upd_cmd;
|
enum i40e_nvmupd_cmd upd_cmd;
|
||||||
|
bool retry_attempt = false;
|
||||||
|
|
||||||
upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
|
upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
|
||||||
|
|
||||||
|
retry:
|
||||||
switch (upd_cmd) {
|
switch (upd_cmd) {
|
||||||
case I40E_NVMUPD_WRITE_CON:
|
case I40E_NVMUPD_WRITE_CON:
|
||||||
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
|
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
|
||||||
@ -725,6 +727,39 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
|
|||||||
*errno = -ESRCH;
|
*errno = -ESRCH;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In some circumstances, a multi-write transaction takes longer
|
||||||
|
* than the default 3 minute timeout on the write semaphore. If
|
||||||
|
* the write failed with an EBUSY status, this is likely the problem,
|
||||||
|
* so here we try to reacquire the semaphore then retry the write.
|
||||||
|
* We only do one retry, then give up.
|
||||||
|
*/
|
||||||
|
if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) &&
|
||||||
|
!retry_attempt) {
|
||||||
|
i40e_status old_status = status;
|
||||||
|
u32 old_asq_status = hw->aq.asq_last_status;
|
||||||
|
u32 gtime;
|
||||||
|
|
||||||
|
gtime = rd32(hw, I40E_GLVFGEN_TIMER);
|
||||||
|
if (gtime >= hw->nvm.hw_semaphore_timeout) {
|
||||||
|
i40e_debug(hw, I40E_DEBUG_ALL,
|
||||||
|
"NVMUPD: write semaphore expired (%d >= %lld), retrying\n",
|
||||||
|
gtime, hw->nvm.hw_semaphore_timeout);
|
||||||
|
i40e_release_nvm(hw);
|
||||||
|
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
|
||||||
|
if (status) {
|
||||||
|
i40e_debug(hw, I40E_DEBUG_ALL,
|
||||||
|
"NVMUPD: write semaphore reacquire failed aq_err = %d\n",
|
||||||
|
hw->aq.asq_last_status);
|
||||||
|
status = old_status;
|
||||||
|
hw->aq.asq_last_status = old_asq_status;
|
||||||
|
} else {
|
||||||
|
retry_attempt = true;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user