^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include "pci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) static void pci_free_resources(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) for (i = 0; i < PCI_NUM_RESOURCES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct resource *res = dev->resource + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) if (res->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) release_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static void pci_stop_dev(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) pci_pme_active(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (pci_dev_is_added(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) device_release_driver(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) pci_proc_detach_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) pci_remove_sysfs_dev_files(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) pci_dev_assign_added(dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static void pci_destroy_dev(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (!dev->dev.kobj.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) device_del(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) down_write(&pci_bus_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) list_del(&dev->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) up_write(&pci_bus_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) pcie_aspm_exit_link_state(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) pci_bridge_d3_update(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) pci_free_resources(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) put_device(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) void pci_remove_bus(struct pci_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) pci_proc_detach_bus(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) down_write(&pci_bus_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) list_del(&bus->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) pci_bus_release_busn_res(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) up_write(&pci_bus_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) pci_remove_legacy_files(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (bus->ops->remove_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) bus->ops->remove_bus(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) pcibios_remove_bus(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) device_unregister(&bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) EXPORT_SYMBOL(pci_remove_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void pci_stop_bus_device(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct pci_bus *bus = dev->subordinate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct pci_dev *child, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Stopping an SR-IOV PF device removes all the associated VFs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * which will update the bus->devices list and confuse the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * iterator. Therefore, iterate in reverse so we remove the VFs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * first, then the PF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) list_for_each_entry_safe_reverse(child, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) &bus->devices, bus_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pci_stop_bus_device(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pci_stop_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static void pci_remove_bus_device(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct pci_bus *bus = dev->subordinate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct pci_dev *child, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) list_for_each_entry_safe(child, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) &bus->devices, bus_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pci_remove_bus_device(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) pci_remove_bus(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dev->subordinate = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pci_destroy_dev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * pci_stop_and_remove_bus_device - remove a PCI device and any children
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @dev: the device to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Remove a PCI device from the device lists, informing the drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * that the device has been removed. We also remove any subordinate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * buses and children in a depth-first manner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * For each device we remove, delete the device structure from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * device lists, remove the /proc entry, and notify userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * (/sbin/hotplug).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) void pci_stop_and_remove_bus_device(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) pci_stop_bus_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) pci_remove_bus_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) pci_lock_rescan_remove();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) pci_stop_and_remove_bus_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pci_unlock_rescan_remove();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) EXPORT_SYMBOL_GPL(pci_stop_and_remove_bus_device_locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) void pci_stop_root_bus(struct pci_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct pci_dev *child, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct pci_host_bridge *host_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!pci_is_root_bus(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) host_bridge = to_pci_host_bridge(bus->bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) list_for_each_entry_safe_reverse(child, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) &bus->devices, bus_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) pci_stop_bus_device(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* stop the host bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) device_release_driver(&host_bridge->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) EXPORT_SYMBOL_GPL(pci_stop_root_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) void pci_remove_root_bus(struct pci_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct pci_dev *child, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct pci_host_bridge *host_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!pci_is_root_bus(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) host_bridge = to_pci_host_bridge(bus->bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) list_for_each_entry_safe(child, tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) &bus->devices, bus_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) pci_remove_bus_device(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) pci_remove_bus(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) host_bridge->bus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* remove the host bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) device_del(&host_bridge->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) EXPORT_SYMBOL_GPL(pci_remove_root_bus);