aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/marvell/mwifiex/pcie.c
diff options
context:
space:
mode:
authorBrian Norris <briannorris@chromium.org>2017-03-16 14:36:07 -0700
committerKalle Valo <kvalo@codeaurora.org>2017-03-20 19:09:20 +0200
commit5caa7f384629eb2b02f2289ffea1277a401adfcb (patch)
tree8481e8d5c8b7a15968e231c74ed80f5a595a3ce9 /drivers/net/wireless/marvell/mwifiex/pcie.c
parentmwifiex: send fewer channels to scan while connected (diff)
downloadlinux-dev-5caa7f384629eb2b02f2289ffea1277a401adfcb.tar.xz
linux-dev-5caa7f384629eb2b02f2289ffea1277a401adfcb.zip
mwifiex: fix kernel crash after shutdown command timeout
We observed a SHUTDOWN command timeout during reboot stress test due to a corner case firmware bug. It can lead to either a use-after-free + OOPS (on either the adapter structure, or the 'card' structure) or an abort (where, e.g., the PCI device is "disabled" before we're done dumping the FW). We can avoid this by canceling/flushing the FW dump work: (a) after we've terminated all other work queues (e.g., for processing commands which could time out) (b) after we've disabled all interrupts (which could also queue more work for us) (c) after we've unregistered the netdev and wiphy structures (and implicitly, and debugfs entries which could manually trigger FW dumps) (d) before we've actually disabled the device (e.g., pci_device_disable()) Altogether, this means no card->work will be scheduled if we sync at a point that satisfies the above. This can be done at the beginning of the .cleanup_if() callback. Signed-off-by: Brian Norris <briannorris@chromium.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/marvell/mwifiex/pcie.c')
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 23e09117bf4a..e381deff37f3 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -294,8 +294,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
if (!adapter || !adapter->priv_num)
return;
- cancel_work_sync(&card->work);
-
reg = card->pcie.reg;
if (reg)
ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
@@ -2854,6 +2852,8 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter)
int ret;
u32 fw_status;
+ cancel_work_sync(&card->work);
+
ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
if (fw_status == FIRMWARE_READY_PCIE) {
mwifiex_dbg(adapter, INFO,