skge: fix wake on lan
[safe/jmp/linux-2.6] / kernel / printk.c
index 6b89dd9..4b47e59 100644 (file)
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/interrupt.h>                   /* For in_interrupt() */
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/smp.h>
 #include <linux/security.h>
 #include <linux/bootmem.h>
 #include <linux/syscalls.h>
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 
@@ -52,10 +53,8 @@ int console_printk[4] = {
        DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
 };
 
-EXPORT_SYMBOL(console_printk);
-
 /*
- * Low lever drivers may need that to know if they can schedule in
+ * Low level drivers may need that to know if they can schedule in
  * their unblank() callback or not. So let's export it.
  */
 int oops_in_progress;
@@ -334,13 +333,25 @@ static void __call_console_drivers(unsigned long start, unsigned long end)
        }
 }
 
+static int __read_mostly ignore_loglevel;
+
+static int __init ignore_loglevel_setup(char *str)
+{
+       ignore_loglevel = 1;
+       printk(KERN_INFO "debug: ignoring loglevel setting.\n");
+
+       return 1;
+}
+
+__setup("ignore_loglevel", ignore_loglevel_setup);
+
 /*
  * Write out chars from start to end - 1 inclusive
  */
 static void _call_console_drivers(unsigned long start,
                                unsigned long end, int msg_log_level)
 {
-       if (msg_log_level < console_loglevel &&
+       if ((msg_log_level < console_loglevel || ignore_loglevel) &&
                        console_drivers && start != end) {
                if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
                        /* wrapped write */
@@ -439,6 +450,7 @@ static int printk_time = 1;
 #else
 static int printk_time = 0;
 #endif
+module_param(printk_time, int, S_IRUGO | S_IWUSR);
 
 static int __init printk_time_setup(char *str)
 {
@@ -471,7 +483,7 @@ static int have_callable_console(void)
  * printk - print a kernel message
  * @fmt: format string
  *
- * This is printk.  It can be called from any context.  We want it to work.
+ * This is printk().  It can be called from any context.  We want it to work.
  *
  * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
  * call the console drivers.  If we fail to get the semaphore we place the output
@@ -517,7 +529,9 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                zap_locks();
 
        /* This stops the holder of console_sem just where we want him */
-       spin_lock_irqsave(&logbuf_lock, flags);
+       raw_local_irq_save(flags);
+       lockdep_off();
+       spin_lock(&logbuf_lock);
        printk_cpu = smp_processor_id();
 
        /* Emit the output into the temporary buffer */
@@ -587,7 +601,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 */
                console_locked = 1;
                printk_cpu = UINT_MAX;
-               spin_unlock_irqrestore(&logbuf_lock, flags);
+               spin_unlock(&logbuf_lock);
 
                /*
                 * Console drivers may assume that per-cpu resources have
@@ -603,6 +617,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                        console_locked = 0;
                        up(&console_sem);
                }
+               lockdep_on();
+               raw_local_irq_restore(flags);
        } else {
                /*
                 * Someone else owns the drivers.  We drop the spinlock, which
@@ -610,7 +626,9 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 * console drivers with the output which we just produced.
                 */
                printk_cpu = UINT_MAX;
-               spin_unlock_irqrestore(&logbuf_lock, flags);
+               spin_unlock(&logbuf_lock);
+               lockdep_on();
+               raw_local_irq_restore(flags);
        }
 
        preempt_enable();
@@ -623,12 +641,7 @@ EXPORT_SYMBOL(vprintk);
 
 asmlinkage long sys_syslog(int type, char __user *buf, int len)
 {
-       return 0;
-}
-
-int do_syslog(int type, char __user *buf, int len)
-{
-       return 0;
+       return -ENOSYS;
 }
 
 static void call_console_drivers(unsigned long start, unsigned long end)
@@ -714,6 +727,7 @@ int __init add_preferred_console(char *name, int idx, char *options)
        return 0;
 }
 
+#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
 /**
  * suspend_console - suspend the console subsystem
  *
@@ -721,6 +735,7 @@ int __init add_preferred_console(char *name, int idx, char *options)
  */
 void suspend_console(void)
 {
+       printk("Suspending console(s)\n");
        acquire_console_sem();
        console_suspended = 1;
 }
@@ -730,6 +745,7 @@ void resume_console(void)
        console_suspended = 0;
        release_console_sem();
 }
+#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
 
 /**
  * acquire_console_sem - lock the console system for exclusive use.
@@ -766,7 +782,12 @@ int is_console_locked(void)
 {
        return console_locked;
 }
-EXPORT_SYMBOL(is_console_locked);
+
+void wake_up_klogd(void)
+{
+       if (!oops_in_progress && waitqueue_active(&log_wait))
+               wake_up_interruptible(&log_wait);
+}
 
 /**
  * release_console_sem - unlock the console system
@@ -792,6 +813,9 @@ void release_console_sem(void)
                up(&secondary_console_sem);
                return;
        }
+
+       console_may_schedule = 0;
+
        for ( ; ; ) {
                spin_lock_irqsave(&logbuf_lock, flags);
                wake_klogd |= log_start - log_end;
@@ -805,11 +829,10 @@ void release_console_sem(void)
                local_irq_restore(flags);
        }
        console_locked = 0;
-       console_may_schedule = 0;
        up(&console_sem);
        spin_unlock_irqrestore(&logbuf_lock, flags);
-       if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait))
-               wake_up_interruptible(&log_wait);
+       if (wake_klogd)
+               wake_up_klogd();
 }
 EXPORT_SYMBOL(release_console_sem);
 
@@ -1089,3 +1112,23 @@ int printk_ratelimit(void)
                                printk_ratelimit_burst);
 }
 EXPORT_SYMBOL(printk_ratelimit);
+
+/**
+ * printk_timed_ratelimit - caller-controlled printk ratelimiting
+ * @caller_jiffies: pointer to caller's state
+ * @interval_msecs: minimum interval between prints
+ *
+ * printk_timed_ratelimit() returns true if more than @interval_msecs
+ * milliseconds have elapsed since the last time printk_timed_ratelimit()
+ * returned true.
+ */
+bool printk_timed_ratelimit(unsigned long *caller_jiffies,
+                       unsigned int interval_msecs)
+{
+       if (*caller_jiffies == 0 || time_after(jiffies, *caller_jiffies)) {
+               *caller_jiffies = jiffies + msecs_to_jiffies(interval_msecs);
+               return true;
+       }
+       return false;
+}
+EXPORT_SYMBOL(printk_timed_ratelimit);