Skip to content

Commit c10383e

Browse files
committed
ACPI: scan: Release PM resources blocked by unused objects
On some systems the ACPI namespace contains device objects that are not used in certain configurations of the system. If they start off in the D0 power state configuration, they will stay in it until the system reboots, because of the lack of any mechanism possibly causing their configuration to change. If that happens, they may prevent some power resources from being turned off or generally they may prevent the platform from getting into the deepest low-power states thus causing some energy to be wasted. Address this issue by changing the configuration of unused ACPI device objects to the D3cold power state one after carrying out the ACPI-based enumeration of devices. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214091 Link: https://lore.kernel.org/linux-acpi/[email protected]/ Reported-by: Mario Limonciello <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]> Tested-by: Mario Limonciello <[email protected]>
1 parent 64570fb commit c10383e

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

drivers/acpi/glue.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,3 +340,28 @@ void acpi_device_notify_remove(struct device *dev)
340340

341341
acpi_unbind_one(dev);
342342
}
343+
344+
int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used)
345+
{
346+
struct acpi_device *adev = to_acpi_device(dev);
347+
348+
/*
349+
* Skip device objects with device IDs, because they may be in use even
350+
* if they are not companions of any physical device objects.
351+
*/
352+
if (adev->pnp.type.hardware_id)
353+
return 0;
354+
355+
mutex_lock(&adev->physical_node_lock);
356+
357+
/*
358+
* Device objects without device IDs are not in use if they have no
359+
* corresponding physical device objects.
360+
*/
361+
if (list_empty(&adev->physical_node_list))
362+
acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
363+
364+
mutex_unlock(&adev->physical_node_lock);
365+
366+
return 0;
367+
}

drivers/acpi/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ bool acpi_device_is_battery(struct acpi_device *adev);
117117
bool acpi_device_is_first_physical_node(struct acpi_device *adev,
118118
const struct device *dev);
119119
int acpi_bus_register_early_device(int type);
120+
int acpi_dev_turn_off_if_unused(struct device *dev, void *not_used);
120121

121122
/* --------------------------------------------------------------------------
122123
Device Matching and Notification

drivers/acpi/scan.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,12 @@ int __init acpi_scan_init(void)
25592559
}
25602560
}
25612561

2562+
/*
2563+
* Make sure that power management resources are not blocked by ACPI
2564+
* device objects with no users.
2565+
*/
2566+
bus_for_each_dev(&acpi_bus_type, NULL, NULL, acpi_dev_turn_off_if_unused);
2567+
25622568
acpi_turn_off_unused_power_resources();
25632569

25642570
acpi_scan_initialized = true;

0 commit comments

Comments
 (0)