diff options
Diffstat (limited to 'drivers/pci/remove.c')
-rw-r--r-- | drivers/pci/remove.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 910387e5bdbf..e4ce1145aa3e 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -1,7 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/pci.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> + #include "pci.h" static void pci_free_resources(struct pci_dev *dev) @@ -14,12 +17,25 @@ static void pci_free_resources(struct pci_dev *dev) } } +static int pci_pwrctl_unregister(struct device *dev, void *data) +{ + struct device_node *pci_node = data, *plat_node = dev_of_node(dev); + + if (dev_is_platform(dev) && plat_node && plat_node == pci_node) { + of_device_unregister(to_platform_device(dev)); + of_node_clear_flag(plat_node, OF_POPULATED); + } + + return 0; +} + static void pci_stop_dev(struct pci_dev *dev) { pci_pme_active(dev, false); if (pci_dev_is_added(dev)) { - of_platform_depopulate(&dev->dev); + device_for_each_child(dev->dev.parent, dev_of_node(&dev->dev), + pci_pwrctl_unregister); device_release_driver(&dev->dev); pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); @@ -34,6 +50,8 @@ static void pci_destroy_dev(struct pci_dev *dev) if (!dev->dev.kobj.parent) return; + pci_npem_remove(dev); + device_del(&dev->dev); down_write(&pci_bus_sem); @@ -163,7 +181,7 @@ void pci_remove_root_bus(struct pci_bus *bus) #ifdef CONFIG_PCI_DOMAINS_GENERIC /* Release domain_nr if it was dynamically allocated */ if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET) - pci_bus_release_domain_nr(bus, host_bridge->dev.parent); + pci_bus_release_domain_nr(host_bridge->dev.parent, bus->domain_nr); #endif pci_remove_bus(bus); |