bnxt_en: fix error path of FW reset
authorSomnath Kotur <somnath.kotur@broadcom.com>
Sun, 18 Jul 2021 19:36:29 +0000 (15:36 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 19 Jul 2021 15:25:44 +0000 (08:25 -0700)
When bnxt_open() fails in the firmware reset path, the driver needs to
gracefully abort, but it is executing code that should be invoked only
in the success path.  Define a function to abort FW reset and
consolidate all error paths to call this new function.

Fixes: dab62e7c2de7 ("bnxt_en: Implement faster recovery for firmware fatal error.")
Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c

index 39908a3..f2f1136 100644 (file)
@@ -11959,10 +11959,21 @@ static bool bnxt_fw_reset_timeout(struct bnxt *bp)
                          (bp->fw_reset_max_dsecs * HZ / 10));
 }
 
+static void bnxt_fw_reset_abort(struct bnxt *bp, int rc)
+{
+       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+       if (bp->fw_reset_state != BNXT_FW_RESET_STATE_POLL_VF) {
+               bnxt_ulp_start(bp, rc);
+               bnxt_dl_health_status_update(bp, false);
+       }
+       bp->fw_reset_state = 0;
+       dev_close(bp->dev);
+}
+
 static void bnxt_fw_reset_task(struct work_struct *work)
 {
        struct bnxt *bp = container_of(work, struct bnxt, fw_reset_task.work);
-       int rc;
+       int rc = 0;
 
        if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
                netdev_err(bp->dev, "bnxt_fw_reset_task() called when not in fw reset mode!\n");
@@ -11993,8 +12004,9 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                bp->fw_reset_timestamp = jiffies;
                rtnl_lock();
                if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) {
+                       bnxt_fw_reset_abort(bp, rc);
                        rtnl_unlock();
-                       goto fw_reset_abort;
+                       return;
                }
                bnxt_fw_reset_close(bp);
                if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) {
@@ -12043,6 +12055,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                        if (val == 0xffff) {
                                if (bnxt_fw_reset_timeout(bp)) {
                                        netdev_err(bp->dev, "Firmware reset aborted, PCI config space invalid\n");
+                                       rc = -ETIMEDOUT;
                                        goto fw_reset_abort;
                                }
                                bnxt_queue_fw_reset_work(bp, HZ / 1000);
@@ -12052,6 +12065,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                clear_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
                if (pci_enable_device(bp->pdev)) {
                        netdev_err(bp->dev, "Cannot re-enable PCI device\n");
+                       rc = -ENODEV;
                        goto fw_reset_abort;
                }
                pci_set_master(bp->pdev);
@@ -12078,9 +12092,10 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                }
                rc = bnxt_open(bp->dev);
                if (rc) {
-                       netdev_err(bp->dev, "bnxt_open_nic() failed\n");
-                       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
-                       dev_close(bp->dev);
+                       netdev_err(bp->dev, "bnxt_open() failed during FW reset\n");
+                       bnxt_fw_reset_abort(bp, rc);
+                       rtnl_unlock();
+                       return;
                }
 
                bp->fw_reset_state = 0;
@@ -12107,12 +12122,8 @@ fw_reset_abort_status:
                netdev_err(bp->dev, "fw_health_status 0x%x\n", sts);
        }
 fw_reset_abort:
-       clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
-       if (bp->fw_reset_state != BNXT_FW_RESET_STATE_POLL_VF)
-               bnxt_dl_health_status_update(bp, false);
-       bp->fw_reset_state = 0;
        rtnl_lock();
-       dev_close(bp->dev);
+       bnxt_fw_reset_abort(bp, rc);
        rtnl_unlock();
 }