On Thu, 15 Jun 2006, Pavel Machek wrote: > > That said... Linus, can I get latest version of that patch? I'll fix > it up to work with s2disk... I don't think I've done anything but fix the SYSTEM_RUNNING thing you noticed and fixed a header problem that DaveJ noticed with CONFIG_VT_CONSOLE not being enabled. But here it is again. (I'm told that the linux-pm list corrupts things with MIME, but at least Pavel should get a non-corrupt version thanks to being directly on the participants list) Btw, the new console prepare/restore code is so simple that I'm not sure it's worthwhile even having a special file for it. It would actually clean things up to move these things into kernel/printk.c (and make the "console_suspended" flag static to that file). Linus ---- Author: Linus Torvalds <torvalds at macmini.osdl.org> Date: Thu Jun 8 15:29:09 2006 -0700 Fix console handling during suspend/resume The old code was terminally broken, and would do extremely bad things if you used netconsole, for example. Like sending out packets when the device had already been suspended etc. The new version may not be perfect either, but it seems fundamentally like a better design. Signed-off-by: Linus Torvalds <torvalds at osdl.org> diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 37c1c76..c03b17f 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -43,13 +43,9 @@ #ifdef CONFIG_PM /* kernel/power/swsusp.c */ extern int software_suspend(void); -#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) extern int pm_prepare_console(void); extern void pm_restore_console(void); -#else -static inline int pm_prepare_console(void) { return 0; } -static inline void pm_restore_console(void) {} -#endif /* defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) */ + #else static inline int software_suspend(void) { diff --git a/kernel/power/console.c b/kernel/power/console.c index 623786d..6e039ca 100644 --- a/kernel/power/console.c +++ b/kernel/power/console.c @@ -9,42 +9,20 @@ #include <linux/kbd_kern.h> #include <linux/console.h> #include "power.h" -#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) -#define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) - -static int orig_fgconsole, orig_kmsg; +extern int console_suspended; int pm_prepare_console(void) { acquire_console_sem(); - - orig_fgconsole = fg_console; - - if (vc_allocate(SUSPEND_CONSOLE)) { - /* we can't have a free VC for now. Too bad, - * we don't want to mess the screen for now. */ - release_console_sem(); - return 1; - } - - set_console(SUSPEND_CONSOLE); - release_console_sem(); - - if (vt_waitactive(SUSPEND_CONSOLE)) { - pr_debug("Suspend: Can't switch VCs."); - return 1; - } - orig_kmsg = kmsg_redirect; - kmsg_redirect = SUSPEND_CONSOLE; + console_suspended = 1; + system_state = SYSTEM_BOOTING; return 0; } void pm_restore_console(void) { - acquire_console_sem(); - set_console(orig_fgconsole); + console_suspended = 0; + system_state = SYSTEM_RUNNING; release_console_sem(); - kmsg_redirect = orig_kmsg; return; } -#endif diff --git a/kernel/printk.c b/kernel/printk.c index c056f33..8adb9ed 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -67,6 +67,7 @@ EXPORT_SYMBOL(oops_in_progress); * driver system. */ static DECLARE_MUTEX(console_sem); +static DECLARE_MUTEX(secondary_console_sem); struct console *console_drivers; /* * This is used for debugging the mess that is the VT code by @@ -77,6 +78,7 @@ struct console *console_drivers; * locked without the console sempahore held */ static int console_locked; +int console_suspended; /* * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars @@ -707,6 +709,11 @@ int __init add_preferred_console(char *n */ void acquire_console_sem(void) { + if (console_suspended) { + down(&secondary_console_sem); + return; + } + BUG_ON(in_interrupt()); down(&console_sem); console_locked = 1; @@ -750,6 +757,11 @@ void release_console_sem(void) unsigned long _con_start, _log_end; unsigned long wake_klogd = 0; + if (console_suspended) { + up(&secondary_console_sem); + return; + } + for ( ; ; ) { spin_lock_irqsave(&logbuf_lock, flags); wake_klogd |= log_start - log_end;