1 #include <linux/pci.h> 2 #include <linux/module.h> 3 #include "pci.h" 4 5 static void pci_free_resources(struct pci_dev *dev) 6 { 7 int i; 8 9 msi_remove_pci_irq_vectors(dev); 10 11 pci_cleanup_rom(dev); 12 for (i = 0; i < PCI_NUM_RESOURCES; i++) { 13 struct resource *res = dev->resource + i; 14 if (res->parent) 15 release_resource(res); 16 } 17 } 18 19 static void pci_destroy_dev(struct pci_dev *dev) 20 { 21 pci_proc_detach_device(dev); 22 pci_remove_sysfs_dev_files(dev); 23 device_unregister(&dev->dev); 24 25 /* Remove the device from the device lists, and prevent any further 26 * list accesses from this device */ 27 spin_lock(&pci_bus_lock); 28 list_del(&dev->bus_list); 29 list_del(&dev->global_list); 30 dev->bus_list.next = dev->bus_list.prev = NULL; 31 dev->global_list.next = dev->global_list.prev = NULL; 32 spin_unlock(&pci_bus_lock); 33 34 pci_free_resources(dev); 35 pci_dev_put(dev); 36 } 37 38 /** 39 * pci_remove_device_safe - remove an unused hotplug device 40 * @dev: the device to remove 41 * 42 * Delete the device structure from the device lists and 43 * notify userspace (/sbin/hotplug), but only if the device 44 * in question is not being used by a driver. 45 * Returns 0 on success. 46 */ 47 int pci_remove_device_safe(struct pci_dev *dev) 48 { 49 if (pci_dev_driver(dev)) 50 return -EBUSY; 51 pci_destroy_dev(dev); 52 return 0; 53 } 54 EXPORT_SYMBOL(pci_remove_device_safe); 55 56 void pci_remove_bus(struct pci_bus *pci_bus) 57 { 58 pci_proc_detach_bus(pci_bus); 59 60 spin_lock(&pci_bus_lock); 61 list_del(&pci_bus->node); 62 spin_unlock(&pci_bus_lock); 63 pci_remove_legacy_files(pci_bus); 64 class_device_remove_file(&pci_bus->class_dev, 65 &class_device_attr_cpuaffinity); 66 sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge"); 67 class_device_unregister(&pci_bus->class_dev); 68 } 69 EXPORT_SYMBOL(pci_remove_bus); 70 71 /** 72 * pci_remove_bus_device - remove a PCI device and any children 73 * @dev: the device to remove 74 * 75 * Remove a PCI device from the device lists, informing the drivers 76 * that the device has been removed. We also remove any subordinate 77 * buses and children in a depth-first manner. 78 * 79 * For each device we remove, delete the device structure from the 80 * device lists, remove the /proc entry, and notify userspace 81 * (/sbin/hotplug). 82 */ 83 void pci_remove_bus_device(struct pci_dev *dev) 84 { 85 if (dev->subordinate) { 86 struct pci_bus *b = dev->subordinate; 87 88 pci_remove_behind_bridge(dev); 89 pci_remove_bus(b); 90 dev->subordinate = NULL; 91 } 92 93 pci_destroy_dev(dev); 94 } 95 96 /** 97 * pci_remove_behind_bridge - remove all devices behind a PCI bridge 98 * @dev: PCI bridge device 99 * 100 * Remove all devices on the bus, except for the parent bridge. 101 * This also removes any child buses, and any devices they may 102 * contain in a depth-first manner. 103 */ 104 void pci_remove_behind_bridge(struct pci_dev *dev) 105 { 106 struct list_head *l, *n; 107 108 if (dev->subordinate) { 109 list_for_each_safe(l, n, &dev->subordinate->devices) { 110 struct pci_dev *dev = pci_dev_b(l); 111 112 pci_remove_bus_device(dev); 113 } 114 } 115 } 116 117 EXPORT_SYMBOL(pci_remove_bus_device); 118 EXPORT_SYMBOL(pci_remove_behind_bridge); 119