diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index ed3902bf249b3e4ceb047ed14762d6ea50b1a4c0..34415d342ece381a97755b051f68945b254303b8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -32,6 +32,16 @@ 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 * @hw: pointer to the hardware structure @@ -585,6 +595,7 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) /* pre-emptive resource lock release */ 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, I40E_HMC_PROFILE_DEFAULT, @@ -708,6 +719,12 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, 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); if (cmd_details) { *details = *cmd_details; @@ -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; } + if (i40e_is_nvm_update_op(desc)) + hw->aq.nvm_busy = true; + /* update the error if time out occurred */ if ((!cmd_completed) && (!details->async && !details->postpone)) { @@ -929,6 +949,9 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw, 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, * FW updates datalen to indicate the event message * size diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index 993f7685a9111694726c1a9bee44f3653651df72..b1552fbc48a0e6876acf838ab7eadf1e72fe492e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -90,6 +90,7 @@ struct i40e_adminq_info { u16 fw_min_ver; /* firmware minor version */ u16 api_maj_ver; /* api major version */ u16 api_min_ver; /* api minor version */ + bool nvm_busy; struct mutex asq_mutex; /* Send queue lock */ struct mutex arq_mutex; /* Receive queue lock */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index 5470ce95936ed483abc547f1ef12b1ef30a34721..c79df257f830d7791580b81ae68028d8ee18d65e 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -27,6 +27,16 @@ #include "i40e_adminq.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 * @hw: pointer to the hardware structure @@ -659,6 +669,12 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, 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); if (cmd_details) { *details = *cmd_details; @@ -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; } + if (i40e_is_nvm_update_op(desc)) + hw->aq.nvm_busy = true; + /* update the error if time out occurred */ if ((!cmd_completed) && (!details->async && !details->postpone)) { @@ -880,6 +899,9 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw, 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, * FW updates datalen to indicate the event message * size diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h index 8f72c31d95cc85adafac60190967de3f607b4bd6..7d24be528601c990e97307c7b0663cd7b66273cf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h @@ -87,6 +87,7 @@ struct i40e_adminq_info { u16 fw_min_ver; /* firmware minor version */ u16 api_maj_ver; /* api major version */ u16 api_min_ver; /* api minor version */ + bool nvm_busy; struct mutex asq_mutex; /* Send queue lock */ struct mutex arq_mutex; /* Receive queue lock */