summaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-07-03 14:23:09 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-07-03 14:23:09 +0200
commit8f8e5c3e2796eaf150d6262115af12707c2616dd (patch)
tree85f3ec09ce6960fd57c85610a5c97841f2ded9ba /kernel/power
parentMerge branches 'pm-domains', 'pm-avs' and 'powercap' (diff)
parentPM / core: Drop run_wake flag from struct dev_pm_info (diff)
downloadlinux-8f8e5c3e2796eaf150d6262115af12707c2616dd.tar.xz
linux-8f8e5c3e2796eaf150d6262115af12707c2616dd.zip
Merge branch 'acpi-pm'
* acpi-pm: PM / core: Drop run_wake flag from struct dev_pm_info PCI / PM: Simplify device wakeup settings code PCI / PM: Drop pme_interrupt flag from struct pci_dev ACPI / PM: Consolidate device wakeup settings code ACPI / PM: Drop run_wake from struct acpi_device_wakeup_flags ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems platform: x86: intel-hid: Wake up the system from suspend-to-idle platform: x86: intel-vbtn: Wake up the system from suspend-to-idle ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle platform/x86: Add driver for ACPI INT0002 Virtual GPIO device PCI / PM: Restore PME Enable if skipping wakeup setup PM / sleep: Print timing information if debug is enabled ACPI / PM: Clean up device wakeup enable/disable code ACPI / PM: Change log level of wakeup-related message USB / PCI / PM: Allow the PCI core to do the resume cleanup ACPI / PM: Run wakeup notify handlers synchronously Conflicts: drivers/base/power/main.c
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/process.c2
-rw-r--r--kernel/power/suspend.c35
2 files changed, 30 insertions, 7 deletions
diff --git a/kernel/power/process.c b/kernel/power/process.c
index c7209f060eeb..78672d324a6e 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -132,7 +132,7 @@ int freeze_processes(void)
if (!pm_freezing)
atomic_inc(&system_freezing_cnt);
- pm_wakeup_clear();
+ pm_wakeup_clear(true);
pr_info("Freezing user space processes ... ");
pm_freezing = true;
error = try_to_freeze_tasks(true);
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 15e6baef5c73..3ecf275d7e44 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -72,6 +72,8 @@ static void freeze_begin(void)
static void freeze_enter(void)
{
+ trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, true);
+
spin_lock_irq(&suspend_freeze_lock);
if (pm_wakeup_pending())
goto out;
@@ -84,11 +86,9 @@ static void freeze_enter(void)
/* Push all the CPUs into the idle loop. */
wake_up_all_idle_cpus();
- pr_debug("PM: suspend-to-idle\n");
/* Make the current CPU wait so it can enter the idle loop too. */
wait_event(suspend_freeze_wait_head,
suspend_freeze_state == FREEZE_STATE_WAKE);
- pr_debug("PM: resume from suspend-to-idle\n");
cpuidle_pause();
put_online_cpus();
@@ -98,6 +98,31 @@ static void freeze_enter(void)
out:
suspend_freeze_state = FREEZE_STATE_NONE;
spin_unlock_irq(&suspend_freeze_lock);
+
+ trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false);
+}
+
+static void s2idle_loop(void)
+{
+ pr_debug("PM: suspend-to-idle\n");
+
+ do {
+ freeze_enter();
+
+ if (freeze_ops && freeze_ops->wake)
+ freeze_ops->wake();
+
+ dpm_resume_noirq(PMSG_RESUME);
+ if (freeze_ops && freeze_ops->sync)
+ freeze_ops->sync();
+
+ if (pm_wakeup_pending())
+ break;
+
+ pm_wakeup_clear(false);
+ } while (!dpm_suspend_noirq(PMSG_SUSPEND));
+
+ pr_debug("PM: resume from suspend-to-idle\n");
}
void freeze_wake(void)
@@ -371,10 +396,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
* all the devices are suspended.
*/
if (state == PM_SUSPEND_FREEZE) {
- trace_suspend_resume(TPS("machine_suspend"), state, true);
- freeze_enter();
- trace_suspend_resume(TPS("machine_suspend"), state, false);
- goto Platform_wake;
+ s2idle_loop();
+ goto Platform_early_resume;
}
error = disable_nonboot_cpus();