When the admin queue command to read NVM returns EBUSY, the driver
currently treats it as a fatal error and aborts the entire read
operation. This can cause spurious NVM read failures during periods of
high firmware activity.
Add retry logic to ice_read_flat_nvm() that handles EBUSY responses
from the admin queue. When an EBUSY error is encountered, release the
NVM resource lock, wait for ICE_SQ_SEND_DELAY_TIME_MS, re-acquire it,
and retry the failed read. The retry is attempted up to
ICE_SQ_SEND_MAX_EXECUTE times before giving up.
Code was extracted from OOT ice driver 1.15.4 release. Additional
change was made to reset last_cmd in case of retry to make sure that
all commands are retried properly.
Fixes: e94509906d6b ("ice: create function to read a section of the NVM and
Shadow RAM")
Signed-off-by: Robert Malz <[email protected]>
---
drivers/net/ethernet/intel/ice/ice_nvm.c | 25 +++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c
b/drivers/net/ethernet/intel/ice/ice_nvm.c
index 7e187a804dfa..cbe21ef9d18e 100644
--- a/drivers/net/ethernet/intel/ice/ice_nvm.c
+++ b/drivers/net/ethernet/intel/ice/ice_nvm.c
@@ -67,6 +67,7 @@ ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length,
u8 *data,
{
u32 inlen = *length;
u32 bytes_read = 0;
+ int retry_cnt = 0;
bool last_cmd;
int status;
@@ -96,11 +97,25 @@ ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32
*length, u8 *data,
offset, read_size,
data + bytes_read, last_cmd,
read_shadow_ram, NULL);
- if (status)
- break;
-
- bytes_read += read_size;
- offset += read_size;
+ if (status) {
+ if (hw->adminq.sq_last_status != ICE_AQ_RC_EBUSY ||
+ retry_cnt > ICE_SQ_SEND_MAX_EXECUTE)
+ break;
+ ice_debug(hw, ICE_DBG_NVM,
+ "NVM read EBUSY error, retry %d\n",
+ retry_cnt + 1);
+ last_cmd = false;
+ ice_release_nvm(hw);
+ msleep(ICE_SQ_SEND_DELAY_TIME_MS);
+ status = ice_acquire_nvm(hw, ICE_RES_READ);
+ if (status)
+ break;
+ retry_cnt++;
+ } else {
+ bytes_read += read_size;
+ offset += read_size;
+ retry_cnt = 0;
+ }
} while (!last_cmd);
*length = bytes_read;
--
2.34.1