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 pci_remove_sysfs_dev_files(dev); 30 of_pci_remove_node(dev); 31 } 32 33 static void pci_destroy_dev(struct pci_dev *dev) 34 { 35 if (pci_dev_test_and_set_removed(dev)) 36 return; 37 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 pci_remove_legacy_files(bus); 70 71 if (bus->ops->remove_bus) 72 bus->ops->remove_bus(bus); 73 74 pcibios_remove_bus(bus); 75 device_unregister(&bus->dev); 76 } 77 EXPORT_SYMBOL(pci_remove_bus); 78 79 static void pci_stop_bus_device(struct pci_dev *dev) 80 { 81 struct pci_bus *bus = dev->subordinate; 82 struct pci_dev *child, *tmp; 83 84 /* 85 * Stopping an SR-IOV PF device removes all the associated VFs, 86 * which will update the bus->devices list and confuse the 87 * iterator. Therefore, iterate in reverse so we remove the VFs 88 * first, then the PF. 89 */ 90 if (bus) { 91 list_for_each_entry_safe_reverse(child, tmp, 92 &bus->devices, bus_list) 93 pci_stop_bus_device(child); 94 } 95 96 pci_stop_dev(dev); 97 } 98 99 static void pci_remove_bus_device(struct pci_dev *dev) 100 { 101 struct pci_bus *bus = dev->subordinate; 102 struct pci_dev *child, *tmp; 103 104 if (bus) { 105 list_for_each_entry_safe(child, tmp, 106 &bus->devices, bus_list) 107 pci_remove_bus_device(child); 108 109 pci_remove_bus(bus); 110 dev->subordinate = NULL; 111 } 112 113 pci_destroy_dev(dev); 114 } 115 116 /** 117 * pci_stop_and_remove_bus_device - remove a PCI device and any children 118 * @dev: the device to remove 119 * 120 * Remove a PCI device from the device lists, informing the drivers 121 * that the device has been removed. We also remove any subordinate 122 * buses and children in a depth-first manner. 123 * 124 * For each device we remove, delete the device structure from the 125 * device lists, remove the /proc entry, and notify userspace 126 * (/sbin/hotplug). 127 */ 128 void pci_stop_and_remove_bus_device(struct pci_dev *dev) 129 { 130 lockdep_assert_held(&pci_rescan_remove_lock); 131 pci_stop_bus_device(dev); 132 pci_remove_bus_device(dev); 133 } 134 EXPORT_SYMBOL(pci_stop_and_remove_bus_device); 135 136 void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev) 137 { 138 pci_lock_rescan_remove(); 139 pci_stop_and_remove_bus_device(dev); 140 pci_unlock_rescan_remove(); 141 } 142 EXPORT_SYMBOL_GPL(pci_stop_and_remove_bus_device_locked); 143 144 void pci_stop_root_bus(struct pci_bus *bus) 145 { 146 struct pci_dev *child, *tmp; 147 struct pci_host_bridge *host_bridge; 148 149 if (!pci_is_root_bus(bus)) 150 return; 151 152 host_bridge = to_pci_host_bridge(bus->bridge); 153 list_for_each_entry_safe_reverse(child, tmp, 154 &bus->devices, bus_list) 155 pci_stop_bus_device(child); 156 157 of_pci_remove_host_bridge_node(host_bridge); 158 159 /* stop the host bridge */ 160 device_release_driver(&host_bridge->dev); 161 } 162 EXPORT_SYMBOL_GPL(pci_stop_root_bus); 163 164 void pci_remove_root_bus(struct pci_bus *bus) 165 { 166 struct pci_dev *child, *tmp; 167 struct pci_host_bridge *host_bridge; 168 169 if (!pci_is_root_bus(bus)) 170 return; 171 172 host_bridge = to_pci_host_bridge(bus->bridge); 173 list_for_each_entry_safe(child, tmp, 174 &bus->devices, bus_list) 175 pci_remove_bus_device(child); 176 177 #ifdef CONFIG_PCI_DOMAINS_GENERIC 178 /* Release domain_nr if it was dynamically allocated */ 179 if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET) 180 pci_bus_release_domain_nr(host_bridge->dev.parent, bus->domain_nr); 181 #endif 182 183 pci_remove_bus(bus); 184 host_bridge->bus = NULL; 185 186 /* remove the host bridge */ 187 device_del(&host_bridge->dev); 188 } 189 EXPORT_SYMBOL_GPL(pci_remove_root_bus); 190