Skip to content

Commit 56db6a8

Browse files
committed
Merge branch 'acpi-pm'
Merge ACPI power management updates for 6.6-rc1: - Fix and clean up suspend-to-idle interface for AMD systems (Mario Limonciello, Andy Shevchenko). * acpi-pm: ACPI: x86: s2idle: Add a function to get LPS0 constraint for a device ACPI: x86: s2idle: Add for_each_lpi_constraint() helper ACPI: x86: s2idle: Add more debugging for AMD constraints parsing ACPI: x86: s2idle: Fix a logic error parsing AMD constraints table ACPI: x86: s2idle: Catch multiple ACPI_TYPE_PACKAGE objects ACPI: x86: s2idle: Post-increment variables when getting constraints ACPI: Adjust #ifdef for *_lps0_dev use
2 parents 0960a3c + 1c2a66d commit 56db6a8

File tree

2 files changed

+73
-36
lines changed

2 files changed

+73
-36
lines changed

drivers/acpi/x86/s2idle.c

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ static struct lpi_constraints *lpi_constraints_table;
9494
static int lpi_constraints_table_size;
9595
static int rev_id;
9696

97+
#define for_each_lpi_constraint(entry) \
98+
for (int i = 0; \
99+
entry = &lpi_constraints_table[i], i < lpi_constraints_table_size; \
100+
i++)
101+
97102
static void lpi_device_get_constraints_amd(void)
98103
{
99104
union acpi_object *out_obj;
@@ -113,6 +118,12 @@ static void lpi_device_get_constraints_amd(void)
113118
union acpi_object *package = &out_obj->package.elements[i];
114119

115120
if (package->type == ACPI_TYPE_PACKAGE) {
121+
if (lpi_constraints_table) {
122+
acpi_handle_err(lps0_device_handle,
123+
"Duplicate constraints list\n");
124+
goto free_acpi_buffer;
125+
}
126+
116127
lpi_constraints_table = kcalloc(package->package.count,
117128
sizeof(*lpi_constraints_table),
118129
GFP_KERNEL);
@@ -123,17 +134,16 @@ static void lpi_device_get_constraints_amd(void)
123134
acpi_handle_debug(lps0_device_handle,
124135
"LPI: constraints list begin:\n");
125136

126-
for (j = 0; j < package->package.count; ++j) {
137+
for (j = 0; j < package->package.count; j++) {
127138
union acpi_object *info_obj = &package->package.elements[j];
128139
struct lpi_device_constraint_amd dev_info = {};
129140
struct lpi_constraints *list;
130141
acpi_status status;
131142

132-
for (k = 0; k < info_obj->package.count; ++k) {
133-
union acpi_object *obj = &info_obj->package.elements[k];
143+
list = &lpi_constraints_table[lpi_constraints_table_size];
134144

135-
list = &lpi_constraints_table[lpi_constraints_table_size];
136-
list->min_dstate = -1;
145+
for (k = 0; k < info_obj->package.count; k++) {
146+
union acpi_object *obj = &info_obj->package.elements[k];
137147

138148
switch (k) {
139149
case 0:
@@ -149,27 +159,25 @@ static void lpi_device_get_constraints_amd(void)
149159
dev_info.min_dstate = obj->integer.value;
150160
break;
151161
}
162+
}
152163

153-
if (!dev_info.enabled || !dev_info.name ||
154-
!dev_info.min_dstate)
155-
continue;
164+
acpi_handle_debug(lps0_device_handle,
165+
"Name:%s, Enabled: %d, States: %d, MinDstate: %d\n",
166+
dev_info.name,
167+
dev_info.enabled,
168+
dev_info.function_states,
169+
dev_info.min_dstate);
156170

157-
status = acpi_get_handle(NULL, dev_info.name,
158-
&list->handle);
159-
if (ACPI_FAILURE(status))
160-
continue;
171+
if (!dev_info.enabled || !dev_info.name ||
172+
!dev_info.min_dstate)
173+
continue;
161174

162-
acpi_handle_debug(lps0_device_handle,
163-
"Name:%s\n", dev_info.name);
175+
status = acpi_get_handle(NULL, dev_info.name, &list->handle);
176+
if (ACPI_FAILURE(status))
177+
continue;
164178

165-
list->min_dstate = dev_info.min_dstate;
179+
list->min_dstate = dev_info.min_dstate;
166180

167-
if (list->min_dstate < 0) {
168-
acpi_handle_debug(lps0_device_handle,
169-
"Incomplete constraint defined\n");
170-
continue;
171-
}
172-
}
173181
lpi_constraints_table_size++;
174182
}
175183
}
@@ -214,7 +222,7 @@ static void lpi_device_get_constraints(void)
214222
if (!package)
215223
continue;
216224

217-
for (j = 0; j < package->package.count; ++j) {
225+
for (j = 0; j < package->package.count; j++) {
218226
union acpi_object *element =
219227
&(package->package.elements[j]);
220228

@@ -246,7 +254,7 @@ static void lpi_device_get_constraints(void)
246254

247255
constraint->min_dstate = -1;
248256

249-
for (j = 0; j < package_count; ++j) {
257+
for (j = 0; j < package_count; j++) {
250258
union acpi_object *info_obj = &info.package[j];
251259
union acpi_object *cnstr_pkg;
252260
union acpi_object *obj;
@@ -291,32 +299,55 @@ static void lpi_device_get_constraints(void)
291299
ACPI_FREE(out_obj);
292300
}
293301

302+
/**
303+
* acpi_get_lps0_constraint - Get the LPS0 constraint for a device.
304+
* @adev: Device to get the constraint for.
305+
*
306+
* The LPS0 constraint is the shallowest (minimum) power state in which the
307+
* device can be so as to allow the platform as a whole to achieve additional
308+
* energy conservation by utilizing a system-wide low-power state.
309+
*
310+
* Returns:
311+
* - ACPI power state value of the constraint for @adev on success.
312+
* - Otherwise, ACPI_STATE_UNKNOWN.
313+
*/
314+
int acpi_get_lps0_constraint(struct acpi_device *adev)
315+
{
316+
struct lpi_constraints *entry;
317+
318+
for_each_lpi_constraint(entry) {
319+
if (adev->handle == entry->handle)
320+
return entry->min_dstate;
321+
}
322+
323+
return ACPI_STATE_UNKNOWN;
324+
}
325+
294326
static void lpi_check_constraints(void)
295327
{
296-
int i;
328+
struct lpi_constraints *entry;
297329

298-
for (i = 0; i < lpi_constraints_table_size; ++i) {
299-
acpi_handle handle = lpi_constraints_table[i].handle;
300-
struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
330+
for_each_lpi_constraint(entry) {
331+
struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle);
301332

302333
if (!adev)
303334
continue;
304335

305-
acpi_handle_debug(handle,
336+
acpi_handle_debug(entry->handle,
306337
"LPI: required min power state:%s current power state:%s\n",
307-
acpi_power_state_string(lpi_constraints_table[i].min_dstate),
338+
acpi_power_state_string(entry->min_dstate),
308339
acpi_power_state_string(adev->power.state));
309340

310341
if (!adev->flags.power_manageable) {
311-
acpi_handle_info(handle, "LPI: Device not power manageable\n");
312-
lpi_constraints_table[i].handle = NULL;
342+
acpi_handle_info(entry->handle, "LPI: Device not power manageable\n");
343+
entry->handle = NULL;
313344
continue;
314345
}
315346

316-
if (adev->power.state < lpi_constraints_table[i].min_dstate)
317-
acpi_handle_info(handle,
347+
if (adev->power.state < entry->min_dstate)
348+
acpi_handle_info(entry->handle,
318349
"LPI: Constraint not met; min power state:%s current power state:%s\n",
319-
acpi_power_state_string(lpi_constraints_table[i].min_dstate),
350+
acpi_power_state_string(entry->min_dstate),
320351
acpi_power_state_string(adev->power.state));
321352
}
322353
}

include/linux/acpi.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,7 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
10981098

10991099
acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
11001100
u32 val_a, u32 val_b);
1101-
#ifdef CONFIG_X86
1101+
#if defined(CONFIG_SUSPEND) && defined(CONFIG_X86)
11021102
struct acpi_s2idle_dev_ops {
11031103
struct list_head list_node;
11041104
void (*prepare)(void);
@@ -1107,7 +1107,13 @@ struct acpi_s2idle_dev_ops {
11071107
};
11081108
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
11091109
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);
1110-
#endif /* CONFIG_X86 */
1110+
int acpi_get_lps0_constraint(struct acpi_device *adev);
1111+
#else /* CONFIG_SUSPEND && CONFIG_X86 */
1112+
static inline int acpi_get_lps0_constraint(struct device *dev)
1113+
{
1114+
return ACPI_STATE_UNKNOWN;
1115+
}
1116+
#endif /* CONFIG_SUSPEND && CONFIG_X86 */
11111117
#ifndef CONFIG_IA64
11121118
void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
11131119
#else

0 commit comments

Comments
 (0)