From 94bb346480f8646871e5547491b5746ae0a643c3 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 20 Sep 2012 17:09:48 -0600 Subject: [PATCH] Revert "PCI: Use hotplug-safe pci_get_domain_bus_and_slot()" This reverts commit 433efd2247b0cbf5e7e86275e1f21281d3b99047. When we remove an SR-IOV device, we have this call chain: driver .remove() method pci_disable_sriov() sriov_disable() virtfn_remove() pci_get_domain_bus_and_slot() sriov_disable() is only called for PFs, not for VFs. When it's called for a PF, it loops through all the VFs and calls virtfn_remove() for each. But we stop and remove VFs before PFs, so by the time we get to virtfn_remove(), the VFs have already been stopped and deleted from the device list. Now pci_get_domain_bus_and_slot(), which uses bus_find_device() and relies on that device list, doesn't find the VFs, so the VF references aren't released correctly. Reported-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 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: 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;