Skip to content

Commit 6381195

Browse files
committed
ACPI: power: Rework turning off unused power resources
Make turning off unused power resources (after the enumeration of devices and during system-wide resume from S3) more straightforward by using the observation that the power resource state stored in struct acpi_power_resource can be used to determine whether or not the give power resource has any users. Namely, when the state of the power resource is unknown, its _STA method has never been evaluated (or the evaluation of it has failed) and its _ON and _OFF methods have never been executed (or they have failed to execute), so for all practical purposes it can be assumed to have no users (or to be unusable). Therefore, instead of checking the number of power resource users, it is sufficient to check if its state is known. Moreover, if the last known state of a given power resource is "off", it is not necessary to turn it off, because it has been used to initialize the power state or the wakeup power resources list of at least one device and either its _STA method has returned 0 ("off"), or its _OFF method has been successfully executed already. Accordingly, modify acpi_turn_off_unused_power_resources() to do the above checks (which are suitable for both uses of it) instead of using the number of power resource users or evaluating its _STA method, drop its argument (which is not useful any more) and update its callers. Also drop the users field from struct acpi_power_resource as it is not useful any more. Tested-by: Dave Olsthoorn <dave@bewaar.me> Tested-by: Shujun Wang <wsj20369@163.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent ca84f18 commit 6381195

4 files changed

Lines changed: 14 additions & 37 deletions

File tree

drivers/acpi/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
142142
int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
143143
int acpi_power_on_resources(struct acpi_device *device, int state);
144144
int acpi_power_transition(struct acpi_device *device, int state);
145-
void acpi_turn_off_unused_power_resources(bool init);
145+
void acpi_turn_off_unused_power_resources(void);
146146

147147
/* --------------------------------------------------------------------------
148148
Device Power Management

drivers/acpi/power.c

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ struct acpi_power_resource {
5252
u32 system_level;
5353
u32 order;
5454
unsigned int ref_count;
55-
unsigned int users;
5655
u8 state;
5756
bool wakeup_enabled;
5857
struct mutex resource_lock;
@@ -174,8 +173,6 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
174173
err = acpi_power_resources_list_add(rhandle, list);
175174
if (err)
176175
break;
177-
178-
to_power_resource(rdev)->users++;
179176
}
180177
if (err)
181178
acpi_power_resources_list_free(list);
@@ -1018,39 +1015,10 @@ void acpi_resume_power_resources(void)
10181015
}
10191016
#endif
10201017

1021-
static void acpi_power_turn_off_if_unused(struct acpi_power_resource *resource,
1022-
bool init)
1023-
{
1024-
if (resource->ref_count > 0)
1025-
return;
1026-
1027-
if (init) {
1028-
if (resource->users > 0)
1029-
return;
1030-
} else {
1031-
int result;
1032-
u8 state;
1033-
1034-
result = acpi_power_get_state(resource->device.handle, &state);
1035-
if (result || state == ACPI_POWER_RESOURCE_STATE_OFF)
1036-
return;
1037-
}
1038-
1039-
dev_info(&resource->device.dev, "Turning OFF\n");
1040-
__acpi_power_off(resource);
1041-
}
1042-
10431018
/**
10441019
* acpi_turn_off_unused_power_resources - Turn off power resources not in use.
1045-
* @init: Control switch.
1046-
*
1047-
* If @ainit is set, unconditionally turn off all of the ACPI power resources
1048-
* without any users.
1049-
*
1050-
* Otherwise, turn off all ACPI power resources without active references (that
1051-
* is, the ones that should be "off" at the moment) that are "on".
10521020
*/
1053-
void acpi_turn_off_unused_power_resources(bool init)
1021+
void acpi_turn_off_unused_power_resources(void)
10541022
{
10551023
struct acpi_power_resource *resource;
10561024

@@ -1059,7 +1027,16 @@ void acpi_turn_off_unused_power_resources(bool init)
10591027
list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) {
10601028
mutex_lock(&resource->resource_lock);
10611029

1062-
acpi_power_turn_off_if_unused(resource, init);
1030+
/*
1031+
* Turn off power resources in an unknown state too, because the
1032+
* platform firmware on some system expects the OS to turn off
1033+
* power resources without any users unconditionally.
1034+
*/
1035+
if (!resource->ref_count &&
1036+
resource->state != ACPI_POWER_RESOURCE_STATE_OFF) {
1037+
dev_info(&resource->device.dev, "Turning OFF\n");
1038+
__acpi_power_off(resource);
1039+
}
10631040

10641041
mutex_unlock(&resource->resource_lock);
10651042
}

drivers/acpi/scan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2360,7 +2360,7 @@ int __init acpi_scan_init(void)
23602360
}
23612361
}
23622362

2363-
acpi_turn_off_unused_power_resources(true);
2363+
acpi_turn_off_unused_power_resources();
23642364

23652365
acpi_scan_initialized = true;
23662366

drivers/acpi/sleep.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ static void acpi_pm_start(u32 acpi_state)
504504
*/
505505
static void acpi_pm_end(void)
506506
{
507-
acpi_turn_off_unused_power_resources(false);
507+
acpi_turn_off_unused_power_resources();
508508
acpi_scan_lock_release();
509509
/*
510510
* This is necessary in case acpi_pm_finish() is not called during a

0 commit comments

Comments
 (0)