Commit 56db6a8e authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

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
parents 0960a3cb 1c2a66d4
...@@ -94,6 +94,11 @@ static struct lpi_constraints *lpi_constraints_table; ...@@ -94,6 +94,11 @@ static struct lpi_constraints *lpi_constraints_table;
static int lpi_constraints_table_size; static int lpi_constraints_table_size;
static int rev_id; static int rev_id;
#define for_each_lpi_constraint(entry) \
for (int i = 0; \
entry = &lpi_constraints_table[i], i < lpi_constraints_table_size; \
i++)
static void lpi_device_get_constraints_amd(void) static void lpi_device_get_constraints_amd(void)
{ {
union acpi_object *out_obj; union acpi_object *out_obj;
...@@ -113,6 +118,12 @@ static void lpi_device_get_constraints_amd(void) ...@@ -113,6 +118,12 @@ static void lpi_device_get_constraints_amd(void)
union acpi_object *package = &out_obj->package.elements[i]; union acpi_object *package = &out_obj->package.elements[i];
if (package->type == ACPI_TYPE_PACKAGE) { if (package->type == ACPI_TYPE_PACKAGE) {
if (lpi_constraints_table) {
acpi_handle_err(lps0_device_handle,
"Duplicate constraints list\n");
goto free_acpi_buffer;
}
lpi_constraints_table = kcalloc(package->package.count, lpi_constraints_table = kcalloc(package->package.count,
sizeof(*lpi_constraints_table), sizeof(*lpi_constraints_table),
GFP_KERNEL); GFP_KERNEL);
...@@ -123,17 +134,16 @@ static void lpi_device_get_constraints_amd(void) ...@@ -123,17 +134,16 @@ static void lpi_device_get_constraints_amd(void)
acpi_handle_debug(lps0_device_handle, acpi_handle_debug(lps0_device_handle,
"LPI: constraints list begin:\n"); "LPI: constraints list begin:\n");
for (j = 0; j < package->package.count; ++j) { for (j = 0; j < package->package.count; j++) {
union acpi_object *info_obj = &package->package.elements[j]; union acpi_object *info_obj = &package->package.elements[j];
struct lpi_device_constraint_amd dev_info = {}; struct lpi_device_constraint_amd dev_info = {};
struct lpi_constraints *list; struct lpi_constraints *list;
acpi_status status; acpi_status status;
for (k = 0; k < info_obj->package.count; ++k) {
union acpi_object *obj = &info_obj->package.elements[k];
list = &lpi_constraints_table[lpi_constraints_table_size]; list = &lpi_constraints_table[lpi_constraints_table_size];
list->min_dstate = -1;
for (k = 0; k < info_obj->package.count; k++) {
union acpi_object *obj = &info_obj->package.elements[k];
switch (k) { switch (k) {
case 0: case 0:
...@@ -149,27 +159,25 @@ static void lpi_device_get_constraints_amd(void) ...@@ -149,27 +159,25 @@ static void lpi_device_get_constraints_amd(void)
dev_info.min_dstate = obj->integer.value; dev_info.min_dstate = obj->integer.value;
break; break;
} }
}
acpi_handle_debug(lps0_device_handle,
"Name:%s, Enabled: %d, States: %d, MinDstate: %d\n",
dev_info.name,
dev_info.enabled,
dev_info.function_states,
dev_info.min_dstate);
if (!dev_info.enabled || !dev_info.name || if (!dev_info.enabled || !dev_info.name ||
!dev_info.min_dstate) !dev_info.min_dstate)
continue; continue;
status = acpi_get_handle(NULL, dev_info.name, status = acpi_get_handle(NULL, dev_info.name, &list->handle);
&list->handle);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
continue; continue;
acpi_handle_debug(lps0_device_handle,
"Name:%s\n", dev_info.name);
list->min_dstate = dev_info.min_dstate; list->min_dstate = dev_info.min_dstate;
if (list->min_dstate < 0) {
acpi_handle_debug(lps0_device_handle,
"Incomplete constraint defined\n");
continue;
}
}
lpi_constraints_table_size++; lpi_constraints_table_size++;
} }
} }
...@@ -214,7 +222,7 @@ static void lpi_device_get_constraints(void) ...@@ -214,7 +222,7 @@ static void lpi_device_get_constraints(void)
if (!package) if (!package)
continue; continue;
for (j = 0; j < package->package.count; ++j) { for (j = 0; j < package->package.count; j++) {
union acpi_object *element = union acpi_object *element =
&(package->package.elements[j]); &(package->package.elements[j]);
...@@ -246,7 +254,7 @@ static void lpi_device_get_constraints(void) ...@@ -246,7 +254,7 @@ static void lpi_device_get_constraints(void)
constraint->min_dstate = -1; constraint->min_dstate = -1;
for (j = 0; j < package_count; ++j) { for (j = 0; j < package_count; j++) {
union acpi_object *info_obj = &info.package[j]; union acpi_object *info_obj = &info.package[j];
union acpi_object *cnstr_pkg; union acpi_object *cnstr_pkg;
union acpi_object *obj; union acpi_object *obj;
...@@ -291,32 +299,55 @@ static void lpi_device_get_constraints(void) ...@@ -291,32 +299,55 @@ static void lpi_device_get_constraints(void)
ACPI_FREE(out_obj); ACPI_FREE(out_obj);
} }
/**
* acpi_get_lps0_constraint - Get the LPS0 constraint for a device.
* @adev: Device to get the constraint for.
*
* The LPS0 constraint is the shallowest (minimum) power state in which the
* device can be so as to allow the platform as a whole to achieve additional
* energy conservation by utilizing a system-wide low-power state.
*
* Returns:
* - ACPI power state value of the constraint for @adev on success.
* - Otherwise, ACPI_STATE_UNKNOWN.
*/
int acpi_get_lps0_constraint(struct acpi_device *adev)
{
struct lpi_constraints *entry;
for_each_lpi_constraint(entry) {
if (adev->handle == entry->handle)
return entry->min_dstate;
}
return ACPI_STATE_UNKNOWN;
}
static void lpi_check_constraints(void) static void lpi_check_constraints(void)
{ {
int i; struct lpi_constraints *entry;
for (i = 0; i < lpi_constraints_table_size; ++i) { for_each_lpi_constraint(entry) {
acpi_handle handle = lpi_constraints_table[i].handle; struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle);
struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
if (!adev) if (!adev)
continue; continue;
acpi_handle_debug(handle, acpi_handle_debug(entry->handle,
"LPI: required min power state:%s current power state:%s\n", "LPI: required min power state:%s current power state:%s\n",
acpi_power_state_string(lpi_constraints_table[i].min_dstate), acpi_power_state_string(entry->min_dstate),
acpi_power_state_string(adev->power.state)); acpi_power_state_string(adev->power.state));
if (!adev->flags.power_manageable) { if (!adev->flags.power_manageable) {
acpi_handle_info(handle, "LPI: Device not power manageable\n"); acpi_handle_info(entry->handle, "LPI: Device not power manageable\n");
lpi_constraints_table[i].handle = NULL; entry->handle = NULL;
continue; continue;
} }
if (adev->power.state < lpi_constraints_table[i].min_dstate) if (adev->power.state < entry->min_dstate)
acpi_handle_info(handle, acpi_handle_info(entry->handle,
"LPI: Constraint not met; min power state:%s current power state:%s\n", "LPI: Constraint not met; min power state:%s current power state:%s\n",
acpi_power_state_string(lpi_constraints_table[i].min_dstate), acpi_power_state_string(entry->min_dstate),
acpi_power_state_string(adev->power.state)); acpi_power_state_string(adev->power.state));
} }
} }
......
...@@ -1098,7 +1098,7 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, ...@@ -1098,7 +1098,7 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
u32 val_a, u32 val_b); u32 val_a, u32 val_b);
#ifdef CONFIG_X86 #if defined(CONFIG_SUSPEND) && defined(CONFIG_X86)
struct acpi_s2idle_dev_ops { struct acpi_s2idle_dev_ops {
struct list_head list_node; struct list_head list_node;
void (*prepare)(void); void (*prepare)(void);
...@@ -1107,7 +1107,13 @@ struct acpi_s2idle_dev_ops { ...@@ -1107,7 +1107,13 @@ struct acpi_s2idle_dev_ops {
}; };
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg); int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg); void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);
#endif /* CONFIG_X86 */ int acpi_get_lps0_constraint(struct acpi_device *adev);
#else /* CONFIG_SUSPEND && CONFIG_X86 */
static inline int acpi_get_lps0_constraint(struct device *dev)
{
return ACPI_STATE_UNKNOWN;
}
#endif /* CONFIG_SUSPEND && CONFIG_X86 */
#ifndef CONFIG_IA64 #ifndef CONFIG_IA64
void arch_reserve_mem_area(acpi_physical_address addr, size_t size); void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
#else #else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment