diff mbox series

[J,1/1] wifi: iwlwifi: pcie: rescan bus if no parent

Message ID 20240103031916.782306-2-kai.heng.feng@canonical.com
State New
Headers show
Series [J,1/1] wifi: iwlwifi: pcie: rescan bus if no parent | expand

Commit Message

Kai-Heng Feng Jan. 3, 2024, 3:19 a.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

BugLink: https://bugs.launchpad.net/bugs/2046217

If the bus has no parent due to the topology, the device rescan
(after some kind of reset was detected) wouldn't work. On the
other hand, some platforms appear to require scanning the parent,
though it's not clear why.

However if there's no parent, then we skip the rescan, which isn't a
good idea. Change the code to go to the parent only if that exists,
and rescan the bus itself where it doesn't.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230913145231.f7795a1ccdab.I2b84810a743469a1bcabf3628262cf54311593f4@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
(backported from commit 111ed1eb175754a9ef11811240329ca40db2072f)
[khfeng: Omitting a predicate that requires a massive feature backport]
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 6 ++++++
 1 file changed, 6 insertions(+)
diff mbox series

Patch

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index 4456aef930cf..e6631e147a41 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1987,12 +1987,18 @@  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;
 
 	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 (bus) {
+		if (bus->parent)
+			bus = bus->parent;
+		pci_rescan_bus(bus);
+	}
 	pci_unlock_rescan_remove();
 
 	kfree(removal);