diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/power/Kconfig | 2 | ||||
-rw-r--r-- | kernel/power/disk.c | 6 | ||||
-rw-r--r-- | kernel/power/power.h | 2 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 12 | ||||
-rw-r--r-- | kernel/printk.c | 7 | ||||
-rw-r--r-- | kernel/signal.c | 31 | ||||
-rw-r--r-- | kernel/sys.c | 52 |
7 files changed, 78 insertions, 34 deletions
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig index 396c7873e804..46a5e5acff97 100644 --- a/kernel/power/Kconfig +++ b/kernel/power/Kconfig | |||
@@ -29,7 +29,7 @@ config PM_DEBUG | |||
29 | 29 | ||
30 | config SOFTWARE_SUSPEND | 30 | config SOFTWARE_SUSPEND |
31 | bool "Software Suspend" | 31 | bool "Software Suspend" |
32 | depends on PM && SWAP && (X86 || ((FVR || PPC32) && !SMP)) | 32 | depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FVR || PPC32) && !SMP) |
33 | ---help--- | 33 | ---help--- |
34 | Enable the possibility of suspending the machine. | 34 | Enable the possibility of suspending the machine. |
35 | It doesn't need APM. | 35 | It doesn't need APM. |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 2d8bf054d036..761956e813f5 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -17,12 +17,12 @@ | |||
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/pm.h> | ||
20 | 21 | ||
21 | #include "power.h" | 22 | #include "power.h" |
22 | 23 | ||
23 | 24 | ||
24 | extern suspend_disk_method_t pm_disk_mode; | 25 | extern suspend_disk_method_t pm_disk_mode; |
25 | extern struct pm_ops * pm_ops; | ||
26 | 26 | ||
27 | extern int swsusp_suspend(void); | 27 | extern int swsusp_suspend(void); |
28 | extern int swsusp_write(void); | 28 | extern int swsusp_write(void); |
@@ -49,13 +49,11 @@ dev_t swsusp_resume_device; | |||
49 | 49 | ||
50 | static void power_down(suspend_disk_method_t mode) | 50 | static void power_down(suspend_disk_method_t mode) |
51 | { | 51 | { |
52 | unsigned long flags; | ||
53 | int error = 0; | 52 | int error = 0; |
54 | 53 | ||
55 | local_irq_save(flags); | ||
56 | switch(mode) { | 54 | switch(mode) { |
57 | case PM_DISK_PLATFORM: | 55 | case PM_DISK_PLATFORM: |
58 | device_shutdown(); | 56 | kernel_power_off_prepare(); |
59 | error = pm_ops->enter(PM_SUSPEND_DISK); | 57 | error = pm_ops->enter(PM_SUSPEND_DISK); |
60 | break; | 58 | break; |
61 | case PM_DISK_SHUTDOWN: | 59 | case PM_DISK_SHUTDOWN: |
diff --git a/kernel/power/power.h b/kernel/power/power.h index cd6a3493cc0d..9c9167d910dd 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #include <linux/suspend.h> | 1 | #include <linux/suspend.h> |
2 | #include <linux/utsname.h> | 2 | #include <linux/utsname.h> |
3 | 3 | ||
4 | /* With SUSPEND_CONSOLE defined, it suspend looks *really* cool, but | 4 | /* With SUSPEND_CONSOLE defined suspend looks *really* cool, but |
5 | we probably do not take enough locks for switching consoles, etc, | 5 | we probably do not take enough locks for switching consoles, etc, |
6 | so bad things might happen. | 6 | so bad things might happen. |
7 | */ | 7 | */ |
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index d967e875ee82..1cc9ff25e479 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
@@ -363,7 +363,7 @@ static void lock_swapdevices(void) | |||
363 | } | 363 | } |
364 | 364 | ||
365 | /** | 365 | /** |
366 | * write_swap_page - Write one page to a fresh swap location. | 366 | * write_page - Write one page to a fresh swap location. |
367 | * @addr: Address we're writing. | 367 | * @addr: Address we're writing. |
368 | * @loc: Place to store the entry we used. | 368 | * @loc: Place to store the entry we used. |
369 | * | 369 | * |
@@ -863,6 +863,9 @@ static int alloc_image_pages(void) | |||
863 | return 0; | 863 | return 0; |
864 | } | 864 | } |
865 | 865 | ||
866 | /* Free pages we allocated for suspend. Suspend pages are alocated | ||
867 | * before atomic copy, so we need to free them after resume. | ||
868 | */ | ||
866 | void swsusp_free(void) | 869 | void swsusp_free(void) |
867 | { | 870 | { |
868 | BUG_ON(PageNosave(virt_to_page(pagedir_save))); | 871 | BUG_ON(PageNosave(virt_to_page(pagedir_save))); |
@@ -918,6 +921,7 @@ static int swsusp_alloc(void) | |||
918 | 921 | ||
919 | pagedir_nosave = NULL; | 922 | pagedir_nosave = NULL; |
920 | nr_copy_pages = calc_nr(nr_copy_pages); | 923 | nr_copy_pages = calc_nr(nr_copy_pages); |
924 | nr_copy_pages_check = nr_copy_pages; | ||
921 | 925 | ||
922 | pr_debug("suspend: (pages needed: %d + %d free: %d)\n", | 926 | pr_debug("suspend: (pages needed: %d + %d free: %d)\n", |
923 | nr_copy_pages, PAGES_FOR_IO, nr_free_pages()); | 927 | nr_copy_pages, PAGES_FOR_IO, nr_free_pages()); |
@@ -940,7 +944,6 @@ static int swsusp_alloc(void) | |||
940 | return error; | 944 | return error; |
941 | } | 945 | } |
942 | 946 | ||
943 | nr_copy_pages_check = nr_copy_pages; | ||
944 | return 0; | 947 | return 0; |
945 | } | 948 | } |
946 | 949 | ||
@@ -1213,8 +1216,9 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) | |||
1213 | free_pagedir(pblist); | 1216 | free_pagedir(pblist); |
1214 | free_eaten_memory(); | 1217 | free_eaten_memory(); |
1215 | pblist = NULL; | 1218 | pblist = NULL; |
1216 | } | 1219 | /* Is this even worth handling? It should never ever happen, and we |
1217 | else | 1220 | have just lost user's state, anyway... */ |
1221 | } else | ||
1218 | printk("swsusp: Relocated %d pages\n", rel); | 1222 | printk("swsusp: Relocated %d pages\n", rel); |
1219 | 1223 | ||
1220 | return pblist; | 1224 | return pblist; |
diff --git a/kernel/printk.c b/kernel/printk.c index a967605bc2e3..4b8f0f9230a4 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -488,6 +488,11 @@ static int __init printk_time_setup(char *str) | |||
488 | 488 | ||
489 | __setup("time", printk_time_setup); | 489 | __setup("time", printk_time_setup); |
490 | 490 | ||
491 | __attribute__((weak)) unsigned long long printk_clock(void) | ||
492 | { | ||
493 | return sched_clock(); | ||
494 | } | ||
495 | |||
491 | /* | 496 | /* |
492 | * This is printk. It can be called from any context. We want it to work. | 497 | * This is printk. It can be called from any context. We want it to work. |
493 | * | 498 | * |
@@ -565,7 +570,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
565 | loglev_char = default_message_loglevel | 570 | loglev_char = default_message_loglevel |
566 | + '0'; | 571 | + '0'; |
567 | } | 572 | } |
568 | t = sched_clock(); | 573 | t = printk_clock(); |
569 | nanosec_rem = do_div(t, 1000000000); | 574 | nanosec_rem = do_div(t, 1000000000); |
570 | tlen = sprintf(tbuf, | 575 | tlen = sprintf(tbuf, |
571 | "<%c>[%5lu.%06lu] ", | 576 | "<%c>[%5lu.%06lu] ", |
diff --git a/kernel/signal.c b/kernel/signal.c index b92c3c9f8b9a..5a274705ba19 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -936,34 +936,31 @@ force_sig_specific(int sig, struct task_struct *t) | |||
936 | * as soon as they're available, so putting the signal on the shared queue | 936 | * as soon as they're available, so putting the signal on the shared queue |
937 | * will be equivalent to sending it to one such thread. | 937 | * will be equivalent to sending it to one such thread. |
938 | */ | 938 | */ |
939 | #define wants_signal(sig, p, mask) \ | 939 | static inline int wants_signal(int sig, struct task_struct *p) |
940 | (!sigismember(&(p)->blocked, sig) \ | 940 | { |
941 | && !((p)->state & mask) \ | 941 | if (sigismember(&p->blocked, sig)) |
942 | && !((p)->flags & PF_EXITING) \ | 942 | return 0; |
943 | && (task_curr(p) || !signal_pending(p))) | 943 | if (p->flags & PF_EXITING) |
944 | 944 | return 0; | |
945 | if (sig == SIGKILL) | ||
946 | return 1; | ||
947 | if (p->state & (TASK_STOPPED | TASK_TRACED)) | ||
948 | return 0; | ||
949 | return task_curr(p) || !signal_pending(p); | ||
950 | } | ||
945 | 951 | ||
946 | static void | 952 | static void |
947 | __group_complete_signal(int sig, struct task_struct *p) | 953 | __group_complete_signal(int sig, struct task_struct *p) |
948 | { | 954 | { |
949 | unsigned int mask; | ||
950 | struct task_struct *t; | 955 | struct task_struct *t; |
951 | 956 | ||
952 | /* | 957 | /* |
953 | * Don't bother traced and stopped tasks (but | ||
954 | * SIGKILL will punch through that). | ||
955 | */ | ||
956 | mask = TASK_STOPPED | TASK_TRACED; | ||
957 | if (sig == SIGKILL) | ||
958 | mask = 0; | ||
959 | |||
960 | /* | ||
961 | * Now find a thread we can wake up to take the signal off the queue. | 958 | * Now find a thread we can wake up to take the signal off the queue. |
962 | * | 959 | * |
963 | * If the main thread wants the signal, it gets first crack. | 960 | * If the main thread wants the signal, it gets first crack. |
964 | * Probably the least surprising to the average bear. | 961 | * Probably the least surprising to the average bear. |
965 | */ | 962 | */ |
966 | if (wants_signal(sig, p, mask)) | 963 | if (wants_signal(sig, p)) |
967 | t = p; | 964 | t = p; |
968 | else if (thread_group_empty(p)) | 965 | else if (thread_group_empty(p)) |
969 | /* | 966 | /* |
@@ -981,7 +978,7 @@ __group_complete_signal(int sig, struct task_struct *p) | |||
981 | t = p->signal->curr_target = p; | 978 | t = p->signal->curr_target = p; |
982 | BUG_ON(t->tgid != p->tgid); | 979 | BUG_ON(t->tgid != p->tgid); |
983 | 980 | ||
984 | while (!wants_signal(sig, t, mask)) { | 981 | while (!wants_signal(sig, t)) { |
985 | t = next_thread(t); | 982 | t = next_thread(t); |
986 | if (t == p->signal->curr_target) | 983 | if (t == p->signal->curr_target) |
987 | /* | 984 | /* |
diff --git a/kernel/sys.c b/kernel/sys.c index f723522e6986..2fa1ed18123c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -361,17 +361,35 @@ out_unlock: | |||
361 | return retval; | 361 | return retval; |
362 | } | 362 | } |
363 | 363 | ||
364 | /** | ||
365 | * emergency_restart - reboot the system | ||
366 | * | ||
367 | * Without shutting down any hardware or taking any locks | ||
368 | * reboot the system. This is called when we know we are in | ||
369 | * trouble so this is our best effort to reboot. This is | ||
370 | * safe to call in interrupt context. | ||
371 | */ | ||
364 | void emergency_restart(void) | 372 | void emergency_restart(void) |
365 | { | 373 | { |
366 | machine_emergency_restart(); | 374 | machine_emergency_restart(); |
367 | } | 375 | } |
368 | EXPORT_SYMBOL_GPL(emergency_restart); | 376 | EXPORT_SYMBOL_GPL(emergency_restart); |
369 | 377 | ||
370 | void kernel_restart(char *cmd) | 378 | /** |
379 | * kernel_restart - reboot the system | ||
380 | * | ||
381 | * Shutdown everything and perform a clean reboot. | ||
382 | * This is not safe to call in interrupt context. | ||
383 | */ | ||
384 | void kernel_restart_prepare(char *cmd) | ||
371 | { | 385 | { |
372 | notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); | 386 | notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); |
373 | system_state = SYSTEM_RESTART; | 387 | system_state = SYSTEM_RESTART; |
374 | device_shutdown(); | 388 | device_shutdown(); |
389 | } | ||
390 | void kernel_restart(char *cmd) | ||
391 | { | ||
392 | kernel_restart_prepare(cmd); | ||
375 | if (!cmd) { | 393 | if (!cmd) { |
376 | printk(KERN_EMERG "Restarting system.\n"); | 394 | printk(KERN_EMERG "Restarting system.\n"); |
377 | } else { | 395 | } else { |
@@ -382,6 +400,12 @@ void kernel_restart(char *cmd) | |||
382 | } | 400 | } |
383 | EXPORT_SYMBOL_GPL(kernel_restart); | 401 | EXPORT_SYMBOL_GPL(kernel_restart); |
384 | 402 | ||
403 | /** | ||
404 | * kernel_kexec - reboot the system | ||
405 | * | ||
406 | * Move into place and start executing a preloaded standalone | ||
407 | * executable. If nothing was preloaded return an error. | ||
408 | */ | ||
385 | void kernel_kexec(void) | 409 | void kernel_kexec(void) |
386 | { | 410 | { |
387 | #ifdef CONFIG_KEXEC | 411 | #ifdef CONFIG_KEXEC |
@@ -390,9 +414,7 @@ void kernel_kexec(void) | |||
390 | if (!image) { | 414 | if (!image) { |
391 | return; | 415 | return; |
392 | } | 416 | } |
393 | notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL); | 417 | kernel_restart_prepare(NULL); |
394 | system_state = SYSTEM_RESTART; | ||
395 | device_shutdown(); | ||
396 | printk(KERN_EMERG "Starting new kernel\n"); | 418 | printk(KERN_EMERG "Starting new kernel\n"); |
397 | machine_shutdown(); | 419 | machine_shutdown(); |
398 | machine_kexec(image); | 420 | machine_kexec(image); |
@@ -400,21 +422,39 @@ void kernel_kexec(void) | |||
400 | } | 422 | } |
401 | EXPORT_SYMBOL_GPL(kernel_kexec); | 423 | EXPORT_SYMBOL_GPL(kernel_kexec); |
402 | 424 | ||
403 | void kernel_halt(void) | 425 | /** |
426 | * kernel_halt - halt the system | ||
427 | * | ||
428 | * Shutdown everything and perform a clean system halt. | ||
429 | */ | ||
430 | void kernel_halt_prepare(void) | ||
404 | { | 431 | { |
405 | notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); | 432 | notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); |
406 | system_state = SYSTEM_HALT; | 433 | system_state = SYSTEM_HALT; |
407 | device_shutdown(); | 434 | device_shutdown(); |
435 | } | ||
436 | void kernel_halt(void) | ||
437 | { | ||
438 | kernel_halt_prepare(); | ||
408 | printk(KERN_EMERG "System halted.\n"); | 439 | printk(KERN_EMERG "System halted.\n"); |
409 | machine_halt(); | 440 | machine_halt(); |
410 | } | 441 | } |
411 | EXPORT_SYMBOL_GPL(kernel_halt); | 442 | EXPORT_SYMBOL_GPL(kernel_halt); |
412 | 443 | ||
413 | void kernel_power_off(void) | 444 | /** |
445 | * kernel_power_off - power_off the system | ||
446 | * | ||
447 | * Shutdown everything and perform a clean system power_off. | ||
448 | */ | ||
449 | void kernel_power_off_prepare(void) | ||
414 | { | 450 | { |
415 | notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); | 451 | notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); |
416 | system_state = SYSTEM_POWER_OFF; | 452 | system_state = SYSTEM_POWER_OFF; |
417 | device_shutdown(); | 453 | device_shutdown(); |
454 | } | ||
455 | void kernel_power_off(void) | ||
456 | { | ||
457 | kernel_power_off_prepare(); | ||
418 | printk(KERN_EMERG "Power down.\n"); | 458 | printk(KERN_EMERG "Power down.\n"); |
419 | machine_power_off(); | 459 | machine_power_off(); |
420 | } | 460 | } |