Move the Display On/Off notifications into dedicated callbacks that gate
the ACPI mutex, so they can be called outside of the suspend path.

Co-developed-by: Mario Limonciello <mario.limoncie...@amd.com>
Signed-off-by: Mario Limonciello <mario.limoncie...@amd.com>
Signed-off-by: Antheas Kapenekakis <l...@antheas.dev>
---
 drivers/acpi/x86/s2idle.c | 67 +++++++++++++++++++++++++++++----------
 1 file changed, 51 insertions(+), 16 deletions(-)

diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
index 7391f87f3aa0..8b39e3b12ec0 100644
--- a/drivers/acpi/x86/s2idle.c
+++ b/drivers/acpi/x86/s2idle.c
@@ -60,6 +60,7 @@ static int lps0_dsm_func_mask;
 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;
 
 /* Device constraint entry structure */
 struct lpi_device_info {
@@ -539,17 +540,18 @@ static struct acpi_scan_handler lps0_handler = {
        .attach = lps0_device_attach,
 };
 
-int acpi_s2idle_prepare_late(void)
+static int acpi_s2idle_display_off(void)
 {
-       struct acpi_s2idle_dev_ops *handler;
-
        if (!lps0_device_handle || sleep_no_lps0)
                return 0;
 
-       if (pm_debug_messages_on)
-               lpi_check_constraints();
+       if (WARN_ON(lsp0_dsm_in_display_off))
+               return -EINVAL;
+
+       lsp0_dsm_in_display_off = true;
+       acpi_scan_lock_acquire();
 
-       /* Screen off */
+       /* Display off */
        if (lps0_dsm_func_mask > 0)
                acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
                                        ACPI_LPS0_DISPLAY_OFF_AMD :
@@ -560,6 +562,47 @@ int acpi_s2idle_prepare_late(void)
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_OFF,
                                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)
+               return 0;
+
+       if (WARN_ON(!lsp0_dsm_in_display_off))
+               return -EINVAL;
+
+       lsp0_dsm_in_display_off = false;
+       acpi_scan_lock_acquire();
+
+       /* Display on */
+       if (lps0_dsm_func_mask_microsoft > 0)
+               acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_ON,
+                               lps0_dsm_func_mask_microsoft, 
lps0_dsm_guid_microsoft);
+       if (lps0_dsm_func_mask > 0)
+               acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
+                                       ACPI_LPS0_DISPLAY_ON_AMD :
+                                       ACPI_LPS0_DISPLAY_ON,
+                                       lps0_dsm_func_mask, lps0_dsm_guid);
+
+       acpi_scan_lock_release();
+
+       return 0;
+}
+
+int acpi_s2idle_prepare_late(void)
+{
+       struct acpi_s2idle_dev_ops *handler;
+
+       if (!lps0_device_handle || sleep_no_lps0)
+               return 0;
+
+       if (pm_debug_messages_on)
+               lpi_check_constraints();
+
        /* LPS0 entry */
        if (lps0_dsm_func_mask > 0 && acpi_s2idle_vendor_amd())
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY_AMD,
@@ -623,19 +666,10 @@ void acpi_s2idle_restore_early(void)
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
                                lps0_dsm_func_mask_microsoft, 
lps0_dsm_guid_microsoft);
        }
-
-       /* Screen on */
-       if (lps0_dsm_func_mask_microsoft > 0)
-               acpi_sleep_run_lps0_dsm(ACPI_LPS0_DISPLAY_ON,
-                               lps0_dsm_func_mask_microsoft, 
lps0_dsm_guid_microsoft);
-       if (lps0_dsm_func_mask > 0)
-               acpi_sleep_run_lps0_dsm(acpi_s2idle_vendor_amd() ?
-                                               ACPI_LPS0_DISPLAY_ON_AMD :
-                                               ACPI_LPS0_DISPLAY_ON,
-                                       lps0_dsm_func_mask, lps0_dsm_guid);
 }
 
 static const struct platform_s2idle_ops acpi_s2idle_ops_lps0 = {
+       .display_off = acpi_s2idle_display_off,
        .begin = acpi_s2idle_begin,
        .prepare = acpi_s2idle_prepare,
        .prepare_late = acpi_s2idle_prepare_late,
@@ -644,6 +678,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,
+       .display_on = acpi_s2idle_display_on,
 };
 
 void __init acpi_s2idle_setup(void)
-- 
2.47.0

Reply via email to