diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 63 | 
1 files changed, 26 insertions, 37 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a33794d9e0d..3a6064bce56 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -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;  }  |