diff options
Diffstat (limited to 'drivers/acpi/glue.c')
| -rw-r--r-- | drivers/acpi/glue.c | 66 | 
1 files changed, 49 insertions, 17 deletions
| diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 7a33a6d985f8..7cd0009e7ff3 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -17,6 +17,8 @@  #include <linux/rwsem.h>  #include <linux/acpi.h>  #include <linux/dma-mapping.h> +#include <linux/pci.h> +#include <linux/pci-acpi.h>  #include <linux/platform_device.h>  #include "internal.h" @@ -111,13 +113,10 @@ struct acpi_device *acpi_find_child_device(struct acpi_device *parent,  		return NULL;  	list_for_each_entry(adev, &parent->children, node) { -		unsigned long long addr; -		acpi_status status; +		acpi_bus_address addr = acpi_device_adr(adev);  		int score; -		status = acpi_evaluate_integer(adev->handle, METHOD_NAME__ADR, -					       NULL, &addr); -		if (ACPI_FAILURE(status) || addr != address) +		if (!adev->pnp.type.bus_address || addr != address)  			continue;  		if (!ret) { @@ -287,12 +286,13 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one);  void acpi_device_notify(struct device *dev)  { -	struct acpi_bus_type *type = acpi_get_bus_type(dev);  	struct acpi_device *adev;  	int ret;  	ret = acpi_bind_one(dev, NULL);  	if (ret) { +		struct acpi_bus_type *type = acpi_get_bus_type(dev); +  		if (!type)  			goto err; @@ -304,17 +304,26 @@ void acpi_device_notify(struct device *dev)  		ret = acpi_bind_one(dev, adev);  		if (ret)  			goto err; -	} -	adev = ACPI_COMPANION(dev); -	if (dev_is_platform(dev)) -		acpi_configure_pmsi_domain(dev); +		if (type->setup) { +			type->setup(dev); +			goto done; +		} +	} else { +		adev = ACPI_COMPANION(dev); + +		if (dev_is_pci(dev)) { +			pci_acpi_setup(dev, adev); +			goto done; +		} else if (dev_is_platform(dev)) { +			acpi_configure_pmsi_domain(dev); +		} +	} -	if (type && type->setup) -		type->setup(dev); -	else if (adev->handler && adev->handler->bind) +	if (adev->handler && adev->handler->bind)  		adev->handler->bind(dev); +done:  	acpi_handle_debug(ACPI_HANDLE(dev), "Bound to device %s\n",  			  dev_name(dev)); @@ -327,16 +336,39 @@ err:  void acpi_device_notify_remove(struct device *dev)  {  	struct acpi_device *adev = ACPI_COMPANION(dev); -	struct acpi_bus_type *type;  	if (!adev)  		return; -	type = acpi_get_bus_type(dev); -	if (type && type->cleanup) -		type->cleanup(dev); +	if (dev_is_pci(dev)) +		pci_acpi_cleanup(dev, adev);  	else if (adev->handler && adev->handler->unbind)  		adev->handler->unbind(dev);  	acpi_unbind_one(dev);  } + +int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used) +{ +	struct acpi_device *adev = to_acpi_device(dev); + +	/* +	 * Skip device objects with device IDs, because they may be in use even +	 * if they are not companions of any physical device objects. +	 */ +	if (adev->pnp.type.hardware_id) +		return 0; + +	mutex_lock(&adev->physical_node_lock); + +	/* +	 * Device objects without device IDs are not in use if they have no +	 * corresponding physical device objects. +	 */ +	if (list_empty(&adev->physical_node_list)) +		acpi_device_set_power(adev, ACPI_STATE_D3_COLD); + +	mutex_unlock(&adev->physical_node_lock); + +	return 0; +} | 
