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