Skip to content

Commit

Permalink
Merge branch 'pci/yinghai-revert-pci_find_bus-and-remove-cleanup' int…
Browse files Browse the repository at this point in the history
…o 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()"
  • Loading branch information
Bjorn Helgaas committed Sep 21, 2012
2 parents 9b9a6d2 + 3891b6a commit 168ae6a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 18 deletions.
8 changes: 6 additions & 2 deletions drivers/pci/iov.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,15 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
static void virtfn_remove(struct pci_dev *dev, int id, int reset)
{
char buf[VIRTFN_ID_LEN];
struct pci_bus *bus;
struct pci_dev *virtfn;
struct pci_sriov *iov = dev->sriov;

virtfn = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus),
virtfn_bus(dev, id), virtfn_devfn(dev, id));
bus = pci_find_bus(pci_domain_nr(dev->bus), virtfn_bus(dev, id));
if (!bus)
return;

virtfn = pci_get_slot(bus, virtfn_devfn(dev, id));
if (!virtfn)
return;

Expand Down
51 changes: 35 additions & 16 deletions drivers/pci/remove.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,39 +56,58 @@ void pci_remove_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL(pci_remove_bus);

/**
* pci_stop_and_remove_bus_device - remove a PCI device and any children
* @dev: the device to remove
*
* Remove a PCI device from the device lists, informing the drivers
* that the device has been removed. We also remove any subordinate
* buses and children in a depth-first manner.
*
* For each device we remove, delete the device structure from the
* device lists, remove the /proc entry, and notify userspace
* (/sbin/hotplug).
*/
void pci_stop_and_remove_bus_device(struct pci_dev *dev)
static void pci_stop_bus_device(struct pci_dev *dev)
{
struct pci_bus *bus = dev->subordinate;
struct pci_dev *child, *tmp;

/*
* Removing an SR-IOV PF device removes all the associated VFs,
* Stopping an SR-IOV PF device removes all the associated VFs,
* which will update the bus->devices list and confuse the
* iterator. Therefore, iterate in reverse so we remove the VFs
* first, then the PF.
*/
if (bus) {
list_for_each_entry_safe_reverse(child, tmp,
&bus->devices, bus_list)
pci_stop_and_remove_bus_device(child);
pci_stop_bus_device(child);
}

pci_stop_dev(dev);
}

static void pci_remove_bus_device(struct pci_dev *dev)
{
struct pci_bus *bus = dev->subordinate;
struct pci_dev *child, *tmp;

if (bus) {
list_for_each_entry_safe(child, tmp,
&bus->devices, bus_list)
pci_remove_bus_device(child);

pci_remove_bus(bus);
dev->subordinate = NULL;
}

pci_stop_dev(dev);
pci_destroy_dev(dev);
}

/**
* pci_stop_and_remove_bus_device - remove a PCI device and any children
* @dev: the device to remove
*
* Remove a PCI device from the device lists, informing the drivers
* that the device has been removed. We also remove any subordinate
* buses and children in a depth-first manner.
*
* For each device we remove, delete the device structure from the
* device lists, remove the /proc entry, and notify userspace
* (/sbin/hotplug).
*/
void pci_stop_and_remove_bus_device(struct pci_dev *dev)
{
pci_stop_bus_device(dev);
pci_remove_bus_device(dev);
}
EXPORT_SYMBOL(pci_stop_and_remove_bus_device);

0 comments on commit 168ae6a

Please sign in to comment.