]> err.no Git - linux-2.6/commitdiff
Add support for suspending and resuming the whole console subsystem
authorLinus Torvalds <torvalds@g5.osdl.org>
Tue, 20 Jun 2006 01:16:01 +0000 (18:16 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Tue, 20 Jun 2006 01:16:01 +0000 (18:16 -0700)
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>
include/linux/console.h
kernel/power/main.c
kernel/printk.c

index 721371382ae5ff1a55eace3ec867fc355b22c24a..08734e660d4182c11c9bc55a6a7e2632f1d3e917 100644 (file)
@@ -117,6 +117,10 @@ extern void console_stop(struct console *);
 extern void console_start(struct console *);
 extern int is_console_locked(void);
 
+/* Suspend and resume console messages over PM events */
+extern void suspend_console(void);
+extern void resume_console(void);
+
 /* Some debug stub to catch some of the obvious races in the VT code */
 #if 1
 #define WARN_CONSOLE_UNLOCKED()        WARN_ON(!is_console_locked() && !oops_in_progress)
index a6d9ef46009ebdcb37f5b8fc4287d81f02dd089a..0a907f0dc56b3bc0f67e189ded38f64e8ad94ebb 100644 (file)
@@ -86,6 +86,7 @@ static int suspend_prepare(suspend_state_t state)
                        goto Thaw;
        }
 
+       suspend_console();
        if ((error = device_suspend(PMSG_SUSPEND))) {
                printk(KERN_ERR "Some devices failed to suspend\n");
                goto Finish;
@@ -133,6 +134,7 @@ int suspend_enter(suspend_state_t state)
 static void suspend_finish(suspend_state_t state)
 {
        device_resume();
+       resume_console();
        thaw_processes();
        enable_nonboot_cpus();
        if (pm_ops && pm_ops->finish)
index c056f3324432c31152063de1ca820fbcd2f3d92a..19a95561929478ffc99ac1552cf3ab645ec16bc1 100644 (file)
@@ -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
@@ -76,7 +77,7 @@ struct console *console_drivers;
  * path in the console code where we end up in places I want
  * locked without the console sempahore held
  */
-static int console_locked;
+static int console_locked, console_suspended;
 
 /*
  * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
@@ -697,6 +698,23 @@ int __init add_preferred_console(char *name, int idx, char *options)
        return 0;
 }
 
+/**
+ * suspend_console - suspend the console subsystem
+ *
+ * This disables printk() while we go into suspend states
+ */
+void suspend_console(void)
+{
+       acquire_console_sem();
+       console_suspended = 1;
+}
+
+void resume_console(void)
+{
+       console_suspended = 0;
+       release_console_sem();
+}
+
 /**
  * acquire_console_sem - lock the console system for exclusive use.
  *
@@ -708,6 +726,10 @@ int __init add_preferred_console(char *name, int idx, char *options)
 void acquire_console_sem(void)
 {
        BUG_ON(in_interrupt());
+       if (console_suspended) {
+               down(&secondary_console_sem);
+               return;
+       }
        down(&console_sem);
        console_locked = 1;
        console_may_schedule = 1;
@@ -750,6 +772,10 @@ 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;