diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 803d9ddd6e75..a33794d9e0dc 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -38,6 +38,8 @@ * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() * when the bridge is scanned and it loses a refcount when the bridge * is removed. + * - When a P2P bridge is present, we elevate the refcount on the subordinate + * bus. It loses the refcount when the the driver unloads. */ #include @@ -440,6 +442,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) goto err; } + /* + * Grab a ref to the subordinate PCI bus in case the bus is + * removed via PCI core logical hotplug. The ref pins the bus + * (which we access during module unload). + */ + get_device(&bridge->pci_bus->dev); spin_lock_init(&bridge->res_lock); init_bridge_misc(bridge); @@ -619,6 +627,12 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) slot = next; } + /* + * Only P2P bridges have a pci_dev + */ + if (bridge->pci_dev) + put_device(&bridge->pci_bus->dev); + pci_dev_put(bridge->pci_dev); list_del(&bridge->list); kfree(bridge);