aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power/suspend.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/power/suspend.c')
-rw-r--r--kernel/power/suspend.c91
1 files changed, 42 insertions, 49 deletions
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 4fd51beed879..396d262b8fd0 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -12,7 +12,6 @@
12#include <linux/delay.h> 12#include <linux/delay.h>
13#include <linux/errno.h> 13#include <linux/errno.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/kmod.h>
16#include <linux/console.h> 15#include <linux/console.h>
17#include <linux/cpu.h> 16#include <linux/cpu.h>
18#include <linux/syscalls.h> 17#include <linux/syscalls.h>
@@ -37,8 +36,8 @@ const char *const pm_states[PM_SUSPEND_MAX] = {
37static const struct platform_suspend_ops *suspend_ops; 36static const struct platform_suspend_ops *suspend_ops;
38 37
39/** 38/**
40 * suspend_set_ops - Set the global suspend method table. 39 * suspend_set_ops - Set the global suspend method table.
41 * @ops: Pointer to ops structure. 40 * @ops: Suspend operations to use.
42 */ 41 */
43void suspend_set_ops(const struct platform_suspend_ops *ops) 42void suspend_set_ops(const struct platform_suspend_ops *ops)
44{ 43{
@@ -58,11 +57,11 @@ bool valid_state(suspend_state_t state)
58} 57}
59 58
60/** 59/**
61 * suspend_valid_only_mem - generic memory-only valid callback 60 * suspend_valid_only_mem - Generic memory-only valid callback.
62 * 61 *
63 * Platform drivers that implement mem suspend only and only need 62 * Platform drivers that implement mem suspend only and only need to check for
64 * to check for that in their .valid callback can use this instead 63 * that in their .valid() callback can use this instead of rolling their own
65 * of rolling their own .valid callback. 64 * .valid() callback.
66 */ 65 */
67int suspend_valid_only_mem(suspend_state_t state) 66int suspend_valid_only_mem(suspend_state_t state)
68{ 67{
@@ -83,10 +82,11 @@ static int suspend_test(int level)
83} 82}
84 83
85/** 84/**
86 * suspend_prepare - Do prep work before entering low-power state. 85 * suspend_prepare - Prepare for entering system sleep state.
87 * 86 *
88 * This is common code that is called for each state that we're entering. 87 * Common code run for every system sleep state that can be entered (except for
89 * Run suspend notifiers, allocate a console and stop all processes. 88 * hibernation). Run suspend notifiers, allocate the "suspend" console and
89 * freeze processes.
90 */ 90 */
91static int suspend_prepare(void) 91static int suspend_prepare(void)
92{ 92{
@@ -101,17 +101,12 @@ static int suspend_prepare(void)
101 if (error) 101 if (error)
102 goto Finish; 102 goto Finish;
103 103
104 error = usermodehelper_disable();
105 if (error)
106 goto Finish;
107
108 error = suspend_freeze_processes(); 104 error = suspend_freeze_processes();
109 if (!error) 105 if (!error)
110 return 0; 106 return 0;
111 107
112 suspend_stats.failed_freeze++; 108 suspend_stats.failed_freeze++;
113 dpm_save_failed_step(SUSPEND_FREEZE); 109 dpm_save_failed_step(SUSPEND_FREEZE);
114 usermodehelper_enable();
115 Finish: 110 Finish:
116 pm_notifier_call_chain(PM_POST_SUSPEND); 111 pm_notifier_call_chain(PM_POST_SUSPEND);
117 pm_restore_console(); 112 pm_restore_console();
@@ -131,9 +126,9 @@ void __attribute__ ((weak)) arch_suspend_enable_irqs(void)
131} 126}
132 127
133/** 128/**
134 * suspend_enter - enter the desired system sleep state. 129 * suspend_enter - Make the system enter the given sleep state.
135 * @state: State to enter 130 * @state: System sleep state to enter.
136 * @wakeup: Returns information that suspend should not be entered again. 131 * @wakeup: Returns information that the sleep state should not be re-entered.
137 * 132 *
138 * This function should be called after devices have been suspended. 133 * This function should be called after devices have been suspended.
139 */ 134 */
@@ -147,7 +142,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
147 goto Platform_finish; 142 goto Platform_finish;
148 } 143 }
149 144
150 error = dpm_suspend_noirq(PMSG_SUSPEND); 145 error = dpm_suspend_end(PMSG_SUSPEND);
151 if (error) { 146 if (error) {
152 printk(KERN_ERR "PM: Some devices failed to power down\n"); 147 printk(KERN_ERR "PM: Some devices failed to power down\n");
153 goto Platform_finish; 148 goto Platform_finish;
@@ -189,7 +184,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
189 if (suspend_ops->wake) 184 if (suspend_ops->wake)
190 suspend_ops->wake(); 185 suspend_ops->wake();
191 186
192 dpm_resume_noirq(PMSG_RESUME); 187 dpm_resume_start(PMSG_RESUME);
193 188
194 Platform_finish: 189 Platform_finish:
195 if (suspend_ops->finish) 190 if (suspend_ops->finish)
@@ -199,9 +194,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
199} 194}
200 195
201/** 196/**
202 * suspend_devices_and_enter - suspend devices and enter the desired system 197 * suspend_devices_and_enter - Suspend devices and enter system sleep state.
203 * sleep state. 198 * @state: System sleep state to enter.
204 * @state: state to enter
205 */ 199 */
206int suspend_devices_and_enter(suspend_state_t state) 200int suspend_devices_and_enter(suspend_state_t state)
207{ 201{
@@ -251,30 +245,27 @@ int suspend_devices_and_enter(suspend_state_t state)
251} 245}
252 246
253/** 247/**
254 * suspend_finish - Do final work before exiting suspend sequence. 248 * suspend_finish - Clean up before finishing the suspend sequence.
255 * 249 *
256 * Call platform code to clean up, restart processes, and free the 250 * Call platform code to clean up, restart processes, and free the console that
257 * console that we've allocated. This is not called for suspend-to-disk. 251 * we've allocated. This routine is not called for hibernation.
258 */ 252 */
259static void suspend_finish(void) 253static void suspend_finish(void)
260{ 254{
261 suspend_thaw_processes(); 255 suspend_thaw_processes();
262 usermodehelper_enable();
263 pm_notifier_call_chain(PM_POST_SUSPEND); 256 pm_notifier_call_chain(PM_POST_SUSPEND);
264 pm_restore_console(); 257 pm_restore_console();
265} 258}
266 259
267/** 260/**
268 * enter_state - Do common work of entering low-power state. 261 * enter_state - Do common work needed to enter system sleep state.
269 * @state: pm_state structure for state we're entering. 262 * @state: System sleep state to enter.
270 * 263 *
271 * Make sure we're the only ones trying to enter a sleep state. Fail 264 * Make sure that no one else is trying to put the system into a sleep state.
272 * if someone has beat us to it, since we don't want anything weird to 265 * Fail if that's not the case. Otherwise, prepare for system suspend, make the
273 * happen when we wake up. 266 * system enter the given sleep state and clean up after wakeup.
274 * Then, do the setup for suspend, enter the state, and cleaup (after
275 * we've woken up).
276 */ 267 */
277int enter_state(suspend_state_t state) 268static int enter_state(suspend_state_t state)
278{ 269{
279 int error; 270 int error;
280 271
@@ -310,24 +301,26 @@ int enter_state(suspend_state_t state)
310} 301}
311 302
312/** 303/**
313 * pm_suspend - Externally visible function for suspending system. 304 * pm_suspend - Externally visible function for suspending the system.
314 * @state: Enumerated value of state to enter. 305 * @state: System sleep state to enter.
315 * 306 *
316 * Determine whether or not value is within range, get state 307 * Check if the value of @state represents one of the supported states,
317 * structure, and enter (above). 308 * execute enter_state() and update system suspend statistics.
318 */ 309 */
319int pm_suspend(suspend_state_t state) 310int pm_suspend(suspend_state_t state)
320{ 311{
321 int ret; 312 int error;
322 if (state > PM_SUSPEND_ON && state < PM_SUSPEND_MAX) { 313
323 ret = enter_state(state); 314 if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
324 if (ret) { 315 return -EINVAL;
325 suspend_stats.fail++; 316
326 dpm_save_failed_errno(ret); 317 error = enter_state(state);
327 } else 318 if (error) {
328 suspend_stats.success++; 319 suspend_stats.fail++;
329 return ret; 320 dpm_save_failed_errno(error);
321 } else {
322 suspend_stats.success++;
330 } 323 }
331 return -EINVAL; 324 return error;
332} 325}
333EXPORT_SYMBOL(pm_suspend); 326EXPORT_SYMBOL(pm_suspend);