Skip to content

Commit 2f4edfa

Browse files
committed
Merge branches 'acpi-pm', 'acpi-processor' and 'acpi-resources'
* acpi-pm: ACPI: PM: postpone bringing devices to D0 unless we need them ACPI: PM: Adjust behavior for field problems on AMD systems ACPI: PM: s2idle: Add support for new Microsoft UUID ACPI: PM: s2idle: Add support for multiple func mask ACPI: PM: s2idle: Refactor common code ACPI: PM: s2idle: Use correct revision id ACPI: power: Use dev_dbg() to print some messages ACPI: sleep: Fix acpi_pm_pre_suspend() kernel-doc ACPI: power: Rework turning off unused power resources ACPI: power: Save the last known state of each power resource ACPI: power: Use u8 as the power resource state data type ACPI: PM / fan: Put fan device IDs into separate header file ACPI: PM: s2idle: Add missing LPS0 functions for AMD * acpi-processor: ACPI: processor_throttling: Fix several coding style issues ACPI: processor_throttling: Remove redundant initialization of 'obj' ACPI: processor idle: Fix up C-state latency if not ordered * acpi-resources: ACPI: resources: Add checks for ACPI IRQ override
4 parents dfef771 + f7599be + 2ef53bf + 0ec4e55 commit 2f4edfa

File tree

11 files changed

+266
-131
lines changed

11 files changed

+266
-131
lines changed

drivers/acpi/device_pm.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/pm_runtime.h>
2121
#include <linux/suspend.h>
2222

23+
#include "fan.h"
2324
#include "internal.h"
2425

2526
/**
@@ -1133,19 +1134,48 @@ static int acpi_subsys_resume_noirq(struct device *dev)
11331134
*
11341135
* Use ACPI to put the given device into the full-power state and carry out the
11351136
* generic early resume procedure for it during system transition into the
1136-
* working state.
1137+
* working state, but only do that if device either defines early resume
1138+
* handler, or does not define power operations at all. Otherwise powering up
1139+
* of the device is postponed to the normal resume phase.
11371140
*/
11381141
static int acpi_subsys_resume_early(struct device *dev)
11391142
{
1143+
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
11401144
int ret;
11411145

11421146
if (dev_pm_skip_resume(dev))
11431147
return 0;
11441148

1149+
if (pm && !pm->resume_early) {
1150+
dev_dbg(dev, "postponing D0 transition to normal resume stage\n");
1151+
return 0;
1152+
}
1153+
11451154
ret = acpi_dev_resume(dev);
11461155
return ret ? ret : pm_generic_resume_early(dev);
11471156
}
11481157

1158+
/**
1159+
* acpi_subsys_resume - Resume device using ACPI.
1160+
* @dev: Device to Resume.
1161+
*
1162+
* Use ACPI to put the given device into the full-power state if it has not been
1163+
* powered up during early resume phase, and carry out the generic resume
1164+
* procedure for it during system transition into the working state.
1165+
*/
1166+
static int acpi_subsys_resume(struct device *dev)
1167+
{
1168+
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
1169+
int ret = 0;
1170+
1171+
if (!dev_pm_skip_resume(dev) && pm && !pm->resume_early) {
1172+
dev_dbg(dev, "executing postponed D0 transition\n");
1173+
ret = acpi_dev_resume(dev);
1174+
}
1175+
1176+
return ret ? ret : pm_generic_resume(dev);
1177+
}
1178+
11491179
/**
11501180
* acpi_subsys_freeze - Run the device driver's freeze callback.
11511181
* @dev: Device to handle.
@@ -1239,6 +1269,7 @@ static struct dev_pm_domain acpi_general_pm_domain = {
12391269
.prepare = acpi_subsys_prepare,
12401270
.complete = acpi_subsys_complete,
12411271
.suspend = acpi_subsys_suspend,
1272+
.resume = acpi_subsys_resume,
12421273
.suspend_late = acpi_subsys_suspend_late,
12431274
.suspend_noirq = acpi_subsys_suspend_noirq,
12441275
.resume_noirq = acpi_subsys_resume_noirq,
@@ -1310,10 +1341,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
13101341
* with the generic ACPI PM domain.
13111342
*/
13121343
static const struct acpi_device_id special_pm_ids[] = {
1313-
{"PNP0C0B", }, /* Generic ACPI fan */
1314-
{"INT3404", }, /* Fan */
1315-
{"INTC1044", }, /* Fan for Tiger Lake generation */
1316-
{"INTC1048", }, /* Fan for Alder Lake generation */
1344+
ACPI_FAN_DEVICE_IDS,
13171345
{}
13181346
};
13191347
struct acpi_device *adev = ACPI_COMPANION(dev);

drivers/acpi/fan.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include <linux/platform_device.h>
1717
#include <linux/sort.h>
1818

19+
#include "fan.h"
20+
1921
MODULE_AUTHOR("Paul Diefenbaugh");
2022
MODULE_DESCRIPTION("ACPI Fan Driver");
2123
MODULE_LICENSE("GPL");
@@ -24,10 +26,7 @@ static int acpi_fan_probe(struct platform_device *pdev);
2426
static int acpi_fan_remove(struct platform_device *pdev);
2527

2628
static const struct acpi_device_id fan_device_ids[] = {
27-
{"PNP0C0B", 0},
28-
{"INT3404", 0},
29-
{"INTC1044", 0},
30-
{"INTC1048", 0},
29+
ACPI_FAN_DEVICE_IDS,
3130
{"", 0},
3231
};
3332
MODULE_DEVICE_TABLE(acpi, fan_device_ids);

drivers/acpi/fan.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
/*
4+
* ACPI fan device IDs are shared between the fan driver and the device power
5+
* management code.
6+
*
7+
* Add new device IDs before the generic ACPI fan one.
8+
*/
9+
#define ACPI_FAN_DEVICE_IDS \
10+
{"INT3404", }, /* Fan */ \
11+
{"INTC1044", }, /* Fan for Tiger Lake generation */ \
12+
{"INTC1048", }, /* Fan for Alder Lake generation */ \
13+
{"PNP0C0B", } /* Generic ACPI fan */

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: 55 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ struct acpi_power_resource {
5252
u32 system_level;
5353
u32 order;
5454
unsigned int ref_count;
55-
unsigned int users;
55+
u8 state;
5656
bool wakeup_enabled;
5757
struct mutex resource_lock;
5858
struct list_head dependents;
@@ -173,53 +173,61 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
173173
err = acpi_power_resources_list_add(rhandle, list);
174174
if (err)
175175
break;
176-
177-
to_power_resource(rdev)->users++;
178176
}
179177
if (err)
180178
acpi_power_resources_list_free(list);
181179

182180
return err;
183181
}
184182

185-
static int acpi_power_get_state(acpi_handle handle, int *state)
183+
static int __get_state(acpi_handle handle, u8 *state)
186184
{
187185
acpi_status status = AE_OK;
188186
unsigned long long sta = 0;
189-
190-
if (!handle || !state)
191-
return -EINVAL;
187+
u8 cur_state;
192188

193189
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
194190
if (ACPI_FAILURE(status))
195191
return -ENODEV;
196192

197-
*state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
198-
ACPI_POWER_RESOURCE_STATE_OFF;
193+
cur_state = sta & ACPI_POWER_RESOURCE_STATE_ON;
199194

200195
acpi_handle_debug(handle, "Power resource is %s\n",
201-
*state ? "on" : "off");
196+
cur_state ? "on" : "off");
197+
198+
*state = cur_state;
199+
return 0;
200+
}
201+
202+
static int acpi_power_get_state(struct acpi_power_resource *resource, u8 *state)
203+
{
204+
if (resource->state == ACPI_POWER_RESOURCE_STATE_UNKNOWN) {
205+
int ret;
202206

207+
ret = __get_state(resource->device.handle, &resource->state);
208+
if (ret)
209+
return ret;
210+
}
211+
212+
*state = resource->state;
203213
return 0;
204214
}
205215

206-
static int acpi_power_get_list_state(struct list_head *list, int *state)
216+
static int acpi_power_get_list_state(struct list_head *list, u8 *state)
207217
{
208218
struct acpi_power_resource_entry *entry;
209-
int cur_state;
219+
u8 cur_state = ACPI_POWER_RESOURCE_STATE_OFF;
210220

211221
if (!list || !state)
212222
return -EINVAL;
213223

214224
/* The state of the list is 'on' IFF all resources are 'on'. */
215-
cur_state = 0;
216225
list_for_each_entry(entry, list, node) {
217226
struct acpi_power_resource *resource = entry->resource;
218-
acpi_handle handle = resource->device.handle;
219227
int result;
220228

221229
mutex_lock(&resource->resource_lock);
222-
result = acpi_power_get_state(handle, &cur_state);
230+
result = acpi_power_get_state(resource, &cur_state);
223231
mutex_unlock(&resource->resource_lock);
224232
if (result)
225233
return result;
@@ -352,8 +360,12 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
352360
acpi_status status = AE_OK;
353361

354362
status = acpi_evaluate_object(resource->device.handle, "_ON", NULL, NULL);
355-
if (ACPI_FAILURE(status))
363+
if (ACPI_FAILURE(status)) {
364+
resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN;
356365
return -ENODEV;
366+
}
367+
368+
resource->state = ACPI_POWER_RESOURCE_STATE_ON;
357369

358370
pr_debug("Power resource [%s] turned on\n", resource->name);
359371

@@ -405,8 +417,12 @@ static int __acpi_power_off(struct acpi_power_resource *resource)
405417

406418
status = acpi_evaluate_object(resource->device.handle, "_OFF",
407419
NULL, NULL);
408-
if (ACPI_FAILURE(status))
420+
if (ACPI_FAILURE(status)) {
421+
resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN;
409422
return -ENODEV;
423+
}
424+
425+
resource->state = ACPI_POWER_RESOURCE_STATE_OFF;
410426

411427
pr_debug("Power resource [%s] turned off\n", resource->name);
412428

@@ -590,13 +606,12 @@ int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
590606

591607
list_for_each_entry(entry, list, node) {
592608
struct acpi_power_resource *resource = entry->resource;
593-
acpi_handle handle = resource->device.handle;
594609
int result;
595-
int state;
610+
u8 state;
596611

597612
mutex_lock(&resource->resource_lock);
598613

599-
result = acpi_power_get_state(handle, &state);
614+
result = acpi_power_get_state(resource, &state);
600615
if (result) {
601616
mutex_unlock(&resource->resource_lock);
602617
return result;
@@ -789,8 +804,8 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
789804

790805
int acpi_power_get_inferred_state(struct acpi_device *device, int *state)
791806
{
807+
u8 list_state = ACPI_POWER_RESOURCE_STATE_OFF;
792808
int result = 0;
793-
int list_state = 0;
794809
int i = 0;
795810

796811
if (!device || !state)
@@ -919,7 +934,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
919934
union acpi_object acpi_object;
920935
struct acpi_buffer buffer = { sizeof(acpi_object), &acpi_object };
921936
acpi_status status;
922-
int state, result = -ENODEV;
937+
int result;
923938

924939
acpi_bus_get_device(handle, &device);
925940
if (device)
@@ -946,13 +961,9 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
946961

947962
resource->system_level = acpi_object.power_resource.system_level;
948963
resource->order = acpi_object.power_resource.resource_order;
964+
resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN;
949965

950-
result = acpi_power_get_state(handle, &state);
951-
if (result)
952-
goto err;
953-
954-
pr_info("%s [%s] (%s)\n", acpi_device_name(device),
955-
acpi_device_bid(device), state ? "on" : "off");
966+
pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device));
956967

957968
device->flags.match_driver = true;
958969
result = acpi_device_add(device, acpi_release_power_resource);
@@ -979,19 +990,21 @@ void acpi_resume_power_resources(void)
979990
mutex_lock(&power_resource_list_lock);
980991

981992
list_for_each_entry(resource, &acpi_power_resource_list, list_node) {
982-
int result, state;
993+
int result;
994+
u8 state;
983995

984996
mutex_lock(&resource->resource_lock);
985997

986-
result = acpi_power_get_state(resource->device.handle, &state);
998+
resource->state = ACPI_POWER_RESOURCE_STATE_UNKNOWN;
999+
result = acpi_power_get_state(resource, &state);
9871000
if (result) {
9881001
mutex_unlock(&resource->resource_lock);
9891002
continue;
9901003
}
9911004

9921005
if (state == ACPI_POWER_RESOURCE_STATE_OFF
9931006
&& resource->ref_count) {
994-
dev_info(&resource->device.dev, "Turning ON\n");
1007+
dev_dbg(&resource->device.dev, "Turning ON\n");
9951008
__acpi_power_on(resource);
9961009
}
9971010

@@ -1002,38 +1015,10 @@ void acpi_resume_power_resources(void)
10021015
}
10031016
#endif
10041017

1005-
static void acpi_power_turn_off_if_unused(struct acpi_power_resource *resource,
1006-
bool init)
1007-
{
1008-
if (resource->ref_count > 0)
1009-
return;
1010-
1011-
if (init) {
1012-
if (resource->users > 0)
1013-
return;
1014-
} else {
1015-
int result, state;
1016-
1017-
result = acpi_power_get_state(resource->device.handle, &state);
1018-
if (result || state == ACPI_POWER_RESOURCE_STATE_OFF)
1019-
return;
1020-
}
1021-
1022-
dev_info(&resource->device.dev, "Turning OFF\n");
1023-
__acpi_power_off(resource);
1024-
}
1025-
10261018
/**
10271019
* acpi_turn_off_unused_power_resources - Turn off power resources not in use.
1028-
* @init: Control switch.
1029-
*
1030-
* If @ainit is set, unconditionally turn off all of the ACPI power resources
1031-
* without any users.
1032-
*
1033-
* Otherwise, turn off all ACPI power resources without active references (that
1034-
* is, the ones that should be "off" at the moment) that are "on".
10351020
*/
1036-
void acpi_turn_off_unused_power_resources(bool init)
1021+
void acpi_turn_off_unused_power_resources(void)
10371022
{
10381023
struct acpi_power_resource *resource;
10391024

@@ -1042,7 +1027,16 @@ void acpi_turn_off_unused_power_resources(bool init)
10421027
list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) {
10431028
mutex_lock(&resource->resource_lock);
10441029

1045-
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_dbg(&resource->device.dev, "Turning OFF\n");
1038+
__acpi_power_off(resource);
1039+
}
10461040

10471041
mutex_unlock(&resource->resource_lock);
10481042
}

0 commit comments

Comments
 (0)