--- zzzz-none-000/linux-3.10.107/drivers/pci/hotplug/shpchp_pci.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/pci/hotplug/shpchp_pci.c 2021-02-04 17:41:59.000000000 +0000 @@ -34,48 +34,47 @@ #include "../pci.h" #include "shpchp.h" -int __ref shpchp_configure_device(struct slot *p_slot) +int shpchp_configure_device(struct slot *p_slot) { struct pci_dev *dev; struct controller *ctrl = p_slot->ctrl; struct pci_dev *bridge = ctrl->pci_dev; struct pci_bus *parent = bridge->subordinate; - int num; + int num, ret = 0; + + pci_lock_rescan_remove(); dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { - ctrl_err(ctrl, "Device %s already exists " - "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), - pci_domain_nr(parent), p_slot->bus, p_slot->device); + ctrl_err(ctrl, "Device %s already exists at %04x:%02x:%02x, cannot hot-add\n", + pci_name(dev), pci_domain_nr(parent), + p_slot->bus, p_slot->device); pci_dev_put(dev); - return -EINVAL; + ret = -EINVAL; + goto out; } num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (num == 0) { ctrl_err(ctrl, "No new device found\n"); - return -ENODEV; + ret = -ENODEV; + goto out; } list_for_each_entry(dev, &parent->devices, bus_list) { if (PCI_SLOT(dev->devfn) != p_slot->device) continue; - if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || - (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) + if (pci_is_bridge(dev)) pci_hp_add_bridge(dev); } pci_assign_unassigned_bridge_resources(bridge); - - list_for_each_entry(dev, &parent->devices, bus_list) { - if (PCI_SLOT(dev->devfn) != p_slot->device) - continue; - pci_configure_slot(dev); - } - + pcie_bus_configure_settings(parent); pci_bus_add_devices(parent); - return 0; + out: + pci_unlock_rescan_remove(); + return ret; } int shpchp_unconfigure_device(struct slot *p_slot) @@ -89,6 +88,8 @@ ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); + pci_lock_rescan_remove(); + list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { if (PCI_SLOT(dev->devfn) != p_slot->device) continue; @@ -108,6 +109,8 @@ pci_stop_and_remove_bus_device(dev); pci_dev_put(dev); } + + pci_unlock_rescan_remove(); return rc; }