diff options
-rw-r--r-- | Documentation/power/devices.txt | 4 | ||||
-rw-r--r-- | include/linux/freezer.h | 4 | ||||
-rw-r--r-- | kernel/power/hibernate.c | 12 | ||||
-rw-r--r-- | kernel/power/power.h | 3 | ||||
-rw-r--r-- | kernel/power/process.c | 30 |
5 files changed, 33 insertions, 20 deletions
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 29b7a9817f5a..646a89e0c07d 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt | |||
@@ -281,10 +281,6 @@ When the system goes into the standby or memory sleep state, the phases are: | |||
281 | time.) Unlike the other suspend-related phases, during the prepare | 281 | time.) Unlike the other suspend-related phases, during the prepare |
282 | phase the device tree is traversed top-down. | 282 | phase the device tree is traversed top-down. |
283 | 283 | ||
284 | In addition to that, if device drivers need to allocate additional | ||
285 | memory to be able to hadle device suspend correctly, that should be | ||
286 | done in the prepare phase. | ||
287 | |||
288 | After the prepare callback method returns, no new children may be | 284 | After the prepare callback method returns, no new children may be |
289 | registered below the device. The method may also prepare the device or | 285 | registered below the device. The method may also prepare the device or |
290 | driver in some way for the upcoming system power transition (for | 286 | driver in some way for the upcoming system power transition (for |
diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 1effc8b56b4e..aa56cf31f7ff 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h | |||
@@ -49,6 +49,7 @@ extern int thaw_process(struct task_struct *p); | |||
49 | 49 | ||
50 | extern void refrigerator(void); | 50 | extern void refrigerator(void); |
51 | extern int freeze_processes(void); | 51 | extern int freeze_processes(void); |
52 | extern int freeze_kernel_threads(void); | ||
52 | extern void thaw_processes(void); | 53 | extern void thaw_processes(void); |
53 | 54 | ||
54 | static inline int try_to_freeze(void) | 55 | static inline int try_to_freeze(void) |
@@ -171,7 +172,8 @@ static inline void clear_freeze_flag(struct task_struct *p) {} | |||
171 | static inline int thaw_process(struct task_struct *p) { return 1; } | 172 | static inline int thaw_process(struct task_struct *p) { return 1; } |
172 | 173 | ||
173 | static inline void refrigerator(void) {} | 174 | static inline void refrigerator(void) {} |
174 | static inline int freeze_processes(void) { BUG(); return 0; } | 175 | static inline int freeze_processes(void) { return -ENOSYS; } |
176 | static inline int freeze_kernel_threads(void) { return -ENOSYS; } | ||
175 | static inline void thaw_processes(void) {} | 177 | static inline void thaw_processes(void) {} |
176 | 178 | ||
177 | static inline int try_to_freeze(void) { return 0; } | 179 | static inline int try_to_freeze(void) { return 0; } |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 8f7b1db1ece1..3a20466015f8 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
@@ -334,13 +334,17 @@ int hibernation_snapshot(int platform_mode) | |||
334 | if (error) | 334 | if (error) |
335 | goto Close; | 335 | goto Close; |
336 | 336 | ||
337 | error = dpm_prepare(PMSG_FREEZE); | ||
338 | if (error) | ||
339 | goto Complete_devices; | ||
340 | |||
341 | /* Preallocate image memory before shutting down devices. */ | 337 | /* Preallocate image memory before shutting down devices. */ |
342 | error = hibernate_preallocate_memory(); | 338 | error = hibernate_preallocate_memory(); |
343 | if (error) | 339 | if (error) |
340 | goto Close; | ||
341 | |||
342 | error = freeze_kernel_threads(); | ||
343 | if (error) | ||
344 | goto Close; | ||
345 | |||
346 | error = dpm_prepare(PMSG_FREEZE); | ||
347 | if (error) | ||
344 | goto Complete_devices; | 348 | goto Complete_devices; |
345 | 349 | ||
346 | suspend_console(); | 350 | suspend_console(); |
diff --git a/kernel/power/power.h b/kernel/power/power.h index 9a00a0a26280..e6206397ce67 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -228,7 +228,8 @@ extern int pm_test_level; | |||
228 | #ifdef CONFIG_SUSPEND_FREEZER | 228 | #ifdef CONFIG_SUSPEND_FREEZER |
229 | static inline int suspend_freeze_processes(void) | 229 | static inline int suspend_freeze_processes(void) |
230 | { | 230 | { |
231 | return freeze_processes(); | 231 | int error = freeze_processes(); |
232 | return error ? : freeze_kernel_threads(); | ||
232 | } | 233 | } |
233 | 234 | ||
234 | static inline void suspend_thaw_processes(void) | 235 | static inline void suspend_thaw_processes(void) |
diff --git a/kernel/power/process.c b/kernel/power/process.c index 0cf3a27a6c9d..addbbe5531bc 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c | |||
@@ -135,7 +135,7 @@ static int try_to_freeze_tasks(bool sig_only) | |||
135 | } | 135 | } |
136 | 136 | ||
137 | /** | 137 | /** |
138 | * freeze_processes - tell processes to enter the refrigerator | 138 | * freeze_processes - Signal user space processes to enter the refrigerator. |
139 | */ | 139 | */ |
140 | int freeze_processes(void) | 140 | int freeze_processes(void) |
141 | { | 141 | { |
@@ -143,20 +143,30 @@ int freeze_processes(void) | |||
143 | 143 | ||
144 | printk("Freezing user space processes ... "); | 144 | printk("Freezing user space processes ... "); |
145 | error = try_to_freeze_tasks(true); | 145 | error = try_to_freeze_tasks(true); |
146 | if (error) | 146 | if (!error) { |
147 | goto Exit; | 147 | printk("done."); |
148 | printk("done.\n"); | 148 | oom_killer_disable(); |
149 | } | ||
150 | printk("\n"); | ||
151 | BUG_ON(in_atomic()); | ||
152 | |||
153 | return error; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator. | ||
158 | */ | ||
159 | int freeze_kernel_threads(void) | ||
160 | { | ||
161 | int error; | ||
149 | 162 | ||
150 | printk("Freezing remaining freezable tasks ... "); | 163 | printk("Freezing remaining freezable tasks ... "); |
151 | error = try_to_freeze_tasks(false); | 164 | error = try_to_freeze_tasks(false); |
152 | if (error) | 165 | if (!error) |
153 | goto Exit; | 166 | printk("done."); |
154 | printk("done."); | ||
155 | 167 | ||
156 | oom_killer_disable(); | ||
157 | Exit: | ||
158 | BUG_ON(in_atomic()); | ||
159 | printk("\n"); | 168 | printk("\n"); |
169 | BUG_ON(in_atomic()); | ||
160 | 170 | ||
161 | return error; | 171 | return error; |
162 | } | 172 | } |