diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_nvm.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_nvm.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 3e70f2e45a47..5defe0d63514 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c | |||
@@ -679,9 +679,11 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, | |||
679 | { | 679 | { |
680 | i40e_status status; | 680 | i40e_status status; |
681 | enum i40e_nvmupd_cmd upd_cmd; | 681 | enum i40e_nvmupd_cmd upd_cmd; |
682 | bool retry_attempt = false; | ||
682 | 683 | ||
683 | upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); | 684 | upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); |
684 | 685 | ||
686 | retry: | ||
685 | switch (upd_cmd) { | 687 | switch (upd_cmd) { |
686 | case I40E_NVMUPD_WRITE_CON: | 688 | case I40E_NVMUPD_WRITE_CON: |
687 | status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); | 689 | status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); |
@@ -725,6 +727,39 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, | |||
725 | *errno = -ESRCH; | 727 | *errno = -ESRCH; |
726 | break; | 728 | break; |
727 | } | 729 | } |
730 | |||
731 | /* In some circumstances, a multi-write transaction takes longer | ||
732 | * than the default 3 minute timeout on the write semaphore. If | ||
733 | * the write failed with an EBUSY status, this is likely the problem, | ||
734 | * so here we try to reacquire the semaphore then retry the write. | ||
735 | * We only do one retry, then give up. | ||
736 | */ | ||
737 | if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) && | ||
738 | !retry_attempt) { | ||
739 | i40e_status old_status = status; | ||
740 | u32 old_asq_status = hw->aq.asq_last_status; | ||
741 | u32 gtime; | ||
742 | |||
743 | gtime = rd32(hw, I40E_GLVFGEN_TIMER); | ||
744 | if (gtime >= hw->nvm.hw_semaphore_timeout) { | ||
745 | i40e_debug(hw, I40E_DEBUG_ALL, | ||
746 | "NVMUPD: write semaphore expired (%d >= %lld), retrying\n", | ||
747 | gtime, hw->nvm.hw_semaphore_timeout); | ||
748 | i40e_release_nvm(hw); | ||
749 | status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); | ||
750 | if (status) { | ||
751 | i40e_debug(hw, I40E_DEBUG_ALL, | ||
752 | "NVMUPD: write semaphore reacquire failed aq_err = %d\n", | ||
753 | hw->aq.asq_last_status); | ||
754 | status = old_status; | ||
755 | hw->aq.asq_last_status = old_asq_status; | ||
756 | } else { | ||
757 | retry_attempt = true; | ||
758 | goto retry; | ||
759 | } | ||
760 | } | ||
761 | } | ||
762 | |||
728 | return status; | 763 | return status; |
729 | } | 764 | } |
730 | 765 | ||