From: Lukas Wunner lukas@wunner.de
mainline inclusion from mainline-v4.20-rc1 commit a50ac6bfd6042b16e0de4ac3264c407e678c9b10 category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I47H3V CVE: NA
--------------------------------
Commit 89ee9f768003 ("PCI: Add device disconnected state") iterates over the devices on a parent bus, marks each as disconnected, then marks each device's children as disconnected using pci_walk_bus().
The same can be achieved more succinctly by calling pci_walk_bus() on the parent bus. Moreover, this does not need to wait until acquiring pci_lock_rescan_remove(), so move it out of that critical section.
The critical section in err.c contains a pci_dev_get() / pci_dev_put() pair which was apparently copy-pasted from pciehp_pci.c. In the latter it serves the purpose of holding the struct pci_dev in place until the Command register is updated. err.c doesn't do anything like that, hence the pair is unnecessary. Remove it.
Signed-off-by: Lukas Wunner lukas@wunner.de Signed-off-by: Bjorn Helgaas bhelgaas@google.com Cc: Keith Busch keith.busch@intel.com Cc: Oza Pawandeep poza@codeaurora.org Cc: Sinan Kaya okaya@kernel.org Cc: Benjamin Herrenschmidt benh@kernel.crashing.org Signed-off-by: Jackie Liu liuyun01@kylinos.cn Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/pci/hotplug/pciehp_pci.c | 9 +++------ drivers/pci/pcie/err.c | 8 ++------ 2 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 18f83e554c73..0322bd4f0a7a 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -91,6 +91,9 @@ void pciehp_unconfigure_device(struct slot *p_slot, bool presence) ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:00\n", __func__, pci_domain_nr(parent), parent->number);
+ if (!presence) + pci_walk_bus(parent, pci_dev_set_disconnected, NULL); + pci_lock_rescan_remove();
/* @@ -102,12 +105,6 @@ void pciehp_unconfigure_device(struct slot *p_slot, bool presence) list_for_each_entry_safe_reverse(dev, temp, &parent->devices, bus_list) { pci_dev_get(dev); - if (!presence) { - pci_dev_set_disconnected(dev, NULL); - if (pci_has_subordinate(dev)) - pci_walk_bus(dev->subordinate, - pci_dev_set_disconnected, NULL); - } pci_stop_and_remove_bus_device(dev); /* * Ensure that no new Requests will be generated from diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c index 571ac3d9c326..1cae9d2c365d 100644 --- a/drivers/pci/pcie/err.c +++ b/drivers/pci/pcie/err.c @@ -241,17 +241,13 @@ void pcie_do_fatal_recovery(struct pci_dev *dev, u32 service) udev = dev->bus->self;
parent = udev->subordinate; + pci_walk_bus(parent, pci_dev_set_disconnected, NULL); + pci_lock_rescan_remove(); pci_dev_get(dev); list_for_each_entry_safe_reverse(pdev, temp, &parent->devices, bus_list) { - pci_dev_get(pdev); - pci_dev_set_disconnected(pdev, NULL); - if (pci_has_subordinate(pdev)) - pci_walk_bus(pdev->subordinate, - pci_dev_set_disconnected, NULL); pci_stop_and_remove_bus_device(pdev); - pci_dev_put(pdev); }
result = reset_link(udev, service);