diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-17 14:11:05 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-01-17 14:11:05 +0100 |
commit | bc9b6407bd6df3ab7189e5622816bbc11ae9d2d8 (patch) | |
tree | 8f44ae6c9750b271eb423787e19db1288b53c42e /drivers/acpi/scan.c | |
parent | 6a8dd80821c215bc49bf6b108e85c1738c82bf43 (diff) | |
download | talos-op-linux-bc9b6407bd6df3ab7189e5622816bbc11ae9d2d8.tar.gz talos-op-linux-bc9b6407bd6df3ab7189e5622816bbc11ae9d2d8.zip |
ACPI / PM: Rework the handling of devices depending on power resources
Commit 0090def6 (ACPI: Add interface to register/unregister device
to/from power resources) made it possible to indicate to the ACPI
core that if the given device depends on any power resources, then
it should be resumed as soon as all of the power resources required
by it to transition to the D0 power state have been turned on.
Unfortunately, however, this was a mistake, because all devices
depending on power resources should be treated this way (i.e. they
should be resumed when all power resources required by their D0
state have been turned on) and for the majority of those devices
the ACPI core can figure out by itself which (physical) devices
depend on what power resources.
For this reason, replace the code added by commit 0090def6 with a
new, much more straightforward, mechanism that will be used
internally by the ACPI core and remove all references to that code
from kernel subsystems using ACPI.
For the cases when there are (physical) devices that should be
resumed whenever a not directly related ACPI device node goes into
D0 as a result of power resources configuration changes, like in
the SATA case, add two new routines, acpi_dev_pm_add_dependent()
and acpi_dev_pm_remove_dependent(), allowing subsystems to manage
such dependencies. Convert the SATA subsystem to use the new
functions accordingly.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7d164a966b0d..c6d60910e8a8 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -633,6 +633,7 @@ static int acpi_device_register(struct acpi_device *device) INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->physical_node_list); mutex_init(&device->physical_node_lock); + INIT_LIST_HEAD(&device->power_dependent); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); if (!new_bus_id) { @@ -706,8 +707,14 @@ static void acpi_device_unregister(struct acpi_device *device) acpi_detach_data(device->handle, acpi_bus_data_handler); + acpi_power_add_remove_device(device, false); acpi_device_remove_files(device); device_unregister(&device->dev); + /* + * Drop the reference counts of all power resources the device depends + * on and turn off the ones that have no more references. + */ + acpi_power_transition(device, ACPI_STATE_D3_COLD); } /* -------------------------------------------------------------------------- @@ -1441,6 +1448,7 @@ static int acpi_add_single_object(struct acpi_device **child, end: if (!result) { + acpi_power_add_remove_device(device, true); acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Adding %s [%s] parent %s\n", dev_name(&device->dev), |