Commit 24f8aa9b464b73e0553f092b747770940ee0ea54
Committed by
Greg Kroah-Hartman
1 parent
9b1d19ee86
Exists in
master
and in
4 other branches
PCI: add pci_stop_bus_device
This patch adds pci_stop_bus_device() which stops a PCI device (detach the driver, remove from the global list and so on) and any children. This is needed for ACPI based PCI-to-PCI bridge hot-remove, and it will be also needed for ACPI based PCI root bridge hot-remove. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> Signed-off-by: Satoru Takeuchi <takeuchi_satoru@jp.fujitsu.com> Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Showing 2 changed files with 37 additions and 1 deletions Side-by-side Diff
drivers/pci/remove.c
... | ... | @@ -16,8 +16,11 @@ |
16 | 16 | } |
17 | 17 | } |
18 | 18 | |
19 | -static void pci_destroy_dev(struct pci_dev *dev) | |
19 | +static void pci_stop_dev(struct pci_dev *dev) | |
20 | 20 | { |
21 | + if (!dev->global_list.next) | |
22 | + return; | |
23 | + | |
21 | 24 | if (!list_empty(&dev->global_list)) { |
22 | 25 | pci_proc_detach_device(dev); |
23 | 26 | pci_remove_sysfs_dev_files(dev); |
24 | 27 | |
... | ... | @@ -27,7 +30,12 @@ |
27 | 30 | dev->global_list.next = dev->global_list.prev = NULL; |
28 | 31 | up_write(&pci_bus_sem); |
29 | 32 | } |
33 | +} | |
30 | 34 | |
35 | +static void pci_destroy_dev(struct pci_dev *dev) | |
36 | +{ | |
37 | + pci_stop_dev(dev); | |
38 | + | |
31 | 39 | /* Remove the device from the device lists, and prevent any further |
32 | 40 | * list accesses from this device */ |
33 | 41 | down_write(&pci_bus_sem); |
34 | 42 | |
... | ... | @@ -119,6 +127,33 @@ |
119 | 127 | } |
120 | 128 | } |
121 | 129 | |
130 | +static void pci_stop_bus_devices(struct pci_bus *bus) | |
131 | +{ | |
132 | + struct list_head *l, *n; | |
133 | + | |
134 | + list_for_each_safe(l, n, &bus->devices) { | |
135 | + struct pci_dev *dev = pci_dev_b(l); | |
136 | + pci_stop_bus_device(dev); | |
137 | + } | |
138 | +} | |
139 | + | |
140 | +/** | |
141 | + * pci_stop_bus_device - stop a PCI device and any children | |
142 | + * @dev: the device to stop | |
143 | + * | |
144 | + * Stop a PCI device (detach the driver, remove from the global list | |
145 | + * and so on). This also stop any subordinate buses and children in a | |
146 | + * depth-first manner. | |
147 | + */ | |
148 | +void pci_stop_bus_device(struct pci_dev *dev) | |
149 | +{ | |
150 | + if (dev->subordinate) | |
151 | + pci_stop_bus_devices(dev->subordinate); | |
152 | + | |
153 | + pci_stop_dev(dev); | |
154 | +} | |
155 | + | |
122 | 156 | EXPORT_SYMBOL(pci_remove_bus_device); |
123 | 157 | EXPORT_SYMBOL(pci_remove_behind_bridge); |
158 | +EXPORT_SYMBOL_GPL(pci_stop_bus_device); |
include/linux/pci.h
... | ... | @@ -441,6 +441,7 @@ |
441 | 441 | extern void pci_dev_put(struct pci_dev *dev); |
442 | 442 | extern void pci_remove_bus(struct pci_bus *b); |
443 | 443 | extern void pci_remove_bus_device(struct pci_dev *dev); |
444 | +extern void pci_stop_bus_device(struct pci_dev *dev); | |
444 | 445 | void pci_setup_cardbus(struct pci_bus *bus); |
445 | 446 | |
446 | 447 | /* Generic PCI functions exported to card drivers */ |