This is a note to let you know that I've just added the patch titled bnxt_en: Fix possible crash in bnxt_fw_reset_task(). to the 5.4-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: bnxt_en-fix-possible-crash-in-bnxt_fw_reset_task.patch and it can be found in the queue-5.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 1ed14856dbc2fd0023ea79392aad1e6e8e8a42b3 Author: Michael Chan <michael.chan@xxxxxxxxxxxx> Date: Wed Aug 26 01:08:36 2020 -0400 bnxt_en: Fix possible crash in bnxt_fw_reset_task(). [ Upstream commit b148bb238c02f0c7797efed026e9bba5892d2172 ] bnxt_fw_reset_task() is run from a delayed workqueue. The current code is not cancelling the workqueue in the driver's .remove() method and it can potentially crash if the device is removed with the workqueue still pending. The fix is to clear the BNXT_STATE_IN_FW_RESET flag and then cancel the delayed workqueue in bnxt_remove_one(). bnxt_queue_fw_reset_work() also needs to check that this flag is set before scheduling. This will guarantee that no rescheduling will be done after it is cancelled. Fixes: 230d1f0de754 ("bnxt_en: Handle firmware reset.") Reviewed-by: Vasundhara Volam <vasundhara-v.volam@xxxxxxxxxxxx> Signed-off-by: Michael Chan <michael.chan@xxxxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 7cb74d7a78e3c..16462d21fea38 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1143,6 +1143,9 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay) { + if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))) + return; + if (BNXT_PF(bp)) queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay); else @@ -1159,10 +1162,12 @@ static void bnxt_queue_sp_work(struct bnxt *bp) static void bnxt_cancel_sp_work(struct bnxt *bp) { - if (BNXT_PF(bp)) + if (BNXT_PF(bp)) { flush_workqueue(bnxt_pf_wq); - else + } else { cancel_work_sync(&bp->sp_task); + cancel_delayed_work_sync(&bp->fw_reset_task); + } } static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) @@ -11386,6 +11391,7 @@ static void bnxt_remove_one(struct pci_dev *pdev) unregister_netdev(dev); bnxt_dl_unregister(bp); bnxt_shutdown_tc(bp); + clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state); bnxt_cancel_sp_work(bp); bp->sp_event = 0;