1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/pci.h> 3 #include <linux/module.h> 4 #include <linux/of.h> 5 #include <linux/of_platform.h> 6 #include <linux/platform_device.h> 7 8 #include "pci.h" 9 10 static void pci_free_resources(struct pci_dev *dev) 11 { 12 struct resource *res; 13 14 pci_dev_for_each_resource(dev, res) { 15 if (res->parent) 16 release_resource(res); 17 } 18 } 19 20 static void pci_stop_dev(struct pci_dev *dev) 21 { 22 pci_pme_active(dev, false); 23 24 if (!pci_dev_test_and_clear_added(dev)) 25 return; 26 27 device_release_driver(&dev->dev); 28 pci_proc_detach_device(dev); 29 of_pci_remove_node(dev); 30 } 31 32 static void pci_destroy_dev(struct pci_dev *dev) 33 { 34 if (pci_dev_test_and_set_removed(dev)) 35 return; 36 37 platform_pci_remove_wake(dev); 38 pci_doe_sysfs_teardown(dev); 39 pci_npem_remove(dev); 40 41 /* 42 * While device is in D0 drop the device from TSM link operations 43 * including unbind and disconnect (IDE + SPDM teardown). 44 */ 45 pci_tsm_destroy(dev); 46 47 device_del(&dev->dev); 48 49 down_write(&pci_bus_sem); 50 list_del(&dev->bus_list); 51 up_write(&pci_bus_sem); 52 53 pci_doe_destroy(dev); 54 pci_ide_destroy(dev); 55 pcie_aspm_exit_link_state(dev); 56 pci_bridge_d3_update(dev); 57 pci_free_resources(dev); 58 put_device(&dev->dev); 59 } 60 61 void pci_remove_bus(struct pci_bus *bus) 62 { 63 pci_proc_detach_bus(bus); 64 65 down_write(&pci_bus_sem); 66 list_del(&bus->node); 67 pci_bus_release_busn_res(bus); 68 up_write(&pci_bus_sem); 69 if (bus->ops->remove_bus) 70 bus->ops->remove_bus(bus); 71 72 pcibios_remove_bus(bus); 73 device_unregister(&bus->dev); 74 } 75 EXPORT_SYMBOL(pci_remove_bus); 76 77 static void pci_stop_bus_device(struct pci_dev *dev) 78 { 79 struct pci_bus *bus = dev->subordinate; 80 struct pci_dev *child, *tmp; 81 82 /* 83 * Stopping an SR-IOV PF device removes all the associated VFs, 84 * which will update the bus->devices list and confuse the 85 * iterator. Therefore, iterate in reverse so we remove the VFs 86 * first, then the PF. 87 */ 88 if (bus) { 89 list_for_each_entry_safe_reverse(child, tmp, 90 &bus->devices, bus_list) 91 pci_stop_bus_device(child); 92 } 93 94 pci_stop_dev(dev); 95 } 96 97 static void pci_remove_bus_device(struct pci_dev *dev) 98 { 99 struct pci_bus *bus = dev->subordinate; 100 struct pci_dev *child, *tmp; 101 102 if (bus) { 103 list_for_each_entry_safe(child, tmp, 104 &bus->devices, bus_list) 105 pci_remove_bus_device(child); 106 107 pci_remove_bus(bus); 108 dev->subordinate = NULL; 109 } 110 111 pci_destroy_dev(dev); 112 } 113 114 /** 115 * pci_stop_and_remove_bus_device - remove a PCI device and any children 116 * @dev: the device to remove 117 * 118 * Remove a PCI device from the device lists, informing the drivers 119 * that the device has been removed. We also remove any subordinate 120 * buses and children in a depth-first manner. 121 * 122 * For each device we remove, delete the device structure from the 123 * device lists, remove the /proc entry, and notify userspace 124 * (/sbin/hotplug). 125 */ 126 void pci_stop_and_remove_bus_device(struct pci_dev *dev) 127 { 128 lockdep_assert_held(&pci_rescan_remove_lock); 129 pci_stop_bus_device(dev); 130 pci_remove_bus_device(dev); 131 } 132 EXPORT_SYMBOL(pci_stop_and_remove_bus_device); 133 134 void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev) 135 { 136 pci_lock_rescan_remove(); 137 pci_stop_and_remove_bus_device(dev); 138 pci_unlock_rescan_remove(); 139 } 140 EXPORT_SYMBOL_GPL(pci_stop_and_remove_bus_device_locked); 141 142 void pci_stop_root_bus(struct pci_bus *bus) 143 { 144 struct pci_dev *child, *tmp; 145 struct pci_host_bridge *host_bridge; 146 147 if (!pci_is_root_bus(bus)) 148 return; 149 150 host_bridge = to_pci_host_bridge(bus->bridge); 151 list_for_each_entry_safe_reverse(child, tmp, 152 &bus->devices, bus_list) 153 pci_stop_bus_device(child); 154 155 of_pci_remove_host_bridge_node(host_bridge); 156 157 /* stop the host bridge */ 158 device_release_driver(&host_bridge->dev); 159 } 160 EXPORT_SYMBOL_GPL(pci_stop_root_bus); 161 162 void pci_remove_root_bus(struct pci_bus *bus) 163 { 164 struct pci_dev *child, *tmp; 165 struct pci_host_bridge *host_bridge; 166 167 if (!pci_is_root_bus(bus)) 168 return; 169 170 host_bridge = to_pci_host_bridge(bus->bridge); 171 list_for_each_entry_safe(child, tmp, 172 &bus->devices, bus_list) 173 pci_remove_bus_device(child); 174 175 #ifdef CONFIG_PCI_DOMAINS_GENERIC 176 /* Release domain_nr if it was dynamically allocated */ 177 if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET) 178 pci_bus_release_domain_nr(host_bridge->dev.parent, bus->domain_nr); 179 #endif 180 181 pci_remove_bus(bus); 182 host_bridge->bus = NULL; 183 184 /* remove the host bridge */ 185 device_del(&host_bridge->dev); 186 } 187 EXPORT_SYMBOL_GPL(pci_remove_root_bus); 188