Commit 24f8aa9b464b73e0553f092b747770940ee0ea54

Authored by Satoru Takeuchi
Committed by Greg Kroah-Hartman
1 parent 9b1d19ee86

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);
... ... @@ -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 */