wifi: iwlwifi: pcie: clean up device removal work
authorJohannes Berg <johannes.berg@intel.com>
Thu, 7 Dec 2023 02:50:11 +0000 (04:50 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 12 Dec 2023 09:37:00 +0000 (10:37 +0100)
We shouldn't access the device if we don't hold a reference,
and if - after locking - we see that it has no bus, we also
can't do anything, in fact, pci_stop_and_remove_bus_device()
will be a no-op.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20231207044813.6c0879e695f7.I1d3ce75ecad32a4cbf1b9dad61bfb7bc7821fdd9@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/trans.c

index a468e5efeecd4f5f1c6d04794c3940ebdcbcbcc9..31a6e34b33ffb91e5d124015ccd95af87d8e12d0 100644 (file)
@@ -2107,18 +2107,29 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk)
                container_of(wk, struct iwl_trans_pcie_removal, work);
        struct pci_dev *pdev = removal->pdev;
        static char *prop[] = {"EVENT=INACCESSIBLE", NULL};
-       struct pci_bus *bus = pdev->bus;
+       struct pci_bus *bus;
+
+       pci_lock_rescan_remove();
+
+       bus = pdev->bus;
+       /* in this case, something else already removed the device */
+       if (!bus)
+               goto out;
 
        dev_err(&pdev->dev, "Device gone - attempting removal\n");
+
        kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, prop);
-       pci_lock_rescan_remove();
-       pci_dev_put(pdev);
+
        pci_stop_and_remove_bus_device(pdev);
-       if (removal->rescan && bus) {
+       pci_dev_put(pdev);
+
+       if (removal->rescan) {
                if (bus->parent)
                        bus = bus->parent;
                pci_rescan_bus(bus);
        }
+
+out:
        pci_unlock_rescan_remove();
 
        kfree(removal);