summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/sleep.c36
-rw-r--r--include/linux/suspend.h2
-rw-r--r--kernel/power/suspend.c12
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();
}