diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2012-09-21 12:57:20 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2012-09-21 12:57:20 -0400 |
commit | 168ae6a08aa6e0cf8b0166dedeb675a20af1fbb7 (patch) | |
tree | 31f19d4d3ca748c526e0bb82a670613c6c71ca40 | |
parent | 9b9a6d261616bed589302bc6244c5bd7c99a733f (diff) | |
parent | 3891b6acb4f443cbe2e99367ee5e67c6bc29d446 (diff) |
Merge branch 'pci/yinghai-revert-pci_find_bus-and-remove-cleanup' into next
* pci/yinghai-revert-pci_find_bus-and-remove-cleanup:
PCI: Stop all children first, before removing all children
Revert "PCI: Use hotplug-safe pci_get_domain_bus_and_slot()"
-rw-r--r-- | drivers/pci/iov.c | 8 | ||||
-rw-r--r-- | drivers/pci/remove.c | 51 |
2 files changed, 41 insertions, 18 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index b0fe7712b4d4..aeccc911abb8 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -152,11 +152,15 @@ failed1: | |||
152 | static void virtfn_remove(struct pci_dev *dev, int id, int reset) | 152 | static void virtfn_remove(struct pci_dev *dev, int id, int reset) |
153 | { | 153 | { |
154 | char buf[VIRTFN_ID_LEN]; | 154 | char buf[VIRTFN_ID_LEN]; |
155 | struct pci_bus *bus; | ||
155 | struct pci_dev *virtfn; | 156 | struct pci_dev *virtfn; |
156 | struct pci_sriov *iov = dev->sriov; | 157 | struct pci_sriov *iov = dev->sriov; |
157 | 158 | ||
158 | virtfn = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus), | 159 | bus = pci_find_bus(pci_domain_nr(dev->bus), virtfn_bus(dev, id)); |
159 | virtfn_bus(dev, id), virtfn_devfn(dev, id)); | 160 | if (!bus) |
161 | return; | ||
162 | |||
163 | virtfn = pci_get_slot(bus, virtfn_devfn(dev, id)); | ||
160 | if (!virtfn) | 164 | if (!virtfn) |
161 | return; | 165 | return; |
162 | 166 | ||
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 | } |
57 | EXPORT_SYMBOL(pci_remove_bus); | 57 | EXPORT_SYMBOL(pci_remove_bus); |
58 | 58 | ||
59 | /** | 59 | static 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 | */ | ||
71 | void 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 | |||
79 | static 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 | */ | ||
108 | void pci_stop_and_remove_bus_device(struct pci_dev *dev) | ||
109 | { | ||
110 | pci_stop_bus_device(dev); | ||
111 | pci_remove_bus_device(dev); | ||
112 | } | ||
94 | EXPORT_SYMBOL(pci_stop_and_remove_bus_device); | 113 | EXPORT_SYMBOL(pci_stop_and_remove_bus_device); |