Commit c4ed02fa authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Jesse Barnes

PCI: Fix reference counting bug

pci_get_subsys() will decrement the reference count of the device that
it starts searching from.  Unfortunately, the pci_find_device() interface
will already have decremented the reference count of the device earlier,
so the device will end up losing all reference counts and be freed.

We can fix this by incrementing the reference count of the device to
start searching from before calling pci_get_subsys().
Signed-off-by: default avatarMatthew Wilcox <willy@linux.intel.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent d389fec6
...@@ -166,6 +166,7 @@ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, ...@@ -166,6 +166,7 @@ struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
{ {
struct pci_dev *pdev; struct pci_dev *pdev;
pci_dev_get(from);
pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
pci_dev_put(pdev); pci_dev_put(pdev);
return pdev; return pdev;
...@@ -270,12 +271,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, ...@@ -270,12 +271,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
WARN_ON(in_interrupt()); WARN_ON(in_interrupt());
if (from) { if (from)
/* FIXME dev_start = &from->dev;
* take the cast off, when bus_find_device is made const.
*/
dev_start = (struct device *)&from->dev;
}
dev = bus_find_device(&pci_bus_type, dev_start, (void *)id, dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
match_pci_dev_by_id); match_pci_dev_by_id);
if (dev) if (dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment