aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/remove.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-09-19 14:54:20 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-09-20 19:37:23 -0400
commit3891b6acb4f443cbe2e99367ee5e67c6bc29d446 (patch)
tree31f19d4d3ca748c526e0bb82a670613c6c71ca40 /drivers/pci/remove.c
parent94bb346480f8646871e5547491b5746ae0a643c3 (diff)
PCI: Stop all children first, before removing all children
This restores the previous behavior of stopping all child devices before removing any of them. The current SR-IOV design, where removing the PF also drops references on all the VFs, depends on having the VFs continue to exist after having been stopped. [bhelgaas: changelog] Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/remove.c')
-rw-r--r--drivers/pci/remove.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 4f9ca9162895..513972f3ed13 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -56,25 +56,13 @@ void pci_remove_bus(struct pci_bus *bus)
56} 56}
57EXPORT_SYMBOL(pci_remove_bus); 57EXPORT_SYMBOL(pci_remove_bus);
58 58
59/** 59static void pci_stop_bus_device(struct pci_dev *dev)
60 * pci_stop_and_remove_bus_device - remove a PCI device and any children
61 * @dev: the device to remove
62 *
63 * Remove a PCI device from the device lists, informing the drivers
64 * that the device has been removed. We also remove any subordinate
65 * buses and children in a depth-first manner.
66 *
67 * For each device we remove, delete the device structure from the
68 * device lists, remove the /proc entry, and notify userspace
69 * (/sbin/hotplug).
70 */
71void pci_stop_and_remove_bus_device(struct pci_dev *dev)
72{ 60{
73 struct pci_bus *bus = dev->subordinate; 61 struct pci_bus *bus = dev->subordinate;
74 struct pci_dev *child, *tmp; 62 struct pci_dev *child, *tmp;
75 63
76 /* 64 /*
77 * Removing an SR-IOV PF device removes all the associated VFs, 65 * Stopping an SR-IOV PF device removes all the associated VFs,
78 * which will update the bus->devices list and confuse the 66 * which will update the bus->devices list and confuse the
79 * iterator. Therefore, iterate in reverse so we remove the VFs 67 * iterator. Therefore, iterate in reverse so we remove the VFs
80 * first, then the PF. 68 * first, then the PF.
@@ -82,13 +70,44 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
82 if (bus) { 70 if (bus) {
83 list_for_each_entry_safe_reverse(child, tmp, 71 list_for_each_entry_safe_reverse(child, tmp,
84 &bus->devices, bus_list) 72 &bus->devices, bus_list)
85 pci_stop_and_remove_bus_device(child); 73 pci_stop_bus_device(child);
74 }
75
76 pci_stop_dev(dev);
77}
78
79static void pci_remove_bus_device(struct pci_dev *dev)
80{
81 struct pci_bus *bus = dev->subordinate;
82 struct pci_dev *child, *tmp;
83
84 if (bus) {
85 list_for_each_entry_safe(child, tmp,
86 &bus->devices, bus_list)
87 pci_remove_bus_device(child);
86 88
87 pci_remove_bus(bus); 89 pci_remove_bus(bus);
88 dev->subordinate = NULL; 90 dev->subordinate = NULL;
89 } 91 }
90 92
91 pci_stop_dev(dev);
92 pci_destroy_dev(dev); 93 pci_destroy_dev(dev);
93} 94}
95
96/**
97 * pci_stop_and_remove_bus_device - remove a PCI device and any children
98 * @dev: the device to remove
99 *
100 * Remove a PCI device from the device lists, informing the drivers
101 * that the device has been removed. We also remove any subordinate
102 * buses and children in a depth-first manner.
103 *
104 * For each device we remove, delete the device structure from the
105 * device lists, remove the /proc entry, and notify userspace
106 * (/sbin/hotplug).
107 */
108void pci_stop_and_remove_bus_device(struct pci_dev *dev)
109{
110 pci_stop_bus_device(dev);
111 pci_remove_bus_device(dev);
112}
94EXPORT_SYMBOL(pci_stop_and_remove_bus_device); 113EXPORT_SYMBOL(pci_stop_and_remove_bus_device);