diff options
author | Satoru Takeuchi <takeuchi_satoru@jp.fujitsu.com> | 2006-09-12 13:16:36 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-26 20:43:54 -0400 |
commit | 24f8aa9b464b73e0553f092b747770940ee0ea54 (patch) | |
tree | e42b0d8d8b57c17da943a5c1cd8748dc8a04880b /drivers/pci | |
parent | 9b1d19ee86746618a8b43d2aaef8319c01af1514 (diff) |
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>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/remove.c | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 99ffbd478b29..430281b2e921 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
@@ -16,8 +16,11 @@ static void pci_free_resources(struct pci_dev *dev) | |||
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 | if (!list_empty(&dev->global_list)) { | 24 | if (!list_empty(&dev->global_list)) { |
22 | pci_proc_detach_device(dev); | 25 | pci_proc_detach_device(dev); |
23 | pci_remove_sysfs_dev_files(dev); | 26 | pci_remove_sysfs_dev_files(dev); |
@@ -27,6 +30,11 @@ static void pci_destroy_dev(struct pci_dev *dev) | |||
27 | dev->global_list.next = dev->global_list.prev = NULL; | 30 | dev->global_list.next = dev->global_list.prev = NULL; |
28 | up_write(&pci_bus_sem); | 31 | up_write(&pci_bus_sem); |
29 | } | 32 | } |
33 | } | ||
34 | |||
35 | static void pci_destroy_dev(struct pci_dev *dev) | ||
36 | { | ||
37 | pci_stop_dev(dev); | ||
30 | 38 | ||
31 | /* Remove the device from the device lists, and prevent any further | 39 | /* Remove the device from the device lists, and prevent any further |
32 | * list accesses from this device */ | 40 | * list accesses from this device */ |
@@ -119,5 +127,32 @@ void pci_remove_behind_bridge(struct pci_dev *dev) | |||
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 | EXPORT_SYMBOL(pci_remove_bus_device); | 156 | EXPORT_SYMBOL(pci_remove_bus_device); |
123 | EXPORT_SYMBOL(pci_remove_behind_bridge); | 157 | EXPORT_SYMBOL(pci_remove_behind_bridge); |
158 | EXPORT_SYMBOL_GPL(pci_stop_bus_device); | ||