diff options
-rw-r--r-- | drivers/acpi/sleep.c | 36 | ||||
-rw-r--r-- | include/linux/suspend.h | 2 | ||||
-rw-r--r-- | kernel/power/suspend.c | 12 |
3 files changed, 35 insertions, 15 deletions
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 864bb18d3a5d..8f7e95f97e1f 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -954,11 +954,6 @@ static int acpi_s2idle_begin(void) static int acpi_s2idle_prepare(void) { - if (lps0_device_handle && !sleep_no_lps0) { - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); - acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); - } - if (acpi_sci_irq_valid()) enable_irq_wake(acpi_sci_irq); @@ -972,11 +967,22 @@ static int acpi_s2idle_prepare(void) return 0; } -static void acpi_s2idle_wake(void) +static int acpi_s2idle_prepare_late(void) { - if (lps0_device_handle && !sleep_no_lps0 && pm_debug_messages_on) + if (!lps0_device_handle || sleep_no_lps0) + return 0; + + if (pm_debug_messages_on) lpi_check_constraints(); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); + + return 0; +} + +static void acpi_s2idle_wake(void) +{ /* * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the SCI has * not triggered while suspended, so bail out. @@ -1011,6 +1017,15 @@ static void acpi_s2idle_wake(void) rearm_wake_irq(acpi_sci_irq); } +static void acpi_s2idle_restore_early(void) +{ + if (!lps0_device_handle || sleep_no_lps0) + return; + + acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); + acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); +} + static void acpi_s2idle_restore(void) { s2idle_wakeup = false; @@ -1021,11 +1036,6 @@ static void acpi_s2idle_restore(void) if (acpi_sci_irq_valid()) disable_irq_wake(acpi_sci_irq); - - if (lps0_device_handle && !sleep_no_lps0) { - acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); - acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); - } } static void acpi_s2idle_end(void) @@ -1036,7 +1046,9 @@ static void acpi_s2idle_end(void) static const struct platform_s2idle_ops acpi_s2idle_ops = { .begin = acpi_s2idle_begin, .prepare = acpi_s2idle_prepare, + .prepare_late = acpi_s2idle_prepare_late, .wake = acpi_s2idle_wake, + .restore_early = acpi_s2idle_restore_early, .restore = acpi_s2idle_restore, .end = acpi_s2idle_end, }; diff --git a/include/linux/suspend.h b/include/linux/suspend.h index f0c4a8445140..6fc8843f1c9e 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -190,7 +190,9 @@ struct platform_suspend_ops { struct platform_s2idle_ops { int (*begin)(void); int (*prepare)(void); + int (*prepare_late)(void); void (*wake)(void); + void (*restore_early)(void); void (*restore)(void); void (*end)(void); }; diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 2b6057853b33..ed9ddef12b13 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -253,13 +253,19 @@ static int platform_suspend_prepare_late(suspend_state_t state) static int platform_suspend_prepare_noirq(suspend_state_t state) { - return state != PM_SUSPEND_TO_IDLE && suspend_ops->prepare_late ? - suspend_ops->prepare_late() : 0; + if (state == PM_SUSPEND_TO_IDLE) { + if (s2idle_ops && s2idle_ops->prepare_late) + return s2idle_ops->prepare_late(); + } + return suspend_ops->prepare_late ? suspend_ops->prepare_late() : 0; } static void platform_resume_noirq(suspend_state_t state) { - if (state != PM_SUSPEND_TO_IDLE && suspend_ops->wake) + if (state == PM_SUSPEND_TO_IDLE) { + if (s2idle_ops && s2idle_ops->restore_early) + s2idle_ops->restore_early(); + } else if (suspend_ops->wake) suspend_ops->wake(); } |