Commit c9296ad2 authored by Shannon Nelson's avatar Shannon Nelson Committed by Jeff Kirsher

i40e/i40evf: add tracking to NVM busy state

The NVM updates take some time and are asynchronous actions that signal
their completion with an AdminQ event.  This code tracks when there is
an NVM update outstanding and won't allow a new update command until a
completion event is received from the current update.

Change-ID: Ic132fe16bd9dc09b002ed38297a877c1a01553ce
Signed-off-by: default avatarShannon Nelson <shannon.nelson@intel.com>
Acked-by: default avatarMitch Williams <mitch.a.williams@intel.com>
Acked-by: default avatarGreg Rose <gregory.v.rose@intel.com>
Tested-by: default avatarKavindya Deegala <kavindya.s.deegala@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 7d54eb2c
...@@ -32,6 +32,16 @@ ...@@ -32,6 +32,16 @@
static void i40e_resume_aq(struct i40e_hw *hw); static void i40e_resume_aq(struct i40e_hw *hw);
/**
* i40e_is_nvm_update_op - return true if this is an NVM update operation
* @desc: API request descriptor
**/
static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc)
{
return (desc->opcode == i40e_aqc_opc_nvm_erase) ||
(desc->opcode == i40e_aqc_opc_nvm_update);
}
/** /**
* i40e_adminq_init_regs - Initialize AdminQ registers * i40e_adminq_init_regs - Initialize AdminQ registers
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
...@@ -585,6 +595,7 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) ...@@ -585,6 +595,7 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
/* pre-emptive resource lock release */ /* pre-emptive resource lock release */
i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL); i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
hw->aq.nvm_busy = false;
ret_code = i40e_aq_set_hmc_resource_profile(hw, ret_code = i40e_aq_set_hmc_resource_profile(hw,
I40E_HMC_PROFILE_DEFAULT, I40E_HMC_PROFILE_DEFAULT,
...@@ -708,6 +719,12 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, ...@@ -708,6 +719,12 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
goto asq_send_command_exit; goto asq_send_command_exit;
} }
if (i40e_is_nvm_update_op(desc) && hw->aq.nvm_busy) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: NVM busy.\n");
status = I40E_ERR_NVM;
goto asq_send_command_exit;
}
details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
if (cmd_details) { if (cmd_details) {
*details = *cmd_details; *details = *cmd_details;
...@@ -835,6 +852,9 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, ...@@ -835,6 +852,9 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval; hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
} }
if (i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
/* update the error if time out occurred */ /* update the error if time out occurred */
if ((!cmd_completed) && if ((!cmd_completed) &&
(!details->async && !details->postpone)) { (!details->async && !details->postpone)) {
...@@ -929,6 +949,9 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, ...@@ -929,6 +949,9 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
e->msg_size); e->msg_size);
} }
if (i40e_is_nvm_update_op(&e->desc))
hw->aq.nvm_busy = false;
/* Restore the original datalen and buffer address in the desc, /* Restore the original datalen and buffer address in the desc,
* FW updates datalen to indicate the event message * FW updates datalen to indicate the event message
* size * size
......
...@@ -90,6 +90,7 @@ struct i40e_adminq_info { ...@@ -90,6 +90,7 @@ struct i40e_adminq_info {
u16 fw_min_ver; /* firmware minor version */ u16 fw_min_ver; /* firmware minor version */
u16 api_maj_ver; /* api major version */ u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */ u16 api_min_ver; /* api minor version */
bool nvm_busy;
struct mutex asq_mutex; /* Send queue lock */ struct mutex asq_mutex; /* Send queue lock */
struct mutex arq_mutex; /* Receive queue lock */ struct mutex arq_mutex; /* Receive queue lock */
......
...@@ -27,6 +27,16 @@ ...@@ -27,6 +27,16 @@
#include "i40e_adminq.h" #include "i40e_adminq.h"
#include "i40e_prototype.h" #include "i40e_prototype.h"
/**
* i40e_is_nvm_update_op - return true if this is an NVM update operation
* @desc: API request descriptor
**/
static inline bool i40e_is_nvm_update_op(struct i40e_aq_desc *desc)
{
return (desc->opcode == i40e_aqc_opc_nvm_erase) ||
(desc->opcode == i40e_aqc_opc_nvm_update);
}
/** /**
* i40e_adminq_init_regs - Initialize AdminQ registers * i40e_adminq_init_regs - Initialize AdminQ registers
* @hw: pointer to the hardware structure * @hw: pointer to the hardware structure
...@@ -659,6 +669,12 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, ...@@ -659,6 +669,12 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
goto asq_send_command_exit; goto asq_send_command_exit;
} }
if (i40e_is_nvm_update_op(desc) && hw->aq.nvm_busy) {
i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, "AQTX: NVM busy.\n");
status = I40E_ERR_NVM;
goto asq_send_command_exit;
}
details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use);
if (cmd_details) { if (cmd_details) {
*details = *cmd_details; *details = *cmd_details;
...@@ -786,6 +802,9 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, ...@@ -786,6 +802,9 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw,
hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval; hw->aq.asq_last_status = (enum i40e_admin_queue_err)retval;
} }
if (i40e_is_nvm_update_op(desc))
hw->aq.nvm_busy = true;
/* update the error if time out occurred */ /* update the error if time out occurred */
if ((!cmd_completed) && if ((!cmd_completed) &&
(!details->async && !details->postpone)) { (!details->async && !details->postpone)) {
...@@ -880,6 +899,9 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw, ...@@ -880,6 +899,9 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
e->msg_size); e->msg_size);
} }
if (i40e_is_nvm_update_op(&e->desc))
hw->aq.nvm_busy = false;
/* Restore the original datalen and buffer address in the desc, /* Restore the original datalen and buffer address in the desc,
* FW updates datalen to indicate the event message * FW updates datalen to indicate the event message
* size * size
......
...@@ -87,6 +87,7 @@ struct i40e_adminq_info { ...@@ -87,6 +87,7 @@ struct i40e_adminq_info {
u16 fw_min_ver; /* firmware minor version */ u16 fw_min_ver; /* firmware minor version */
u16 api_maj_ver; /* api major version */ u16 api_maj_ver; /* api major version */
u16 api_min_ver; /* api minor version */ u16 api_min_ver; /* api minor version */
bool nvm_busy;
struct mutex asq_mutex; /* Send queue lock */ struct mutex asq_mutex; /* Send queue lock */
struct mutex arq_mutex; /* Receive queue lock */ struct mutex arq_mutex; /* Receive queue lock */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment