CHROMIUM: drm/anx7808: Add hardware probe.
[cascardo/linux.git] / kernel / printk.c
index b663c2c..363718d 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/rculist.h>
+#include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
 
@@ -112,9 +113,16 @@ static DEFINE_RAW_SPINLOCK(logbuf_lock);
  * The indices into log_buf are not constrained to log_buf_len - they
  * must be masked before subscripting
  */
-static unsigned log_start;     /* Index into log_buf: next char to be read by syslog() */
-static unsigned con_start;     /* Index into log_buf: next char to be sent to consoles */
-static unsigned log_end;       /* Index into log_buf: most-recently-written-char + 1 */
+
+/* Index into log_buf: next char to be read by syslog() */
+static unsigned __suspend_volatile_bss log_start;
+
+/* Index into log_buf: next char to be sent to consoles */
+static unsigned __suspend_volatile_bss con_start;
+
+/* Index into log_buf: most-recently-written-char + 1 */
+static unsigned __suspend_volatile_bss log_end;
+
 
 /*
  * If exclusive_console is non-NULL then only this console is to be printed to.
@@ -147,10 +155,12 @@ static int console_may_schedule;
 
 #ifdef CONFIG_PRINTK
 
-static char __log_buf[__LOG_BUF_LEN];
+static __suspend_volatile_bss char __log_buf[__LOG_BUF_LEN];
 static char *log_buf = __log_buf;
 static int log_buf_len = __LOG_BUF_LEN;
-static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
+
+/* Number of chars produced since last read+clear operation */
+static __suspend_volatile_bss unsigned logged_chars;
 static int saved_console_loglevel = -1;
 
 #ifdef CONFIG_KEXEC
@@ -820,7 +830,7 @@ static const char recursion_bug_msg [] =
                KERN_CRIT "BUG: recent printk recursion!\n";
 static int recursion_bug;
 static int new_text_line = 1;
-static char printk_buf[1024];
+static __suspend_volatile_bss char printk_buf[1024];
 
 int printk_delay_msec __read_mostly;
 
@@ -1253,6 +1263,14 @@ void wake_up_klogd(void)
                this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
 }
 
+static void console_unlock_work_fn(struct work_struct *work)
+{
+       if (console_trylock())
+               console_unlock();
+}
+
+static DECLARE_WORK(console_unlock_work, console_unlock_work_fn);
+
 /**
  * console_unlock - unlock the console system
  *
@@ -1271,7 +1289,7 @@ void console_unlock(void)
 {
        unsigned long flags;
        unsigned _con_start, _log_end;
-       unsigned wake_klogd = 0, retry = 0;
+       unsigned wake_klogd = 0;
 
        if (console_suspended) {
                up(&console_sem);
@@ -1280,12 +1298,9 @@ void console_unlock(void)
 
        console_may_schedule = 0;
 
-again:
-       for ( ; ; ) {
-               raw_spin_lock_irqsave(&logbuf_lock, flags);
-               wake_klogd |= log_start - log_end;
-               if (con_start == log_end)
-                       break;                  /* Nothing to print */
+       raw_spin_lock_irqsave(&logbuf_lock, flags);
+       wake_klogd |= log_start - log_end;
+       if (con_start != log_end) {
                _con_start = con_start;
                _log_end = log_end;
                con_start = log_end;            /* Flush */
@@ -1293,32 +1308,28 @@ again:
                stop_critical_timings();        /* don't trace print latency */
                call_console_drivers(_con_start, _log_end);
                start_critical_timings();
-               local_irq_restore(flags);
+       } else {
+               raw_spin_unlock(&logbuf_lock);
        }
+
        console_locked = 0;
 
        /* Release the exclusive_console once it is used */
        if (unlikely(exclusive_console))
                exclusive_console = NULL;
 
-       raw_spin_unlock(&logbuf_lock);
-
        up(&console_sem);
 
        /*
-        * Someone could have filled up the buffer again, so re-check if there's
-        * something to flush. In case we cannot trylock the console_sem again,
-        * there's a new owner and the console_unlock() from them will do the
-        * flush, no worries.
+        * Someone could have filled up the buffer again, so re-check and
+        * schedule work if there's something to flush.
         */
        raw_spin_lock(&logbuf_lock);
        if (con_start != log_end)
-               retry = 1;
+               if (!work_pending(&console_unlock_work))
+                       schedule_work(&console_unlock_work);
        raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 
-       if (retry && console_trylock())
-               goto again;
-
        if (wake_klogd)
                wake_up_klogd();
 }