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
This commit is contained in:
commit
56db6a8e5a
|
@ -94,6 +94,11 @@ static struct lpi_constraints *lpi_constraints_table;
|
|||
static int lpi_constraints_table_size;
|
||||
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)
|
||||
{
|
||||
union acpi_object *out_obj;
|
||||
|
@ -113,6 +118,12 @@ static void lpi_device_get_constraints_amd(void)
|
|||
union acpi_object *package = &out_obj->package.elements[i];
|
||||
|
||||
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,
|
||||
sizeof(*lpi_constraints_table),
|
||||
GFP_KERNEL);
|
||||
|
@ -123,17 +134,16 @@ static void lpi_device_get_constraints_amd(void)
|
|||
acpi_handle_debug(lps0_device_handle,
|
||||
"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];
|
||||
struct lpi_device_constraint_amd dev_info = {};
|
||||
struct lpi_constraints *list;
|
||||
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) {
|
||||
case 0:
|
||||
|
@ -149,27 +159,25 @@ static void lpi_device_get_constraints_amd(void)
|
|||
dev_info.min_dstate = obj->integer.value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dev_info.enabled || !dev_info.name ||
|
||||
!dev_info.min_dstate)
|
||||
continue;
|
||||
|
||||
status = acpi_get_handle(NULL, dev_info.name,
|
||||
&list->handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
continue;
|
||||
|
||||
acpi_handle_debug(lps0_device_handle,
|
||||
"Name:%s\n", dev_info.name);
|
||||
|
||||
list->min_dstate = dev_info.min_dstate;
|
||||
|
||||
if (list->min_dstate < 0) {
|
||||
acpi_handle_debug(lps0_device_handle,
|
||||
"Incomplete constraint defined\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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 ||
|
||||
!dev_info.min_dstate)
|
||||
continue;
|
||||
|
||||
status = acpi_get_handle(NULL, dev_info.name, &list->handle);
|
||||
if (ACPI_FAILURE(status))
|
||||
continue;
|
||||
|
||||
list->min_dstate = dev_info.min_dstate;
|
||||
|
||||
lpi_constraints_table_size++;
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +222,7 @@ static void lpi_device_get_constraints(void)
|
|||
if (!package)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < package->package.count; ++j) {
|
||||
for (j = 0; j < package->package.count; j++) {
|
||||
union acpi_object *element =
|
||||
&(package->package.elements[j]);
|
||||
|
||||
|
@ -246,7 +254,7 @@ static void lpi_device_get_constraints(void)
|
|||
|
||||
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 *cnstr_pkg;
|
||||
union acpi_object *obj;
|
||||
|
@ -291,32 +299,55 @@ free_acpi_buffer:
|
|||
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)
|
||||
{
|
||||
int i;
|
||||
struct lpi_constraints *entry;
|
||||
|
||||
for (i = 0; i < lpi_constraints_table_size; ++i) {
|
||||
acpi_handle handle = lpi_constraints_table[i].handle;
|
||||
struct acpi_device *adev = acpi_fetch_acpi_dev(handle);
|
||||
for_each_lpi_constraint(entry) {
|
||||
struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle);
|
||||
|
||||
if (!adev)
|
||||
continue;
|
||||
|
||||
acpi_handle_debug(handle,
|
||||
acpi_handle_debug(entry->handle,
|
||||
"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));
|
||||
|
||||
if (!adev->flags.power_manageable) {
|
||||
acpi_handle_info(handle, "LPI: Device not power manageable\n");
|
||||
lpi_constraints_table[i].handle = NULL;
|
||||
acpi_handle_info(entry->handle, "LPI: Device not power manageable\n");
|
||||
entry->handle = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (adev->power.state < lpi_constraints_table[i].min_dstate)
|
||||
acpi_handle_info(handle,
|
||||
if (adev->power.state < entry->min_dstate)
|
||||
acpi_handle_info(entry->handle,
|
||||
"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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
u32 val_a, u32 val_b);
|
||||
#ifdef CONFIG_X86
|
||||
#if defined(CONFIG_SUSPEND) && defined(CONFIG_X86)
|
||||
struct acpi_s2idle_dev_ops {
|
||||
struct list_head list_node;
|
||||
void (*prepare)(void);
|
||||
|
@ -1107,7 +1107,13 @@ struct acpi_s2idle_dev_ops {
|
|||
};
|
||||
int acpi_register_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
|
||||
void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
|
||||
#else
|
||||
|
|
Loading…
Reference in New Issue