diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:16:01 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-19 21:16:01 -0400 |
| commit | 557240b48e2dc4f6fa878afc3fc767ad745ca7ed (patch) | |
| tree | 354e9de17c28b438db675f6a2b779415f1634c45 | |
| parent | 5603509137940f4cbc577281cee62110d4097b1b (diff) | |
Add support for suspending and resuming the whole console subsystem
Trying to suspend/resume with console messages flying all around is
doomed to failure, when the devices that the messages are trying to
go to are being shut down.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | include/linux/console.h | 4 | ||||
| -rw-r--r-- | kernel/power/main.c | 2 | ||||
| -rw-r--r-- | kernel/printk.c | 28 |
3 files changed, 33 insertions, 1 deletions
diff --git a/include/linux/console.h b/include/linux/console.h index 721371382ae5..08734e660d41 100644 --- a/include/linux/console.h +++ b/include/linux/console.h | |||
| @@ -117,6 +117,10 @@ extern void console_stop(struct console *); | |||
| 117 | extern void console_start(struct console *); | 117 | extern void console_start(struct console *); |
| 118 | extern int is_console_locked(void); | 118 | extern int is_console_locked(void); |
| 119 | 119 | ||
| 120 | /* Suspend and resume console messages over PM events */ | ||
| 121 | extern void suspend_console(void); | ||
| 122 | extern void resume_console(void); | ||
| 123 | |||
| 120 | /* Some debug stub to catch some of the obvious races in the VT code */ | 124 | /* Some debug stub to catch some of the obvious races in the VT code */ |
| 121 | #if 1 | 125 | #if 1 |
| 122 | #define WARN_CONSOLE_UNLOCKED() WARN_ON(!is_console_locked() && !oops_in_progress) | 126 | #define WARN_CONSOLE_UNLOCKED() WARN_ON(!is_console_locked() && !oops_in_progress) |
diff --git a/kernel/power/main.c b/kernel/power/main.c index a6d9ef46009e..0a907f0dc56b 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
| @@ -86,6 +86,7 @@ static int suspend_prepare(suspend_state_t state) | |||
| 86 | goto Thaw; | 86 | goto Thaw; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | suspend_console(); | ||
| 89 | if ((error = device_suspend(PMSG_SUSPEND))) { | 90 | if ((error = device_suspend(PMSG_SUSPEND))) { |
| 90 | printk(KERN_ERR "Some devices failed to suspend\n"); | 91 | printk(KERN_ERR "Some devices failed to suspend\n"); |
| 91 | goto Finish; | 92 | goto Finish; |
| @@ -133,6 +134,7 @@ int suspend_enter(suspend_state_t state) | |||
| 133 | static void suspend_finish(suspend_state_t state) | 134 | static void suspend_finish(suspend_state_t state) |
| 134 | { | 135 | { |
| 135 | device_resume(); | 136 | device_resume(); |
| 137 | resume_console(); | ||
| 136 | thaw_processes(); | 138 | thaw_processes(); |
| 137 | enable_nonboot_cpus(); | 139 | enable_nonboot_cpus(); |
| 138 | if (pm_ops && pm_ops->finish) | 140 | if (pm_ops && pm_ops->finish) |
diff --git a/kernel/printk.c b/kernel/printk.c index c056f3324432..19a955619294 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -67,6 +67,7 @@ EXPORT_SYMBOL(oops_in_progress); | |||
| 67 | * driver system. | 67 | * driver system. |
| 68 | */ | 68 | */ |
| 69 | static DECLARE_MUTEX(console_sem); | 69 | static DECLARE_MUTEX(console_sem); |
| 70 | static DECLARE_MUTEX(secondary_console_sem); | ||
| 70 | struct console *console_drivers; | 71 | struct console *console_drivers; |
| 71 | /* | 72 | /* |
| 72 | * This is used for debugging the mess that is the VT code by | 73 | * This is used for debugging the mess that is the VT code by |
| @@ -76,7 +77,7 @@ struct console *console_drivers; | |||
| 76 | * path in the console code where we end up in places I want | 77 | * path in the console code where we end up in places I want |
| 77 | * locked without the console sempahore held | 78 | * locked without the console sempahore held |
| 78 | */ | 79 | */ |
| 79 | static int console_locked; | 80 | static int console_locked, console_suspended; |
| 80 | 81 | ||
| 81 | /* | 82 | /* |
| 82 | * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars | 83 | * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars |
| @@ -698,6 +699,23 @@ int __init add_preferred_console(char *name, int idx, char *options) | |||
| 698 | } | 699 | } |
| 699 | 700 | ||
| 700 | /** | 701 | /** |
| 702 | * suspend_console - suspend the console subsystem | ||
| 703 | * | ||
| 704 | * This disables printk() while we go into suspend states | ||
| 705 | */ | ||
| 706 | void suspend_console(void) | ||
| 707 | { | ||
| 708 | acquire_console_sem(); | ||
| 709 | console_suspended = 1; | ||
| 710 | } | ||
| 711 | |||
| 712 | void resume_console(void) | ||
| 713 | { | ||
| 714 | console_suspended = 0; | ||
| 715 | release_console_sem(); | ||
| 716 | } | ||
| 717 | |||
| 718 | /** | ||
| 701 | * acquire_console_sem - lock the console system for exclusive use. | 719 | * acquire_console_sem - lock the console system for exclusive use. |
| 702 | * | 720 | * |
| 703 | * Acquires a semaphore which guarantees that the caller has | 721 | * Acquires a semaphore which guarantees that the caller has |
| @@ -708,6 +726,10 @@ int __init add_preferred_console(char *name, int idx, char *options) | |||
| 708 | void acquire_console_sem(void) | 726 | void acquire_console_sem(void) |
| 709 | { | 727 | { |
| 710 | BUG_ON(in_interrupt()); | 728 | BUG_ON(in_interrupt()); |
| 729 | if (console_suspended) { | ||
| 730 | down(&secondary_console_sem); | ||
| 731 | return; | ||
| 732 | } | ||
| 711 | down(&console_sem); | 733 | down(&console_sem); |
| 712 | console_locked = 1; | 734 | console_locked = 1; |
| 713 | console_may_schedule = 1; | 735 | console_may_schedule = 1; |
| @@ -750,6 +772,10 @@ void release_console_sem(void) | |||
| 750 | unsigned long _con_start, _log_end; | 772 | unsigned long _con_start, _log_end; |
| 751 | unsigned long wake_klogd = 0; | 773 | unsigned long wake_klogd = 0; |
| 752 | 774 | ||
| 775 | if (console_suspended) { | ||
| 776 | up(&secondary_console_sem); | ||
| 777 | return; | ||
| 778 | } | ||
| 753 | for ( ; ; ) { | 779 | for ( ; ; ) { |
| 754 | spin_lock_irqsave(&logbuf_lock, flags); | 780 | spin_lock_irqsave(&logbuf_lock, flags); |
| 755 | wake_klogd |= log_start - log_end; | 781 | wake_klogd |= log_start - log_end; |
