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 28429c8fbc98..039018abad4a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c | |||
@@ -725,9 +725,11 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, | |||
725 | { | 725 | { |
726 | i40e_status status; | 726 | i40e_status status; |
727 | enum i40e_nvmupd_cmd upd_cmd; | 727 | enum i40e_nvmupd_cmd upd_cmd; |
728 | bool retry_attempt = false; | ||
728 | 729 | ||
729 | upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); | 730 | upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); |
730 | 731 | ||
732 | retry: | ||
731 | switch (upd_cmd) { | 733 | switch (upd_cmd) { |
732 | case I40E_NVMUPD_WRITE_CON: | 734 | case I40E_NVMUPD_WRITE_CON: |
733 | status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); | 735 | status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); |
@@ -771,6 +773,39 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, | |||
771 | *errno = -ESRCH; | 773 | *errno = -ESRCH; |
772 | break; | 774 | break; |
773 | } | 775 | } |
776 | |||
777 | /* In some circumstances, a multi-write transaction takes longer | ||
778 | * than the default 3 minute timeout on the write semaphore. If | ||
779 | * the write failed with an EBUSY status, this is likely the problem, | ||
780 | * so here we try to reacquire the semaphore then retry the write. | ||
781 | * We only do one retry, then give up. | ||
782 | */ | ||
783 | if (status && (hw->aq.asq_last_status == I40E_AQ_RC_EBUSY) && | ||
784 | !retry_attempt) { | ||
785 | i40e_status old_status = status; | ||
786 | u32 old_asq_status = hw->aq.asq_last_status; | ||
787 | u32 gtime; | ||
788 | |||
789 | gtime = rd32(hw, I40E_GLVFGEN_TIMER); | ||
790 | if (gtime >= hw->nvm.hw_semaphore_timeout) { | ||
791 | i40e_debug(hw, I40E_DEBUG_ALL, | ||
792 | "NVMUPD: write semaphore expired (%d >= %lld), retrying\n", | ||
793 | gtime, hw->nvm.hw_semaphore_timeout); | ||
794 | i40e_release_nvm(hw); | ||
795 | status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); | ||
796 | if (status) { | ||
797 | i40e_debug(hw, I40E_DEBUG_ALL, | ||
798 | "NVMUPD: write semaphore reacquire failed aq_err = %d\n", | ||
799 | hw->aq.asq_last_status); | ||
800 | status = old_status; | ||
801 | hw->aq.asq_last_status = old_asq_status; | ||
802 | } else { | ||
803 | retry_attempt = true; | ||
804 | goto retry; | ||
805 | } | ||
806 | } | ||
807 | } | ||
808 | |||
774 | return status; | 809 | return status; |
775 | } | 810 | } |
776 | 811 | ||