|
@@ -32,9 +32,6 @@
|
|
|
|
|
|
/*
|
|
|
* Lifetime rules for pci_dev:
|
|
|
- * - The one in acpiphp_func has its refcount elevated by pci_get_slot()
|
|
|
- * when the driver is loaded or when an insertion event occurs. It loses
|
|
|
- * a refcount when its ejected or the driver unloads.
|
|
|
* - 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.
|
|
@@ -130,6 +127,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
|
|
unsigned long long adr, sun;
|
|
|
int device, function, retval;
|
|
|
struct pci_bus *pbus = bridge->pci_bus;
|
|
|
+ struct pci_dev *pdev;
|
|
|
|
|
|
if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
|
|
|
return AE_OK;
|
|
@@ -213,10 +211,10 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
|
|
newfunc->slot = slot;
|
|
|
list_add_tail(&newfunc->sibling, &slot->funcs);
|
|
|
|
|
|
- /* associate corresponding pci_dev */
|
|
|
- newfunc->pci_dev = pci_get_slot(pbus, PCI_DEVFN(device, function));
|
|
|
- if (newfunc->pci_dev) {
|
|
|
+ pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
|
|
|
+ if (pdev) {
|
|
|
slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
|
|
|
+ pci_dev_put(pdev);
|
|
|
}
|
|
|
|
|
|
if (is_dock_device(handle)) {
|
|
@@ -617,7 +615,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
|
|
|
if (ACPI_FAILURE(status))
|
|
|
err("failed to remove notify handler\n");
|
|
|
}
|
|
|
- pci_dev_put(func->pci_dev);
|
|
|
list_del(list);
|
|
|
kfree(func);
|
|
|
}
|
|
@@ -1101,22 +1098,24 @@ static int __ref enable_device(struct acpiphp_slot *slot)
|
|
|
pci_enable_bridges(bus);
|
|
|
pci_bus_add_devices(bus);
|
|
|
|
|
|
- /* associate pci_dev to our representation */
|
|
|
list_for_each (l, &slot->funcs) {
|
|
|
func = list_entry(l, struct acpiphp_func, sibling);
|
|
|
- func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
|
|
|
- func->function));
|
|
|
- if (!func->pci_dev)
|
|
|
+ dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
|
|
|
+ func->function));
|
|
|
+ if (!dev)
|
|
|
continue;
|
|
|
|
|
|
- if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
|
|
|
- func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS)
|
|
|
+ if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
|
|
|
+ dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) {
|
|
|
+ pci_dev_put(dev);
|
|
|
continue;
|
|
|
+ }
|
|
|
|
|
|
status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
|
|
|
if (ACPI_FAILURE(status))
|
|
|
warn("find_p2p_bridge failed (error code = 0x%x)\n",
|
|
|
status);
|
|
|
+ pci_dev_put(dev);
|
|
|
}
|
|
|
|
|
|
slot->flags |= SLOT_ENABLED;
|
|
@@ -1142,17 +1141,14 @@ static void disable_bridges(struct pci_bus *bus)
|
|
|
*/
|
|
|
static int disable_device(struct acpiphp_slot *slot)
|
|
|
{
|
|
|
- int retval = 0;
|
|
|
struct acpiphp_func *func;
|
|
|
- struct list_head *l;
|
|
|
+ struct pci_dev *pdev;
|
|
|
|
|
|
/* is this slot already disabled? */
|
|
|
if (!(slot->flags & SLOT_ENABLED))
|
|
|
goto err_exit;
|
|
|
|
|
|
- list_for_each (l, &slot->funcs) {
|
|
|
- func = list_entry(l, struct acpiphp_func, sibling);
|
|
|
-
|
|
|
+ list_for_each_entry(func, &slot->funcs, sibling) {
|
|
|
if (func->bridge) {
|
|
|
/* cleanup p2p bridges under this P2P bridge */
|
|
|
cleanup_p2p_bridge(func->bridge->handle,
|
|
@@ -1160,35 +1156,28 @@ static int disable_device(struct acpiphp_slot *slot)
|
|
|
func->bridge = NULL;
|
|
|
}
|
|
|
|
|
|
- if (func->pci_dev) {
|
|
|
- pci_stop_bus_device(func->pci_dev);
|
|
|
- if (func->pci_dev->subordinate) {
|
|
|
- disable_bridges(func->pci_dev->subordinate);
|
|
|
- pci_disable_device(func->pci_dev);
|
|
|
+ pdev = pci_get_slot(slot->bridge->pci_bus,
|
|
|
+ PCI_DEVFN(slot->device, func->function));
|
|
|
+ if (pdev) {
|
|
|
+ pci_stop_bus_device(pdev);
|
|
|
+ if (pdev->subordinate) {
|
|
|
+ disable_bridges(pdev->subordinate);
|
|
|
+ pci_disable_device(pdev);
|
|
|
}
|
|
|
+ pci_remove_bus_device(pdev);
|
|
|
+ pci_dev_put(pdev);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- list_for_each (l, &slot->funcs) {
|
|
|
- func = list_entry(l, struct acpiphp_func, sibling);
|
|
|
-
|
|
|
+ list_for_each_entry(func, &slot->funcs, sibling) {
|
|
|
acpiphp_unconfigure_ioapics(func->handle);
|
|
|
acpiphp_bus_trim(func->handle);
|
|
|
- /* try to remove anyway.
|
|
|
- * acpiphp_bus_add might have been failed */
|
|
|
-
|
|
|
- if (!func->pci_dev)
|
|
|
- continue;
|
|
|
-
|
|
|
- pci_remove_bus_device(func->pci_dev);
|
|
|
- pci_dev_put(func->pci_dev);
|
|
|
- func->pci_dev = NULL;
|
|
|
}
|
|
|
|
|
|
slot->flags &= (~SLOT_ENABLED);
|
|
|
|
|
|
- err_exit:
|
|
|
- return retval;
|
|
|
+err_exit:
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|