Commit 3958b1da authored by Somnath Kotur's avatar Somnath Kotur Committed by David S. Miller

bnxt_en: fix error path of FW reset

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: dab62e7c ("bnxt_en: Implement faster recovery for firmware fatal error.")
Signed-off-by: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6cd657cb
...@@ -11959,10 +11959,21 @@ static bool bnxt_fw_reset_timeout(struct bnxt *bp) ...@@ -11959,10 +11959,21 @@ static bool bnxt_fw_reset_timeout(struct bnxt *bp)
(bp->fw_reset_max_dsecs * HZ / 10)); (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) static void bnxt_fw_reset_task(struct work_struct *work)
{ {
struct bnxt *bp = container_of(work, struct bnxt, fw_reset_task.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)) { 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"); 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) ...@@ -11993,8 +12004,9 @@ static void bnxt_fw_reset_task(struct work_struct *work)
bp->fw_reset_timestamp = jiffies; bp->fw_reset_timestamp = jiffies;
rtnl_lock(); rtnl_lock();
if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) { if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) {
bnxt_fw_reset_abort(bp, rc);
rtnl_unlock(); rtnl_unlock();
goto fw_reset_abort; return;
} }
bnxt_fw_reset_close(bp); bnxt_fw_reset_close(bp);
if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) { if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) {
...@@ -12043,6 +12055,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) ...@@ -12043,6 +12055,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
if (val == 0xffff) { if (val == 0xffff) {
if (bnxt_fw_reset_timeout(bp)) { if (bnxt_fw_reset_timeout(bp)) {
netdev_err(bp->dev, "Firmware reset aborted, PCI config space invalid\n"); netdev_err(bp->dev, "Firmware reset aborted, PCI config space invalid\n");
rc = -ETIMEDOUT;
goto fw_reset_abort; goto fw_reset_abort;
} }
bnxt_queue_fw_reset_work(bp, HZ / 1000); bnxt_queue_fw_reset_work(bp, HZ / 1000);
...@@ -12052,6 +12065,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) ...@@ -12052,6 +12065,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
clear_bit(BNXT_STATE_FW_FATAL_COND, &bp->state); clear_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
if (pci_enable_device(bp->pdev)) { if (pci_enable_device(bp->pdev)) {
netdev_err(bp->dev, "Cannot re-enable PCI device\n"); netdev_err(bp->dev, "Cannot re-enable PCI device\n");
rc = -ENODEV;
goto fw_reset_abort; goto fw_reset_abort;
} }
pci_set_master(bp->pdev); pci_set_master(bp->pdev);
...@@ -12078,9 +12092,10 @@ static void bnxt_fw_reset_task(struct work_struct *work) ...@@ -12078,9 +12092,10 @@ static void bnxt_fw_reset_task(struct work_struct *work)
} }
rc = bnxt_open(bp->dev); rc = bnxt_open(bp->dev);
if (rc) { if (rc) {
netdev_err(bp->dev, "bnxt_open_nic() failed\n"); netdev_err(bp->dev, "bnxt_open() failed during FW reset\n");
clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state); bnxt_fw_reset_abort(bp, rc);
dev_close(bp->dev); rtnl_unlock();
return;
} }
bp->fw_reset_state = 0; bp->fw_reset_state = 0;
...@@ -12107,12 +12122,8 @@ static void bnxt_fw_reset_task(struct work_struct *work) ...@@ -12107,12 +12122,8 @@ static void bnxt_fw_reset_task(struct work_struct *work)
netdev_err(bp->dev, "fw_health_status 0x%x\n", sts); netdev_err(bp->dev, "fw_health_status 0x%x\n", sts);
} }
fw_reset_abort: 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(); rtnl_lock();
dev_close(bp->dev); bnxt_fw_reset_abort(bp, rc);
rtnl_unlock(); rtnl_unlock();
} }
......
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