diff options
Diffstat (limited to 'kernel/power/suspend.c')
-rw-r--r-- | kernel/power/suspend.c | 91 |
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] = { | |||
37 | static const struct platform_suspend_ops *suspend_ops; | 36 | static 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 | */ |
43 | void suspend_set_ops(const struct platform_suspend_ops *ops) | 42 | void 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 | */ |
67 | int suspend_valid_only_mem(suspend_state_t state) | 66 | int 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 | */ |
91 | static int suspend_prepare(void) | 91 | static 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 | */ |
206 | int suspend_devices_and_enter(suspend_state_t state) | 200 | int 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 | */ |
259 | static void suspend_finish(void) | 253 | static 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 | */ |
277 | int enter_state(suspend_state_t state) | 268 | static 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 | */ |
319 | int pm_suspend(suspend_state_t state) | 310 | int 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 | } |
333 | EXPORT_SYMBOL(pm_suspend); | 326 | EXPORT_SYMBOL(pm_suspend); |