@@ -61,6 +61,7 @@ static guid_t lps0_dsm_guid_microsoft;
static int lps0_dsm_func_mask_microsoft;
static int lps0_dsm_state;
static bool lsp0_dsm_in_display_off;
+static bool lsp0_dsm_in_sleep;
/* Device constraint entry structure */
struct lpi_device_info {
@@ -567,6 +568,48 @@ static int acpi_s2idle_display_off(void)
return 0;
}
+static int acpi_s2idle_sleep_entry(void)
+{
+ if (!lps0_device_handle || sleep_no_lps0 || lps0_dsm_func_mask_microsoft <= 0)
+ return 0;
+
+ if (WARN_ON(lsp0_dsm_in_sleep))
+ return -EINVAL;
+
+ lsp0_dsm_in_sleep = true;
+ acpi_scan_lock_acquire();
+
+ /* Modern Standby Sleep Entry */
+ if (lps0_dsm_func_mask_microsoft > 0)
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_ENTRY,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+
+ acpi_scan_lock_release();
+
+ return 0;
+}
+
+static int acpi_s2idle_sleep_exit(void)
+{
+ if (!lps0_device_handle || sleep_no_lps0 || lps0_dsm_func_mask_microsoft <= 0)
+ return 0;
+
+ if (WARN_ON(!lsp0_dsm_in_sleep))
+ return -EINVAL;
+
+ lsp0_dsm_in_sleep = false;
+ acpi_scan_lock_acquire();
+
+ /* Modern Standby Sleep Exit */
+ if (lps0_dsm_func_mask_microsoft > 0)
+ acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_EXIT,
+ lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+
+ acpi_scan_lock_release();
+
+ return 0;
+}
+
static int acpi_s2idle_display_on(void)
{
if (!lps0_device_handle || sleep_no_lps0)
@@ -608,13 +651,9 @@ int acpi_s2idle_prepare_late(void)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
lps0_dsm_func_mask, lps0_dsm_guid);
- if (lps0_dsm_func_mask_microsoft > 0) {
- /* Modern Standby entry */
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_ENTRY,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
+ if (lps0_dsm_func_mask_microsoft > 0)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
- }
if (lps0_dsm_func_mask > 0 && !acpi_s2idle_vendor_amd())
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
@@ -659,17 +698,14 @@ void acpi_s2idle_restore_early(void)
ACPI_LPS0_EXIT,
lps0_dsm_func_mask, lps0_dsm_guid);
- if (lps0_dsm_func_mask_microsoft > 0) {
+ if (lps0_dsm_func_mask_microsoft > 0)
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
- /* Modern Standby exit */
- acpi_sleep_run_lps0_dsm(ACPI_LPS0_SLEEP_EXIT,
- lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
- }
}
static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
.display_off = acpi_s2idle_display_off,
+ .sleep_entry = acpi_s2idle_sleep_entry,
.begin = acpi_s2idle_begin,
.prepare = acpi_s2idle_prepare,
.prepare_late = acpi_s2idle_prepare_late,
@@ -678,6 +714,7 @@ static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
.restore_early = acpi_s2idle_restore_early,
.restore = acpi_s2idle_restore,
.end = acpi_s2idle_end,
+ .sleep_exit = acpi_s2idle_sleep_exit,
.display_on = acpi_s2idle_display_on,
};
Move the Sleep Entry/Exit notifications outside the suspend sequence, with their own ACPI lock, as was done for Display On/Off. Suggested-by: Mario Limonciello <mario.limonciello@amd.com> Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev> --- drivers/acpi/x86/s2idle.c | 57 ++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 10 deletions(-)