Skip to content

Commit 20e1d64

Browse files
superm1jwrdegoede
authored andcommitted
ACPI / x86: Add support for LPS0 callback handler
Currenty the latest thing run during a suspend to idle attempt is the LPS0 `prepare_late` callback and the earliest thing is the `resume_early` callback. There is a desire for the `amd-pmc` driver to suspend later in the suspend process (ideally the very last thing), so create a callback that it or any other driver can hook into to do this. Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Link: https://lore.kernel.org/r/20220317141445.6498-1-mario.limonciello@amd.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent 6060a75 commit 20e1d64

2 files changed

Lines changed: 49 additions & 1 deletion

File tree

drivers/acpi/x86/s2idle.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ struct lpi_device_constraint_amd {
8686
int min_dstate;
8787
};
8888

89+
static LIST_HEAD(lps0_s2idle_devops_head);
90+
8991
static struct lpi_constraints *lpi_constraints_table;
9092
static int lpi_constraints_table_size;
9193
static int rev_id;
@@ -444,6 +446,8 @@ static struct acpi_scan_handler lps0_handler = {
444446

445447
int acpi_s2idle_prepare_late(void)
446448
{
449+
struct acpi_s2idle_dev_ops *handler;
450+
447451
if (!lps0_device_handle || sleep_no_lps0)
448452
return 0;
449453

@@ -474,14 +478,26 @@ int acpi_s2idle_prepare_late(void)
474478
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
475479
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
476480
}
481+
482+
list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node) {
483+
if (handler->prepare)
484+
handler->prepare();
485+
}
486+
477487
return 0;
478488
}
479489

480490
void acpi_s2idle_restore_early(void)
481491
{
492+
struct acpi_s2idle_dev_ops *handler;
493+
482494
if (!lps0_device_handle || sleep_no_lps0)
483495
return;
484496

497+
list_for_each_entry(handler, &lps0_s2idle_devops_head, list_node)
498+
if (handler->restore)
499+
handler->restore();
500+
485501
/* Modern standby exit */
486502
if (lps0_dsm_func_mask_microsoft > 0)
487503
acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
@@ -524,4 +540,28 @@ void acpi_s2idle_setup(void)
524540
s2idle_set_ops(&acpi_s2idle_ops_lps0);
525541
}
526542

543+
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg)
544+
{
545+
if (!lps0_device_handle || sleep_no_lps0)
546+
return -ENODEV;
547+
548+
lock_system_sleep();
549+
list_add(&arg->list_node, &lps0_s2idle_devops_head);
550+
unlock_system_sleep();
551+
552+
return 0;
553+
}
554+
EXPORT_SYMBOL_GPL(acpi_register_lps0_dev);
555+
556+
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg)
557+
{
558+
if (!lps0_device_handle || sleep_no_lps0)
559+
return;
560+
561+
lock_system_sleep();
562+
list_del(&arg->list_node);
563+
unlock_system_sleep();
564+
}
565+
EXPORT_SYMBOL_GPL(acpi_unregister_lps0_dev);
566+
527567
#endif /* CONFIG_SUSPEND */

include/linux/acpi.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,15 @@ void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
10231023

10241024
acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state,
10251025
u32 val_a, u32 val_b);
1026-
1026+
#ifdef CONFIG_X86
1027+
struct acpi_s2idle_dev_ops {
1028+
struct list_head list_node;
1029+
void (*prepare)(void);
1030+
void (*restore)(void);
1031+
};
1032+
int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
1033+
void acpi_unregister_lps0_dev(struct acpi_s2idle_dev_ops *arg);
1034+
#endif /* CONFIG_X86 */
10271035
#ifndef CONFIG_IA64
10281036
void arch_reserve_mem_area(acpi_physical_address addr, size_t size);
10291037
#else

0 commit comments

Comments
 (0)