net/i40e/base: enable AQ event get in NVM update
authorQi Zhang <qi.z.zhang@intel.com>
Tue, 9 Jan 2018 20:30:12 +0000 (15:30 -0500)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 16 Jan 2018 17:47:49 +0000 (18:47 +0100)
This patch adds new I40E_NVMUPD_GET_AQ_EVENT state
to allow retrieval of AdminQ events as a result.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Beilei Xing <beilei.xing@intel.com>
drivers/net/i40e/base/i40e_adminq.c
drivers/net/i40e/base/i40e_nvm.c
drivers/net/i40e/base/i40e_prototype.h
drivers/net/i40e/base/i40e_type.h

index bfa8ca9..9859e53 100644 (file)
@@ -1143,7 +1143,7 @@ enum i40e_status_code i40e_clean_arq_element(struct i40e_hw *hw,
        hw->aq.arq.next_to_use = ntu;
 
 #ifdef PF_DRIVER
-       i40e_nvmupd_check_wait_event(hw, LE16_TO_CPU(e->desc.opcode));
+       i40e_nvmupd_check_wait_event(hw, LE16_TO_CPU(e->desc.opcode), &e->desc);
 #endif /* PF_DRIVER */
 clean_arq_element_out:
        /* Set pending if needed, unlock and return */
index 773ccf5..c77dac0 100644 (file)
@@ -790,6 +790,9 @@ STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
 STATIC enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
                                                    struct i40e_nvm_access *cmd,
                                                    u8 *bytes, int *perrno);
+STATIC enum i40e_status_code i40e_nvmupd_get_aq_event(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno);
 STATIC INLINE u8 i40e_nvmupd_get_module(u32 val)
 {
        return (u8)(val & I40E_NVM_MOD_PNT_MASK);
@@ -822,6 +825,7 @@ STATIC const char *i40e_nvm_update_state_str[] = {
        "I40E_NVMUPD_STATUS",
        "I40E_NVMUPD_EXEC_AQ",
        "I40E_NVMUPD_GET_AQ_RESULT",
+       "I40E_NVMUPD_GET_AQ_EVENT",
 };
 
 /**
@@ -919,9 +923,9 @@ enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
                 * the wait info and return before doing anything else
                 */
                if (cmd->offset == 0xffff) {
-                       i40e_nvmupd_check_wait_event(hw, hw->nvm_wait_opcode);
+                       i40e_nvmupd_clear_wait_state(hw);
                        status = I40E_SUCCESS;
-                       goto exit;
+                       break;
                }
 
                status = I40E_ERR_NOT_READY;
@@ -936,7 +940,7 @@ enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
                *perrno = -ESRCH;
                break;
        }
-exit:
+
        i40e_release_spinlock(&hw->aq.arq_spinlock);
        return status;
 }
@@ -1067,6 +1071,10 @@ STATIC enum i40e_status_code i40e_nvmupd_state_init(struct i40e_hw *hw,
                status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno);
                break;
 
+       case I40E_NVMUPD_GET_AQ_EVENT:
+               status = i40e_nvmupd_get_aq_event(hw, cmd, bytes, perrno);
+               break;
+
        default:
                i40e_debug(hw, I40E_DEBUG_NVM,
                           "NVMUPD: bad cmd %s in init state\n",
@@ -1245,39 +1253,55 @@ retry:
 }
 
 /**
- * i40e_nvmupd_check_wait_event - handle NVM update operation events
+ * i40e_nvmupd_clear_wait_state - clear wait state on hw
  * @hw: pointer to the hardware structure
- * @opcode: the event that just happened
  **/
-void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode)
+void i40e_nvmupd_clear_wait_state(struct i40e_hw *hw)
 {
-       if (opcode == hw->nvm_wait_opcode) {
+       i40e_debug(hw, I40E_DEBUG_NVM,
+                  "NVMUPD: clearing wait on opcode 0x%04x\n",
+                  hw->nvm_wait_opcode);
 
-               i40e_debug(hw, I40E_DEBUG_NVM,
-                          "NVMUPD: clearing wait on opcode 0x%04x\n", opcode);
-               if (hw->nvm_release_on_done) {
-                       i40e_release_nvm(hw);
-                       hw->nvm_release_on_done = false;
-               }
-               hw->nvm_wait_opcode = 0;
+       if (hw->nvm_release_on_done) {
+               i40e_release_nvm(hw);
+               hw->nvm_release_on_done = false;
+       }
+       hw->nvm_wait_opcode = 0;
 
-               if (hw->aq.arq_last_status) {
-                       hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
-                       return;
-               }
+       if (hw->aq.arq_last_status) {
+               hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
+               return;
+       }
 
-               switch (hw->nvmupd_state) {
-               case I40E_NVMUPD_STATE_INIT_WAIT:
-                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
-                       break;
+       switch (hw->nvmupd_state) {
+       case I40E_NVMUPD_STATE_INIT_WAIT:
+               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               break;
 
-               case I40E_NVMUPD_STATE_WRITE_WAIT:
-                       hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
-                       break;
+       case I40E_NVMUPD_STATE_WRITE_WAIT:
+               hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
+               break;
 
-               default:
-                       break;
-               }
+       default:
+               break;
+       }
+}
+
+/**
+ * i40e_nvmupd_check_wait_event - handle NVM update operation events
+ * @hw: pointer to the hardware structure
+ * @opcode: the event that just happened
+ * @desc: AdminQ descriptor
+ **/
+void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode,
+                                 struct i40e_aq_desc *desc)
+{
+       u32 aq_desc_len = sizeof(struct i40e_aq_desc);
+
+       if (opcode == hw->nvm_wait_opcode) {
+               i40e_memcpy(&hw->nvm_aq_event_desc, desc,
+                           aq_desc_len, I40E_NONDMA_TO_NONDMA);
+               i40e_nvmupd_clear_wait_state(hw);
        }
 }
 
@@ -1335,6 +1359,9 @@ STATIC enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
                        else if (module == 0)
                                upd_cmd = I40E_NVMUPD_GET_AQ_RESULT;
                        break;
+               case I40E_NVM_AQE:
+                       upd_cmd = I40E_NVMUPD_GET_AQ_EVENT;
+                       break;
                }
                break;
 
@@ -1397,6 +1424,9 @@ STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
        u32 aq_data_len;
 
        i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+       if (cmd->offset == 0xffff)
+               return I40E_SUCCESS;
+
        memset(&cmd_details, 0, sizeof(cmd_details));
        cmd_details.wb_desc = &hw->nvm_wb_desc;
 
@@ -1433,6 +1463,9 @@ STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
                }
        }
 
+       if (cmd->offset)
+               memset(&hw->nvm_aq_event_desc, 0, aq_desc_len);
+
        /* and away we go! */
        status = i40e_asq_send_command(hw, aq_desc, buff,
                                       buff_size, &cmd_details);
@@ -1442,6 +1475,7 @@ STATIC enum i40e_status_code i40e_nvmupd_exec_aq(struct i40e_hw *hw,
                           i40e_stat_str(hw, status),
                           i40e_aq_str(hw, hw->aq.asq_last_status));
                *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
+               return status;
        }
 
        /* should we wait for a followup event? */
@@ -1522,6 +1556,41 @@ STATIC enum i40e_status_code i40e_nvmupd_get_aq_result(struct i40e_hw *hw,
        return I40E_SUCCESS;
 }
 
+/**
+ * i40e_nvmupd_get_aq_event - Get the Admin Queue event from previous exec_aq
+ * @hw: pointer to hardware structure
+ * @cmd: pointer to nvm update command buffer
+ * @bytes: pointer to the data buffer
+ * @perrno: pointer to return error code
+ *
+ * cmd structure contains identifiers and data buffer
+ **/
+STATIC enum i40e_status_code i40e_nvmupd_get_aq_event(struct i40e_hw *hw,
+                                                   struct i40e_nvm_access *cmd,
+                                                   u8 *bytes, int *perrno)
+{
+       u32 aq_total_len;
+       u32 aq_desc_len;
+
+       i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__);
+
+       aq_desc_len = sizeof(struct i40e_aq_desc);
+       aq_total_len = aq_desc_len + LE16_TO_CPU(hw->nvm_aq_event_desc.datalen);
+
+       /* check copylength range */
+       if (cmd->data_size > aq_total_len) {
+               i40e_debug(hw, I40E_DEBUG_NVM,
+                          "%s: copy length %d too big, trimming to %d\n",
+                          __func__, cmd->data_size, aq_total_len);
+               cmd->data_size = aq_total_len;
+       }
+
+       i40e_memcpy(bytes, &hw->nvm_aq_event_desc, cmd->data_size,
+                   I40E_NONDMA_TO_NONDMA);
+
+       return I40E_SUCCESS;
+}
+
 /**
  * i40e_nvmupd_nvm_read - Read NVM
  * @hw: pointer to hardware structure
index d16bbf7..c6ec2d7 100644 (file)
@@ -487,7 +487,9 @@ enum i40e_status_code i40e_validate_nvm_checksum(struct i40e_hw *hw,
 enum i40e_status_code i40e_nvmupd_command(struct i40e_hw *hw,
                                          struct i40e_nvm_access *cmd,
                                          u8 *bytes, int *);
-void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode);
+void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode,
+                                 struct i40e_aq_desc *desc);
+void i40e_nvmupd_clear_wait_state(struct i40e_hw *hw);
 void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
 #endif /* PF_DRIVER */
 
index e3f014c..056ca4d 100644 (file)
@@ -490,6 +490,7 @@ enum i40e_nvmupd_cmd {
        I40E_NVMUPD_STATUS,
        I40E_NVMUPD_EXEC_AQ,
        I40E_NVMUPD_GET_AQ_RESULT,
+       I40E_NVMUPD_GET_AQ_EVENT,
 };
 
 enum i40e_nvmupd_state {
@@ -522,6 +523,7 @@ enum i40e_nvmupd_state {
 #define I40E_NVM_SA                            (I40E_NVM_SNT | I40E_NVM_LCB)
 #define I40E_NVM_ERA                           0x4
 #define I40E_NVM_CSUM                          0x8
+#define I40E_NVM_AQE                           0xe
 #define I40E_NVM_EXEC                          0xf
 
 #define I40E_NVM_ADAPT_SHIFT   16
@@ -705,6 +707,7 @@ struct i40e_hw {
        /* state of nvm update process */
        enum i40e_nvmupd_state nvmupd_state;
        struct i40e_aq_desc nvm_wb_desc;
+       struct i40e_aq_desc nvm_aq_event_desc;
        struct i40e_virt_mem nvm_buff;
        bool nvm_release_on_done;
        u16 nvm_wait_opcode;