This adds wait states to the NVM update state machine to signify when
waiting for an update operation to finish, whether we're in the middle
of a set of Write operations, or we're now idle but waiting.

Signed-off-by: Jingjing Wu <jingjing.wu at intel.com>
---
 drivers/net/i40e/base/i40e_adminq.c | 13 ++++++++++
 drivers/net/i40e/base/i40e_nvm.c    | 48 +++++++++++++++++++++++++++----------
 drivers/net/i40e/base/i40e_type.h   |  4 +++-
 3 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/drivers/net/i40e/base/i40e_adminq.c 
b/drivers/net/i40e/base/i40e_adminq.c
index c83476c..7589b39 100644
--- a/drivers/net/i40e/base/i40e_adminq.c
+++ b/drivers/net/i40e/base/i40e_adminq.c
@@ -1065,6 +1065,19 @@ clean_arq_element_out:
                        i40e_release_nvm(hw);
                        hw->aq.nvm_release_on_done = false;
                }
+
+               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;
+
+               default:
+                       break;
+               }
        }

 #endif
diff --git a/drivers/net/i40e/base/i40e_nvm.c b/drivers/net/i40e/base/i40e_nvm.c
index 1da81a7..f4ea289 100644
--- a/drivers/net/i40e/base/i40e_nvm.c
+++ b/drivers/net/i40e/base/i40e_nvm.c
@@ -762,6 +762,12 @@ enum i40e_status_code i40e_nvmupd_command(struct i40e_hw 
*hw,
                status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno);
                break;

+       case I40E_NVMUPD_STATE_INIT_WAIT:
+       case I40E_NVMUPD_STATE_WRITE_WAIT:
+               status = I40E_ERR_NOT_READY;
+               *perrno = -EBUSY;
+               break;
+
        default:
                /* invalid state, should never happen */
                i40e_debug(hw, I40E_DEBUG_NVM,
@@ -827,10 +833,12 @@ STATIC enum i40e_status_code 
i40e_nvmupd_state_init(struct i40e_hw *hw,
                                                     hw->aq.asq_last_status);
                } else {
                        status = i40e_nvmupd_nvm_erase(hw, cmd, perrno);
-                       if (status)
+                       if (status) {
                                i40e_release_nvm(hw);
-                       else
+                       } else {
                                hw->aq.nvm_release_on_done = true;
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+                       }
                }
                break;

@@ -841,10 +849,12 @@ STATIC enum i40e_status_code 
i40e_nvmupd_state_init(struct i40e_hw *hw,
                                                     hw->aq.asq_last_status);
                } else {
                        status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
-                       if (status)
+                       if (status) {
                                i40e_release_nvm(hw);
-                       else
+                       } else {
                                hw->aq.nvm_release_on_done = true;
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+                       }
                }
                break;

@@ -858,7 +868,7 @@ STATIC enum i40e_status_code i40e_nvmupd_state_init(struct 
i40e_hw *hw,
                        if (status)
                                i40e_release_nvm(hw);
                        else
-                               hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
                }
                break;

@@ -877,6 +887,7 @@ STATIC enum i40e_status_code i40e_nvmupd_state_init(struct 
i40e_hw *hw,
                                i40e_release_nvm(hw);
                        } else {
                                hw->aq.nvm_release_on_done = true;
+                               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
                        }
                }
                break;
@@ -906,7 +917,7 @@ STATIC enum i40e_status_code 
i40e_nvmupd_state_reading(struct i40e_hw *hw,
                                                    struct i40e_nvm_access *cmd,
                                                    u8 *bytes, int *perrno)
 {
-       enum i40e_status_code status;
+       enum i40e_status_code status = I40E_SUCCESS;
        enum i40e_nvmupd_cmd upd_cmd;

        DEBUGFUNC("i40e_nvmupd_state_reading");
@@ -950,7 +961,7 @@ STATIC enum i40e_status_code 
i40e_nvmupd_state_writing(struct i40e_hw *hw,
                                                    struct i40e_nvm_access *cmd,
                                                    u8 *bytes, int *perrno)
 {
-       enum i40e_status_code status;
+       enum i40e_status_code status = I40E_SUCCESS;
        enum i40e_nvmupd_cmd upd_cmd;
        bool retry_attempt = false;

@@ -962,13 +973,22 @@ retry:
        switch (upd_cmd) {
        case I40E_NVMUPD_WRITE_CON:
                status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
+               if (!status)
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
                break;

        case I40E_NVMUPD_WRITE_LCB:
                status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
-               if (!status)
+               if (status) {
+                       *perrno = hw->aq.asq_last_status ?
+                                  i40e_aq_rc_to_posix(status,
+                                                      hw->aq.asq_last_status) :
+                                  -EIO;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               } else {
                        hw->aq.nvm_release_on_done = true;
-               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+               }
                break;

        case I40E_NVMUPD_CSUM_CON:
@@ -979,19 +999,23 @@ retry:
                                                       hw->aq.asq_last_status) :
                                   -EIO;
                        hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               } else {
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
                }
                break;

        case I40E_NVMUPD_CSUM_LCB:
                status = i40e_update_nvm_checksum(hw);
-               if (status)
+               if (status) {
                        *perrno = hw->aq.asq_last_status ?
                                   i40e_aq_rc_to_posix(status,
                                                       hw->aq.asq_last_status) :
                                   -EIO;
-               else
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+               } else {
                        hw->aq.nvm_release_on_done = true;
-               hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+                       hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
+               }
                break;

        default:
diff --git a/drivers/net/i40e/base/i40e_type.h 
b/drivers/net/i40e/base/i40e_type.h
index e1cb5fd..f9fc35c 100644
--- a/drivers/net/i40e/base/i40e_type.h
+++ b/drivers/net/i40e/base/i40e_type.h
@@ -369,7 +369,9 @@ enum i40e_nvmupd_cmd {
 enum i40e_nvmupd_state {
        I40E_NVMUPD_STATE_INIT,
        I40E_NVMUPD_STATE_READING,
-       I40E_NVMUPD_STATE_WRITING
+       I40E_NVMUPD_STATE_WRITING,
+       I40E_NVMUPD_STATE_INIT_WAIT,
+       I40E_NVMUPD_STATE_WRITE_WAIT,
 };

 /* nvm_access definition and its masks/shifts need to be accessible to
-- 
2.4.0

Reply via email to