blob: 8233cd4047d776c311ef71800479f1e2b637e5da [file] [log] [blame]
Rafael J. Wysockia9d70522009-06-10 01:27:12 +02001/*
2 * kernel/power/suspend.c - Suspend to RAM and standby functionality.
3 *
4 * Copyright (c) 2003 Patrick Mochel
5 * Copyright (c) 2003 Open Source Development Lab
6 * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
7 *
8 * This file is released under the GPLv2.
9 */
10
11#include <linux/string.h>
12#include <linux/delay.h>
13#include <linux/errno.h>
14#include <linux/init.h>
15#include <linux/console.h>
16#include <linux/cpu.h>
Rafael J. Wysockif3f12532014-04-20 23:43:01 +020017#include <linux/cpuidle.h>
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020018#include <linux/syscalls.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090019#include <linux/gfp.h>
Matthew Garrettdd4c4f12010-05-28 16:32:14 -040020#include <linux/io.h>
21#include <linux/kernel.h>
22#include <linux/list.h>
23#include <linux/mm.h>
24#include <linux/slab.h>
Paul Gortmaker6e5fdee2011-05-26 16:00:52 -040025#include <linux/export.h>
Matthew Garrettdd4c4f12010-05-28 16:32:14 -040026#include <linux/suspend.h>
Rafael J. Wysocki40dc1662011-03-15 00:43:46 +010027#include <linux/syscore_ops.h>
Srivatsa S. Bhat443772d42012-06-16 15:30:45 +020028#include <linux/ftrace.h>
Jean Pihet938cfed2011-01-05 19:49:01 +010029#include <trace/events/power.h>
Gideon Israel Dsouza52f5684c2014-04-07 15:39:20 -070030#include <linux/compiler.h>
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020031
32#include "power.h"
33
34const char *const pm_states[PM_SUSPEND_MAX] = {
Zhang Rui7e73c5ae2013-02-06 13:00:36 +010035 [PM_SUSPEND_FREEZE] = "freeze",
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020036 [PM_SUSPEND_STANDBY] = "standby",
37 [PM_SUSPEND_MEM] = "mem",
38};
39
Lionel Debroux2f55ac02010-11-16 14:14:02 +010040static const struct platform_suspend_ops *suspend_ops;
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020041
Zhang Rui7e73c5ae2013-02-06 13:00:36 +010042static bool need_suspend_ops(suspend_state_t state)
43{
Viresh Kumar7500d932014-03-10 19:31:51 +053044 return state > PM_SUSPEND_FREEZE;
Zhang Rui7e73c5ae2013-02-06 13:00:36 +010045}
46
47static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head);
48static bool suspend_freeze_wake;
49
50static void freeze_begin(void)
51{
52 suspend_freeze_wake = false;
53}
54
55static void freeze_enter(void)
56{
Rafael J. Wysockif3f12532014-04-20 23:43:01 +020057 cpuidle_resume();
Zhang Rui7e73c5ae2013-02-06 13:00:36 +010058 wait_event(suspend_freeze_wait_head, suspend_freeze_wake);
Rafael J. Wysockif3f12532014-04-20 23:43:01 +020059 cpuidle_pause();
Zhang Rui7e73c5ae2013-02-06 13:00:36 +010060}
61
62void freeze_wake(void)
63{
64 suspend_freeze_wake = true;
65 wake_up(&suspend_freeze_wait_head);
66}
67EXPORT_SYMBOL_GPL(freeze_wake);
68
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020069/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +010070 * suspend_set_ops - Set the global suspend method table.
71 * @ops: Suspend operations to use.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020072 */
Lionel Debroux2f55ac02010-11-16 14:14:02 +010073void suspend_set_ops(const struct platform_suspend_ops *ops)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020074{
Srivatsa S. Bhatbcda53f2011-12-07 22:29:54 +010075 lock_system_sleep();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020076 suspend_ops = ops;
Srivatsa S. Bhatbcda53f2011-12-07 22:29:54 +010077 unlock_system_sleep();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020078}
Kevin Hilmana5e4fd82011-06-27 01:01:07 +020079EXPORT_SYMBOL_GPL(suspend_set_ops);
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020080
81bool valid_state(suspend_state_t state)
82{
Zhang Ruic26b78a2013-03-27 03:36:11 +000083 if (state == PM_SUSPEND_FREEZE) {
84#ifdef CONFIG_PM_DEBUG
85 if (pm_test_level != TEST_NONE &&
86 pm_test_level != TEST_FREEZER &&
87 pm_test_level != TEST_DEVICES &&
88 pm_test_level != TEST_PLATFORM) {
89 printk(KERN_WARNING "Unsupported pm_test mode for "
90 "freeze state, please choose "
91 "none/freezer/devices/platform.\n");
92 return false;
93 }
94#endif
95 return true;
96 }
Rafael J. Wysockia9d70522009-06-10 01:27:12 +020097 /*
Zhang Rui7e73c5ae2013-02-06 13:00:36 +010098 * PM_SUSPEND_STANDBY and PM_SUSPEND_MEMORY states need lowlevel
99 * support and need to be valid to the lowlevel
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200100 * implementation, no valid callback implies that none are valid.
101 */
102 return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
103}
104
105/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100106 * suspend_valid_only_mem - Generic memory-only valid callback.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200107 *
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100108 * Platform drivers that implement mem suspend only and only need to check for
109 * that in their .valid() callback can use this instead of rolling their own
110 * .valid() callback.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200111 */
112int suspend_valid_only_mem(suspend_state_t state)
113{
114 return state == PM_SUSPEND_MEM;
115}
Kevin Hilmana5e4fd82011-06-27 01:01:07 +0200116EXPORT_SYMBOL_GPL(suspend_valid_only_mem);
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200117
118static int suspend_test(int level)
119{
120#ifdef CONFIG_PM_DEBUG
121 if (pm_test_level == level) {
122 printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
123 mdelay(5000);
124 return 1;
125 }
126#endif /* !CONFIG_PM_DEBUG */
127 return 0;
128}
129
130/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100131 * suspend_prepare - Prepare for entering system sleep state.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200132 *
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100133 * Common code run for every system sleep state that can be entered (except for
134 * hibernation). Run suspend notifiers, allocate the "suspend" console and
135 * freeze processes.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200136 */
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100137static int suspend_prepare(suspend_state_t state)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200138{
139 int error;
140
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100141 if (need_suspend_ops(state) && (!suspend_ops || !suspend_ops->enter))
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200142 return -EPERM;
143
144 pm_prepare_console();
145
146 error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
147 if (error)
148 goto Finish;
149
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200150 error = suspend_freeze_processes();
Tejun Heo03afed82011-11-21 12:32:24 -0800151 if (!error)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200152 return 0;
153
Tejun Heo03afed82011-11-21 12:32:24 -0800154 suspend_stats.failed_freeze++;
155 dpm_save_failed_step(SUSPEND_FREEZE);
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200156 Finish:
157 pm_notifier_call_chain(PM_POST_SUSPEND);
158 pm_restore_console();
159 return error;
160}
161
162/* default implementation */
Gideon Israel Dsouza52f5684c2014-04-07 15:39:20 -0700163void __weak arch_suspend_disable_irqs(void)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200164{
165 local_irq_disable();
166}
167
168/* default implementation */
Gideon Israel Dsouza52f5684c2014-04-07 15:39:20 -0700169void __weak arch_suspend_enable_irqs(void)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200170{
171 local_irq_enable();
172}
173
174/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100175 * suspend_enter - Make the system enter the given sleep state.
176 * @state: System sleep state to enter.
177 * @wakeup: Returns information that the sleep state should not be re-entered.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200178 *
MyungJoo Ham3b5fe852011-06-12 15:57:05 +0200179 * This function should be called after devices have been suspended.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200180 */
MyungJoo Ham3b5fe852011-06-12 15:57:05 +0200181static int suspend_enter(suspend_state_t state, bool *wakeup)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200182{
183 int error;
184
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100185 if (need_suspend_ops(state) && suspend_ops->prepare) {
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200186 error = suspend_ops->prepare();
187 if (error)
Rafael J. Wysockice441012010-07-07 23:43:45 +0200188 goto Platform_finish;
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200189 }
190
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100191 error = dpm_suspend_end(PMSG_SUSPEND);
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200192 if (error) {
193 printk(KERN_ERR "PM: Some devices failed to power down\n");
Rafael J. Wysockice441012010-07-07 23:43:45 +0200194 goto Platform_finish;
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200195 }
196
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100197 if (need_suspend_ops(state) && suspend_ops->prepare_late) {
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200198 error = suspend_ops->prepare_late();
199 if (error)
Rafael J. Wysockice441012010-07-07 23:43:45 +0200200 goto Platform_wake;
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200201 }
202
Zhang Rui08605ac2013-03-27 03:36:10 +0000203 if (suspend_test(TEST_PLATFORM))
204 goto Platform_wake;
205
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100206 /*
207 * PM_SUSPEND_FREEZE equals
208 * frozen processes + suspended devices + idle processors.
209 * Thus we should invoke freeze_enter() soon after
210 * all the devices are suspended.
211 */
212 if (state == PM_SUSPEND_FREEZE) {
213 freeze_enter();
214 goto Platform_wake;
215 }
216
Brandt, Todd E38312612013-07-11 07:44:35 +0000217 ftrace_stop();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200218 error = disable_nonboot_cpus();
219 if (error || suspend_test(TEST_CPUS))
220 goto Enable_cpus;
221
222 arch_suspend_disable_irqs();
223 BUG_ON(!irqs_disabled());
224
Rafael J. Wysocki2e711c02011-04-26 19:15:07 +0200225 error = syscore_suspend();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200226 if (!error) {
MyungJoo Ham3b5fe852011-06-12 15:57:05 +0200227 *wakeup = pm_wakeup_pending();
228 if (!(suspend_test(TEST_CORE) || *wakeup)) {
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200229 error = suspend_ops->enter(state);
Rafael J. Wysockic125e962010-07-05 22:43:53 +0200230 events_check_enabled = false;
231 }
Rafael J. Wysocki40dc1662011-03-15 00:43:46 +0100232 syscore_resume();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200233 }
234
235 arch_suspend_enable_irqs();
236 BUG_ON(irqs_disabled());
237
238 Enable_cpus:
239 enable_nonboot_cpus();
Brandt, Todd E38312612013-07-11 07:44:35 +0000240 ftrace_start();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200241
242 Platform_wake:
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100243 if (need_suspend_ops(state) && suspend_ops->wake)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200244 suspend_ops->wake();
245
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100246 dpm_resume_start(PMSG_RESUME);
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200247
Rafael J. Wysockice441012010-07-07 23:43:45 +0200248 Platform_finish:
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100249 if (need_suspend_ops(state) && suspend_ops->finish)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200250 suspend_ops->finish();
251
252 return error;
253}
254
255/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100256 * suspend_devices_and_enter - Suspend devices and enter system sleep state.
257 * @state: System sleep state to enter.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200258 */
259int suspend_devices_and_enter(suspend_state_t state)
260{
261 int error;
MyungJoo Ham3b5fe852011-06-12 15:57:05 +0200262 bool wakeup = false;
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200263
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100264 if (need_suspend_ops(state) && !suspend_ops)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200265 return -ENOSYS;
266
Jean Pihet938cfed2011-01-05 19:49:01 +0100267 trace_machine_suspend(state);
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100268 if (need_suspend_ops(state) && suspend_ops->begin) {
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200269 error = suspend_ops->begin(state);
270 if (error)
271 goto Close;
272 }
273 suspend_console();
274 suspend_test_start();
275 error = dpm_suspend_start(PMSG_SUSPEND);
276 if (error) {
Bernie Thompson9350de062013-06-01 00:47:43 +0000277 pr_err("PM: Some devices failed to suspend, or early wake event detected\n");
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200278 goto Recover_platform;
279 }
280 suspend_test_finish("suspend devices");
281 if (suspend_test(TEST_DEVICES))
282 goto Recover_platform;
283
MyungJoo Ham3b5fe852011-06-12 15:57:05 +0200284 do {
285 error = suspend_enter(state, &wakeup);
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100286 } while (!error && !wakeup && need_suspend_ops(state)
MyungJoo Ham3b5fe852011-06-12 15:57:05 +0200287 && suspend_ops->suspend_again && suspend_ops->suspend_again());
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200288
289 Resume_devices:
290 suspend_test_start();
291 dpm_resume_end(PMSG_RESUME);
292 suspend_test_finish("resume devices");
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200293 resume_console();
294 Close:
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100295 if (need_suspend_ops(state) && suspend_ops->end)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200296 suspend_ops->end();
Jean Pihet938cfed2011-01-05 19:49:01 +0100297 trace_machine_suspend(PWR_EVENT_EXIT);
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200298 return error;
299
300 Recover_platform:
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100301 if (need_suspend_ops(state) && suspend_ops->recover)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200302 suspend_ops->recover();
303 goto Resume_devices;
304}
305
306/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100307 * suspend_finish - Clean up before finishing the suspend sequence.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200308 *
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100309 * Call platform code to clean up, restart processes, and free the console that
310 * we've allocated. This routine is not called for hibernation.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200311 */
312static void suspend_finish(void)
313{
314 suspend_thaw_processes();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200315 pm_notifier_call_chain(PM_POST_SUSPEND);
316 pm_restore_console();
317}
318
319/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100320 * enter_state - Do common work needed to enter system sleep state.
321 * @state: System sleep state to enter.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200322 *
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100323 * Make sure that no one else is trying to put the system into a sleep state.
324 * Fail if that's not the case. Otherwise, prepare for system suspend, make the
325 * system enter the given sleep state and clean up after wakeup.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200326 */
Rafael J. Wysocki93e1ee42012-02-13 16:29:24 +0100327static int enter_state(suspend_state_t state)
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200328{
329 int error;
330
331 if (!valid_state(state))
332 return -ENODEV;
333
334 if (!mutex_trylock(&pm_mutex))
335 return -EBUSY;
336
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100337 if (state == PM_SUSPEND_FREEZE)
338 freeze_begin();
339
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200340 printk(KERN_INFO "PM: Syncing filesystems ... ");
341 sys_sync();
342 printk("done.\n");
343
344 pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
Zhang Rui7e73c5ae2013-02-06 13:00:36 +0100345 error = suspend_prepare(state);
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200346 if (error)
347 goto Unlock;
348
349 if (suspend_test(TEST_FREEZER))
350 goto Finish;
351
352 pr_debug("PM: Entering %s sleep\n", pm_states[state]);
Rafael J. Wysocki87186472011-05-10 21:09:53 +0200353 pm_restrict_gfp_mask();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200354 error = suspend_devices_and_enter(state);
Rafael J. Wysocki87186472011-05-10 21:09:53 +0200355 pm_restore_gfp_mask();
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200356
357 Finish:
358 pr_debug("PM: Finishing wakeup.\n");
359 suspend_finish();
360 Unlock:
361 mutex_unlock(&pm_mutex);
362 return error;
363}
364
365/**
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100366 * pm_suspend - Externally visible function for suspending the system.
367 * @state: System sleep state to enter.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200368 *
Rafael J. Wysocki55ae4512012-02-13 16:29:14 +0100369 * Check if the value of @state represents one of the supported states,
370 * execute enter_state() and update system suspend statistics.
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200371 */
372int pm_suspend(suspend_state_t state)
373{
Rafael J. Wysockibc25cf52012-02-13 16:29:33 +0100374 int error;
375
376 if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
377 return -EINVAL;
378
379 error = enter_state(state);
380 if (error) {
381 suspend_stats.fail++;
382 dpm_save_failed_errno(error);
383 } else {
384 suspend_stats.success++;
ShuoX Liu2a77c462011-08-10 23:01:26 +0200385 }
Rafael J. Wysockibc25cf52012-02-13 16:29:33 +0100386 return error;
Rafael J. Wysockia9d70522009-06-10 01:27:12 +0200387}
388EXPORT_SYMBOL(pm_suspend);