aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-31 02:31:57 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-31 02:31:57 -0500
commita9de18eb761f7c1c860964b2e5addc1a35c7e861 (patch)
tree886e75fdfd09690cd262ca69cb7f5d1d42b48602 /kernel/power
parentb2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (diff)
parent6a94cb73064c952255336cc57731904174b2c58f (diff)
Merge branch 'linus' into stackprotector
Conflicts: arch/x86/include/asm/pda.h kernel/fork.c
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/Kconfig2
-rw-r--r--kernel/power/disk.c26
-rw-r--r--kernel/power/main.c14
-rw-r--r--kernel/power/power.h2
-rw-r--r--kernel/power/process.c119
-rw-r--r--kernel/power/swap.c14
-rw-r--r--kernel/power/user.c10
7 files changed, 45 insertions, 142 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index dcd165f92a88..23bd4daeb96b 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -96,7 +96,7 @@ config SUSPEND
96 96
97config PM_TEST_SUSPEND 97config PM_TEST_SUSPEND
98 bool "Test suspend/resume and wakealarm during bootup" 98 bool "Test suspend/resume and wakealarm during bootup"
99 depends on SUSPEND && PM_DEBUG && RTC_LIB=y 99 depends on SUSPEND && PM_DEBUG && RTC_CLASS=y
100 ---help--- 100 ---help---
101 This option will let you suspend your machine during bootup, and 101 This option will let you suspend your machine during bootup, and
102 make it wake up a few seconds later using an RTC wakeup alarm. 102 make it wake up a few seconds later using an RTC wakeup alarm.
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index bbd85c60f741..f77d3819ef57 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -14,6 +14,7 @@
14#include <linux/reboot.h> 14#include <linux/reboot.h>
15#include <linux/string.h> 15#include <linux/string.h>
16#include <linux/device.h> 16#include <linux/device.h>
17#include <linux/kmod.h>
17#include <linux/delay.h> 18#include <linux/delay.h>
18#include <linux/fs.h> 19#include <linux/fs.h>
19#include <linux/mount.h> 20#include <linux/mount.h>
@@ -21,7 +22,6 @@
21#include <linux/console.h> 22#include <linux/console.h>
22#include <linux/cpu.h> 23#include <linux/cpu.h>
23#include <linux/freezer.h> 24#include <linux/freezer.h>
24#include <linux/ftrace.h>
25 25
26#include "power.h" 26#include "power.h"
27 27
@@ -256,7 +256,7 @@ static int create_image(int platform_mode)
256 256
257int hibernation_snapshot(int platform_mode) 257int hibernation_snapshot(int platform_mode)
258{ 258{
259 int error, ftrace_save; 259 int error;
260 260
261 /* Free memory before shutting down devices. */ 261 /* Free memory before shutting down devices. */
262 error = swsusp_shrink_memory(); 262 error = swsusp_shrink_memory();
@@ -268,7 +268,6 @@ int hibernation_snapshot(int platform_mode)
268 goto Close; 268 goto Close;
269 269
270 suspend_console(); 270 suspend_console();
271 ftrace_save = __ftrace_enabled_save();
272 error = device_suspend(PMSG_FREEZE); 271 error = device_suspend(PMSG_FREEZE);
273 if (error) 272 if (error)
274 goto Recover_platform; 273 goto Recover_platform;
@@ -298,7 +297,6 @@ int hibernation_snapshot(int platform_mode)
298 Resume_devices: 297 Resume_devices:
299 device_resume(in_suspend ? 298 device_resume(in_suspend ?
300 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 299 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
301 __ftrace_enabled_restore(ftrace_save);
302 resume_console(); 300 resume_console();
303 Close: 301 Close:
304 platform_end(platform_mode); 302 platform_end(platform_mode);
@@ -369,11 +367,10 @@ static int resume_target_kernel(void)
369 367
370int hibernation_restore(int platform_mode) 368int hibernation_restore(int platform_mode)
371{ 369{
372 int error, ftrace_save; 370 int error;
373 371
374 pm_prepare_console(); 372 pm_prepare_console();
375 suspend_console(); 373 suspend_console();
376 ftrace_save = __ftrace_enabled_save();
377 error = device_suspend(PMSG_QUIESCE); 374 error = device_suspend(PMSG_QUIESCE);
378 if (error) 375 if (error)
379 goto Finish; 376 goto Finish;
@@ -388,7 +385,6 @@ int hibernation_restore(int platform_mode)
388 platform_restore_cleanup(platform_mode); 385 platform_restore_cleanup(platform_mode);
389 device_resume(PMSG_RECOVER); 386 device_resume(PMSG_RECOVER);
390 Finish: 387 Finish:
391 __ftrace_enabled_restore(ftrace_save);
392 resume_console(); 388 resume_console();
393 pm_restore_console(); 389 pm_restore_console();
394 return error; 390 return error;
@@ -401,7 +397,7 @@ int hibernation_restore(int platform_mode)
401 397
402int hibernation_platform_enter(void) 398int hibernation_platform_enter(void)
403{ 399{
404 int error, ftrace_save; 400 int error;
405 401
406 if (!hibernation_ops) 402 if (!hibernation_ops)
407 return -ENOSYS; 403 return -ENOSYS;
@@ -416,7 +412,6 @@ int hibernation_platform_enter(void)
416 goto Close; 412 goto Close;
417 413
418 suspend_console(); 414 suspend_console();
419 ftrace_save = __ftrace_enabled_save();
420 error = device_suspend(PMSG_HIBERNATE); 415 error = device_suspend(PMSG_HIBERNATE);
421 if (error) { 416 if (error) {
422 if (hibernation_ops->recover) 417 if (hibernation_ops->recover)
@@ -451,7 +446,6 @@ int hibernation_platform_enter(void)
451 hibernation_ops->finish(); 446 hibernation_ops->finish();
452 Resume_devices: 447 Resume_devices:
453 device_resume(PMSG_RESTORE); 448 device_resume(PMSG_RESTORE);
454 __ftrace_enabled_restore(ftrace_save);
455 resume_console(); 449 resume_console();
456 Close: 450 Close:
457 hibernation_ops->end(); 451 hibernation_ops->end();
@@ -520,6 +514,10 @@ int hibernate(void)
520 if (error) 514 if (error)
521 goto Exit; 515 goto Exit;
522 516
517 error = usermodehelper_disable();
518 if (error)
519 goto Exit;
520
523 /* Allocate memory management structures */ 521 /* Allocate memory management structures */
524 error = create_basic_memory_bitmaps(); 522 error = create_basic_memory_bitmaps();
525 if (error) 523 if (error)
@@ -558,6 +556,7 @@ int hibernate(void)
558 thaw_processes(); 556 thaw_processes();
559 Finish: 557 Finish:
560 free_basic_memory_bitmaps(); 558 free_basic_memory_bitmaps();
559 usermodehelper_enable();
561 Exit: 560 Exit:
562 pm_notifier_call_chain(PM_POST_HIBERNATION); 561 pm_notifier_call_chain(PM_POST_HIBERNATION);
563 pm_restore_console(); 562 pm_restore_console();
@@ -634,6 +633,10 @@ static int software_resume(void)
634 if (error) 633 if (error)
635 goto Finish; 634 goto Finish;
636 635
636 error = usermodehelper_disable();
637 if (error)
638 goto Finish;
639
637 error = create_basic_memory_bitmaps(); 640 error = create_basic_memory_bitmaps();
638 if (error) 641 if (error)
639 goto Finish; 642 goto Finish;
@@ -641,7 +644,7 @@ static int software_resume(void)
641 pr_debug("PM: Preparing processes for restore.\n"); 644 pr_debug("PM: Preparing processes for restore.\n");
642 error = prepare_processes(); 645 error = prepare_processes();
643 if (error) { 646 if (error) {
644 swsusp_close(); 647 swsusp_close(FMODE_READ);
645 goto Done; 648 goto Done;
646 } 649 }
647 650
@@ -656,6 +659,7 @@ static int software_resume(void)
656 thaw_processes(); 659 thaw_processes();
657 Done: 660 Done:
658 free_basic_memory_bitmaps(); 661 free_basic_memory_bitmaps();
662 usermodehelper_enable();
659 Finish: 663 Finish:
660 pm_notifier_call_chain(PM_POST_RESTORE); 664 pm_notifier_call_chain(PM_POST_RESTORE);
661 pm_restore_console(); 665 pm_restore_console();
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 540b16b68565..613f16941b85 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -14,6 +14,7 @@
14#include <linux/string.h> 14#include <linux/string.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <linux/kmod.h>
17#include <linux/init.h> 18#include <linux/init.h>
18#include <linux/console.h> 19#include <linux/console.h>
19#include <linux/cpu.h> 20#include <linux/cpu.h>
@@ -21,7 +22,6 @@
21#include <linux/freezer.h> 22#include <linux/freezer.h>
22#include <linux/vmstat.h> 23#include <linux/vmstat.h>
23#include <linux/syscalls.h> 24#include <linux/syscalls.h>
24#include <linux/ftrace.h>
25 25
26#include "power.h" 26#include "power.h"
27 27
@@ -173,7 +173,7 @@ static void suspend_test_finish(const char *label)
173 * has some performance issues. The stack dump of a WARN_ON 173 * has some performance issues. The stack dump of a WARN_ON
174 * is more likely to get the right attention than a printk... 174 * is more likely to get the right attention than a printk...
175 */ 175 */
176 WARN_ON(msec > (TEST_SUSPEND_SECONDS * 1000)); 176 WARN(msec > (TEST_SUSPEND_SECONDS * 1000), "Component: %s\n", label);
177} 177}
178 178
179#else 179#else
@@ -237,6 +237,10 @@ static int suspend_prepare(void)
237 if (error) 237 if (error)
238 goto Finish; 238 goto Finish;
239 239
240 error = usermodehelper_disable();
241 if (error)
242 goto Finish;
243
240 if (suspend_freeze_processes()) { 244 if (suspend_freeze_processes()) {
241 error = -EAGAIN; 245 error = -EAGAIN;
242 goto Thaw; 246 goto Thaw;
@@ -256,6 +260,7 @@ static int suspend_prepare(void)
256 260
257 Thaw: 261 Thaw:
258 suspend_thaw_processes(); 262 suspend_thaw_processes();
263 usermodehelper_enable();
259 Finish: 264 Finish:
260 pm_notifier_call_chain(PM_POST_SUSPEND); 265 pm_notifier_call_chain(PM_POST_SUSPEND);
261 pm_restore_console(); 266 pm_restore_console();
@@ -311,7 +316,7 @@ static int suspend_enter(suspend_state_t state)
311 */ 316 */
312int suspend_devices_and_enter(suspend_state_t state) 317int suspend_devices_and_enter(suspend_state_t state)
313{ 318{
314 int error, ftrace_save; 319 int error;
315 320
316 if (!suspend_ops) 321 if (!suspend_ops)
317 return -ENOSYS; 322 return -ENOSYS;
@@ -322,7 +327,6 @@ int suspend_devices_and_enter(suspend_state_t state)
322 goto Close; 327 goto Close;
323 } 328 }
324 suspend_console(); 329 suspend_console();
325 ftrace_save = __ftrace_enabled_save();
326 suspend_test_start(); 330 suspend_test_start();
327 error = device_suspend(PMSG_SUSPEND); 331 error = device_suspend(PMSG_SUSPEND);
328 if (error) { 332 if (error) {
@@ -354,7 +358,6 @@ int suspend_devices_and_enter(suspend_state_t state)
354 suspend_test_start(); 358 suspend_test_start();
355 device_resume(PMSG_RESUME); 359 device_resume(PMSG_RESUME);
356 suspend_test_finish("resume devices"); 360 suspend_test_finish("resume devices");
357 __ftrace_enabled_restore(ftrace_save);
358 resume_console(); 361 resume_console();
359 Close: 362 Close:
360 if (suspend_ops->end) 363 if (suspend_ops->end)
@@ -376,6 +379,7 @@ int suspend_devices_and_enter(suspend_state_t state)
376static void suspend_finish(void) 379static void suspend_finish(void)
377{ 380{
378 suspend_thaw_processes(); 381 suspend_thaw_processes();
382 usermodehelper_enable();
379 pm_notifier_call_chain(PM_POST_SUSPEND); 383 pm_notifier_call_chain(PM_POST_SUSPEND);
380 pm_restore_console(); 384 pm_restore_console();
381} 385}
diff --git a/kernel/power/power.h b/kernel/power/power.h
index acc0c101dbd5..46b5ec7a3afb 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -153,7 +153,7 @@ extern int swsusp_shrink_memory(void);
153extern void swsusp_free(void); 153extern void swsusp_free(void);
154extern int swsusp_read(unsigned int *flags_p); 154extern int swsusp_read(unsigned int *flags_p);
155extern int swsusp_write(unsigned int flags); 155extern int swsusp_write(unsigned int flags);
156extern void swsusp_close(void); 156extern void swsusp_close(fmode_t);
157 157
158struct timeval; 158struct timeval;
159/* kernel/power/swsusp.c */ 159/* kernel/power/swsusp.c */
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 278946aecaf0..ca634019497a 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -28,121 +28,6 @@ static inline int freezeable(struct task_struct * p)
28 return 1; 28 return 1;
29} 29}
30 30
31/*
32 * freezing is complete, mark current process as frozen
33 */
34static inline void frozen_process(void)
35{
36 if (!unlikely(current->flags & PF_NOFREEZE)) {
37 current->flags |= PF_FROZEN;
38 wmb();
39 }
40 clear_freeze_flag(current);
41}
42
43/* Refrigerator is place where frozen processes are stored :-). */
44void refrigerator(void)
45{
46 /* Hmm, should we be allowed to suspend when there are realtime
47 processes around? */
48 long save;
49
50 task_lock(current);
51 if (freezing(current)) {
52 frozen_process();
53 task_unlock(current);
54 } else {
55 task_unlock(current);
56 return;
57 }
58 save = current->state;
59 pr_debug("%s entered refrigerator\n", current->comm);
60
61 spin_lock_irq(&current->sighand->siglock);
62 recalc_sigpending(); /* We sent fake signal, clean it up */
63 spin_unlock_irq(&current->sighand->siglock);
64
65 for (;;) {
66 set_current_state(TASK_UNINTERRUPTIBLE);
67 if (!frozen(current))
68 break;
69 schedule();
70 }
71 pr_debug("%s left refrigerator\n", current->comm);
72 __set_current_state(save);
73}
74
75static void fake_signal_wake_up(struct task_struct *p)
76{
77 unsigned long flags;
78
79 spin_lock_irqsave(&p->sighand->siglock, flags);
80 signal_wake_up(p, 0);
81 spin_unlock_irqrestore(&p->sighand->siglock, flags);
82}
83
84static inline bool should_send_signal(struct task_struct *p)
85{
86 return !(p->flags & PF_FREEZER_NOSIG);
87}
88
89/**
90 * freeze_task - send a freeze request to given task
91 * @p: task to send the request to
92 * @sig_only: if set, the request will only be sent if the task has the
93 * PF_FREEZER_NOSIG flag unset
94 * Return value: 'false', if @sig_only is set and the task has
95 * PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise
96 *
97 * The freeze request is sent by setting the tasks's TIF_FREEZE flag and
98 * either sending a fake signal to it or waking it up, depending on whether
99 * or not it has PF_FREEZER_NOSIG set. If @sig_only is set and the task
100 * has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its
101 * TIF_FREEZE flag will not be set.
102 */
103static bool freeze_task(struct task_struct *p, bool sig_only)
104{
105 /*
106 * We first check if the task is freezing and next if it has already
107 * been frozen to avoid the race with frozen_process() which first marks
108 * the task as frozen and next clears its TIF_FREEZE.
109 */
110 if (!freezing(p)) {
111 rmb();
112 if (frozen(p))
113 return false;
114
115 if (!sig_only || should_send_signal(p))
116 set_freeze_flag(p);
117 else
118 return false;
119 }
120
121 if (should_send_signal(p)) {
122 if (!signal_pending(p))
123 fake_signal_wake_up(p);
124 } else if (sig_only) {
125 return false;
126 } else {
127 wake_up_state(p, TASK_INTERRUPTIBLE);
128 }
129
130 return true;
131}
132
133static void cancel_freezing(struct task_struct *p)
134{
135 unsigned long flags;
136
137 if (freezing(p)) {
138 pr_debug(" clean up: %s\n", p->comm);
139 clear_freeze_flag(p);
140 spin_lock_irqsave(&p->sighand->siglock, flags);
141 recalc_sigpending_and_wake(p);
142 spin_unlock_irqrestore(&p->sighand->siglock, flags);
143 }
144}
145
146static int try_to_freeze_tasks(bool sig_only) 31static int try_to_freeze_tasks(bool sig_only)
147{ 32{
148 struct task_struct *g, *p; 33 struct task_struct *g, *p;
@@ -250,6 +135,9 @@ static void thaw_tasks(bool nosig_only)
250 if (nosig_only && should_send_signal(p)) 135 if (nosig_only && should_send_signal(p))
251 continue; 136 continue;
252 137
138 if (cgroup_frozen(p))
139 continue;
140
253 thaw_process(p); 141 thaw_process(p);
254 } while_each_thread(g, p); 142 } while_each_thread(g, p);
255 read_unlock(&tasklist_lock); 143 read_unlock(&tasklist_lock);
@@ -264,4 +152,3 @@ void thaw_processes(void)
264 printk("done.\n"); 152 printk("done.\n");
265} 153}
266 154
267EXPORT_SYMBOL(refrigerator);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 80ccac849e46..6da14358537c 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -172,13 +172,13 @@ static int swsusp_swap_check(void) /* This is called before saving image */
172 return res; 172 return res;
173 173
174 root_swap = res; 174 root_swap = res;
175 res = blkdev_get(resume_bdev, FMODE_WRITE, O_RDWR); 175 res = blkdev_get(resume_bdev, FMODE_WRITE);
176 if (res) 176 if (res)
177 return res; 177 return res;
178 178
179 res = set_blocksize(resume_bdev, PAGE_SIZE); 179 res = set_blocksize(resume_bdev, PAGE_SIZE);
180 if (res < 0) 180 if (res < 0)
181 blkdev_put(resume_bdev); 181 blkdev_put(resume_bdev, FMODE_WRITE);
182 182
183 return res; 183 return res;
184} 184}
@@ -426,7 +426,7 @@ int swsusp_write(unsigned int flags)
426 426
427 release_swap_writer(&handle); 427 release_swap_writer(&handle);
428 out: 428 out:
429 swsusp_close(); 429 swsusp_close(FMODE_WRITE);
430 return error; 430 return error;
431} 431}
432 432
@@ -574,7 +574,7 @@ int swsusp_read(unsigned int *flags_p)
574 error = load_image(&handle, &snapshot, header->pages - 1); 574 error = load_image(&handle, &snapshot, header->pages - 1);
575 release_swap_reader(&handle); 575 release_swap_reader(&handle);
576 576
577 blkdev_put(resume_bdev); 577 blkdev_put(resume_bdev, FMODE_READ);
578 578
579 if (!error) 579 if (!error)
580 pr_debug("PM: Image successfully loaded\n"); 580 pr_debug("PM: Image successfully loaded\n");
@@ -609,7 +609,7 @@ int swsusp_check(void)
609 return -EINVAL; 609 return -EINVAL;
610 } 610 }
611 if (error) 611 if (error)
612 blkdev_put(resume_bdev); 612 blkdev_put(resume_bdev, FMODE_READ);
613 else 613 else
614 pr_debug("PM: Signature found, resuming\n"); 614 pr_debug("PM: Signature found, resuming\n");
615 } else { 615 } else {
@@ -626,14 +626,14 @@ int swsusp_check(void)
626 * swsusp_close - close swap device. 626 * swsusp_close - close swap device.
627 */ 627 */
628 628
629void swsusp_close(void) 629void swsusp_close(fmode_t mode)
630{ 630{
631 if (IS_ERR(resume_bdev)) { 631 if (IS_ERR(resume_bdev)) {
632 pr_debug("PM: Image device not initialised\n"); 632 pr_debug("PM: Image device not initialised\n");
633 return; 633 return;
634 } 634 }
635 635
636 blkdev_put(resume_bdev); 636 blkdev_put(resume_bdev, mode);
637} 637}
638 638
639static int swsusp_header_init(void) 639static int swsusp_header_init(void)
diff --git a/kernel/power/user.c b/kernel/power/user.c
index a6332a313262..005b93d839ba 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -212,13 +212,20 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
212 case SNAPSHOT_FREEZE: 212 case SNAPSHOT_FREEZE:
213 if (data->frozen) 213 if (data->frozen)
214 break; 214 break;
215
215 printk("Syncing filesystems ... "); 216 printk("Syncing filesystems ... ");
216 sys_sync(); 217 sys_sync();
217 printk("done.\n"); 218 printk("done.\n");
218 219
219 error = freeze_processes(); 220 error = usermodehelper_disable();
220 if (error) 221 if (error)
222 break;
223
224 error = freeze_processes();
225 if (error) {
221 thaw_processes(); 226 thaw_processes();
227 usermodehelper_enable();
228 }
222 if (!error) 229 if (!error)
223 data->frozen = 1; 230 data->frozen = 1;
224 break; 231 break;
@@ -227,6 +234,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
227 if (!data->frozen || data->ready) 234 if (!data->frozen || data->ready)
228 break; 235 break;
229 thaw_processes(); 236 thaw_processes();
237 usermodehelper_enable();
230 data->frozen = 0; 238 data->frozen = 0;
231 break; 239 break;
232 240