diff options
Diffstat (limited to 'drivers')
| -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); |
