Commit 3bc7d4a3 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Add BNXT_STATE_IN_FW_RESET state.

The new flag will be set in subsequent patches when firmware is
going through reset.  If bnxt_close() is called while the new flag
is set, the FW reset sequence will have to be aborted because the
NIC is prematurely closed before FW reset has completed.  We also
reject SRIOV configurations while FW reset is in progress.

v2: No longer drop rtnl_lock() in close and wait for FW reset to complete.
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7e914027
...@@ -8716,6 +8716,10 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up) ...@@ -8716,6 +8716,10 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_HOT_FW_RESET_DONE) if (flags & FUNC_DRV_IF_CHANGE_RESP_FLAGS_HOT_FW_RESET_DONE)
fw_reset = true; fw_reset = true;
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) {
netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n");
return -ENODEV;
}
if (resc_reinit || fw_reset) { if (resc_reinit || fw_reset) {
if (fw_reset) { if (fw_reset) {
rc = bnxt_fw_init_one(bp); rc = bnxt_fw_init_one(bp);
...@@ -9226,6 +9230,10 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init, ...@@ -9226,6 +9230,10 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init,
bnxt_debug_dev_exit(bp); bnxt_debug_dev_exit(bp);
bnxt_disable_napi(bp); bnxt_disable_napi(bp);
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) &&
pci_is_enabled(bp->pdev))
pci_disable_device(bp->pdev);
bnxt_free_skbs(bp); bnxt_free_skbs(bp);
/* Save ring stats before shutdown */ /* Save ring stats before shutdown */
...@@ -9242,6 +9250,18 @@ int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) ...@@ -9242,6 +9250,18 @@ int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
{ {
int rc = 0; int rc = 0;
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
/* If we get here, it means firmware reset is in progress
* while we are trying to close. We can safely proceed with
* the close because we are holding rtnl_lock(). Some firmware
* messages may fail as we proceed to close. We set the
* ABORT_ERR flag here so that the FW reset thread will later
* abort when it gets the rtnl_lock() and sees the flag.
*/
netdev_warn(bp->dev, "FW reset in progress during close, FW reset will be aborted\n");
set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
}
#ifdef CONFIG_BNXT_SRIOV #ifdef CONFIG_BNXT_SRIOV
if (bp->sriov_cfg) { if (bp->sriov_cfg) {
rc = wait_event_interruptible_timeout(bp->sriov_cfg_wait, rc = wait_event_interruptible_timeout(bp->sriov_cfg_wait,
......
...@@ -1605,6 +1605,7 @@ struct bnxt { ...@@ -1605,6 +1605,7 @@ struct bnxt {
#define BNXT_STATE_IN_SP_TASK 1 #define BNXT_STATE_IN_SP_TASK 1
#define BNXT_STATE_READ_STATS 2 #define BNXT_STATE_READ_STATS 2
#define BNXT_STATE_FW_RESET_DET 3 #define BNXT_STATE_FW_RESET_DET 3
#define BNXT_STATE_IN_FW_RESET 4
#define BNXT_STATE_ABORT_ERR 5 #define BNXT_STATE_ABORT_ERR 5
struct bnxt_irq *irq_tbl; struct bnxt_irq *irq_tbl;
......
...@@ -828,6 +828,11 @@ int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs) ...@@ -828,6 +828,11 @@ int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs)
rtnl_unlock(); rtnl_unlock();
return 0; return 0;
} }
if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
netdev_warn(dev, "Reject SRIOV config request when FW reset is in progress\n");
rtnl_unlock();
return 0;
}
bp->sriov_cfg = true; bp->sriov_cfg = true;
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