]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - kernel/printk.c
powerpc: make mem= work on iSeries again
[karo-tx-linux.git] / kernel / printk.c
index 5092397fac29926bfab6da75fc273882b14e905d..3cb9708209bcb94a9d30a4c807f760ae485bf0c4 100644 (file)
@@ -10,7 +10,7 @@
  * elsewhere, in preparation for a serial line console (someday).
  * Ted Ts'o, 2/11/93.
  * Modified for sysctl support, 1/8/97, Chris Horn.
- * Fixed SMP synchronization, 08/08/99, Manfred Spraul 
+ * Fixed SMP synchronization, 08/08/99, Manfred Spraul
  *     manfreds@colorfullife.com
  * Rewrote bits to get rid of console_lock
  *     01Mar01 Andrew Morton <andrewm@uow.edu.au>
@@ -148,7 +148,7 @@ static int __init console_setup(char *str)
        if (!strcmp(str, "ttyb"))
                strcpy(name, "ttyS1");
 #endif
-       for(s = name; *s; s++)
+       for (s = name; *s; s++)
                if ((*s >= '0' && *s <= '9') || *s == ',')
                        break;
        idx = simple_strtoul(s, NULL, 10);
@@ -169,11 +169,11 @@ static int __init log_buf_len_setup(char *str)
                size = roundup_pow_of_two(size);
        if (size > log_buf_len) {
                unsigned long start, dest_idx, offset;
-               char * new_log_buf;
+               char *new_log_buf;
 
                new_log_buf = alloc_bootmem(size);
                if (!new_log_buf) {
-                       printk("log_buf_len: allocation failed\n");
+                       printk(KERN_WARNING "log_buf_len: allocation failed\n");
                        goto out;
                }
 
@@ -193,10 +193,9 @@ static int __init log_buf_len_setup(char *str)
                log_end -= offset;
                spin_unlock_irqrestore(&logbuf_lock, flags);
 
-               printk("log_buf_len: %d\n", log_buf_len);
+               printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len);
        }
 out:
-
        return 1;
 }
 
@@ -217,7 +216,7 @@ __setup("log_buf_len=", log_buf_len_setup);
  *     9 -- Return number of unread characters in the log buffer
  *     10 -- Return size of the log buffer
  */
-int do_syslog(int type, char __user * buf, int len)
+int do_syslog(int type, char __user *buf, int len)
 {
        unsigned long i, j, limit, count;
        int do_clear = 0;
@@ -244,7 +243,8 @@ int do_syslog(int type, char __user * buf, int len)
                        error = -EFAULT;
                        goto out;
                }
-               error = wait_event_interruptible(log_wait, (log_start - log_end));
+               error = wait_event_interruptible(log_wait,
+                                                       (log_start - log_end));
                if (error)
                        goto out;
                i = 0;
@@ -264,7 +264,7 @@ int do_syslog(int type, char __user * buf, int len)
                        error = i;
                break;
        case 4:         /* Read/clear last kernel messages */
-               do_clear = 1; 
+               do_clear = 1;
                /* FALL THRU */
        case 3:         /* Read last kernel messages */
                error = -EINVAL;
@@ -288,11 +288,11 @@ int do_syslog(int type, char __user * buf, int len)
                limit = log_end;
                /*
                 * __put_user() could sleep, and while we sleep
-                * printk() could overwrite the messages 
+                * printk() could overwrite the messages
                 * we try to copy to user space. Therefore
                 * the messages are copied in reverse. <manfreds>
                 */
-               for(i = 0; i < count && !error; i++) {
+               for (i = 0; i < count && !error; i++) {
                        j = limit-1-i;
                        if (j + log_buf_len < log_end)
                                break;
@@ -306,10 +306,10 @@ int do_syslog(int type, char __user * buf, int len)
                if (error)
                        break;
                error = i;
-               if(i != count) {
+               if (i != count) {
                        int offset = count-error;
                        /* buffer overflow during copy, correct user buffer. */
-                       for(i=0;i<error;i++) {
+                       for (i = 0; i < error; i++) {
                                if (__get_user(c,&buf[i+offset]) ||
                                    __put_user(c,&buf[i])) {
                                        error = -EFAULT;
@@ -351,7 +351,7 @@ out:
        return error;
 }
 
-asmlinkage long sys_syslog(int type, char __user * buf, int len)
+asmlinkage long sys_syslog(int type, char __user *buf, int len)
 {
        return do_syslog(type, buf, len);
 }
@@ -404,21 +404,19 @@ static void call_console_drivers(unsigned long start, unsigned long end)
        cur_index = start;
        start_print = start;
        while (cur_index != end) {
-               if (    msg_level < 0 &&
-                       ((end - cur_index) > 2) &&
-                       LOG_BUF(cur_index + 0) == '<' &&
-                       LOG_BUF(cur_index + 1) >= '0' &&
-                       LOG_BUF(cur_index + 1) <= '7' &&
-                       LOG_BUF(cur_index + 2) == '>')
-               {
+               if (msg_level < 0 && ((end - cur_index) > 2) &&
+                               LOG_BUF(cur_index + 0) == '<' &&
+                               LOG_BUF(cur_index + 1) >= '0' &&
+                               LOG_BUF(cur_index + 1) <= '7' &&
+                               LOG_BUF(cur_index + 2) == '>') {
                        msg_level = LOG_BUF(cur_index + 1) - '0';
                        cur_index += 3;
                        start_print = cur_index;
                }
                while (cur_index != end) {
                        char c = LOG_BUF(cur_index);
-                       cur_index++;
 
+                       cur_index++;
                        if (c == '\n') {
                                if (msg_level < 0) {
                                        /*
@@ -461,7 +459,7 @@ static void zap_locks(void)
        static unsigned long oops_timestamp;
 
        if (time_after_eq(jiffies, oops_timestamp) &&
-                       !time_after(jiffies, oops_timestamp + 30*HZ))
+                       !time_after(jiffies, oops_timestamp + 30 * HZ))
                return;
 
        oops_timestamp = jiffies;
@@ -488,9 +486,14 @@ static int __init printk_time_setup(char *str)
 
 __setup("time", printk_time_setup);
 
+__attribute__((weak)) unsigned long long printk_clock(void)
+{
+       return sched_clock();
+}
+
 /*
  * 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
  * into the log buffer and return.  The current holder of the console_sem will
@@ -514,6 +517,9 @@ asmlinkage int printk(const char *fmt, ...)
        return r;
 }
 
+/* cpu currently holding logbuf_lock */
+static volatile unsigned int printk_cpu = UINT_MAX;
+
 asmlinkage int vprintk(const char *fmt, va_list args)
 {
        unsigned long flags;
@@ -522,11 +528,15 @@ asmlinkage int vprintk(const char *fmt, va_list args)
        static char printk_buf[1024];
        static int log_level_unknown = 1;
 
-       if (unlikely(oops_in_progress))
+       preempt_disable();
+       if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id())
+               /* If a crash is occurring during printk() on this CPU,
+                * make sure we can't deadlock */
                zap_locks();
 
        /* This stops the holder of console_sem just where we want him */
        spin_lock_irqsave(&logbuf_lock, flags);
+       printk_cpu = smp_processor_id();
 
        /* Emit the output into the temporary buffer */
        printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
@@ -558,7 +568,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                                        loglev_char = default_message_loglevel
                                                + '0';
                                }
-                               t = sched_clock();
+                               t = printk_clock();
                                nanosec_rem = do_div(t, 1000000000);
                                tlen = sprintf(tbuf,
                                                "<%c>[%5lu.%06lu] ",
@@ -595,6 +605,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 * CPU until it is officially up.  We shouldn't be calling into
                 * random console drivers on a CPU which doesn't exist yet..
                 */
+               printk_cpu = UINT_MAX;
                spin_unlock_irqrestore(&logbuf_lock, flags);
                goto out;
        }
@@ -604,6 +615,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 * We own the drivers.  We can drop the spinlock and let
                 * release_console_sem() print the text
                 */
+               printk_cpu = UINT_MAX;
                spin_unlock_irqrestore(&logbuf_lock, flags);
                console_may_schedule = 0;
                release_console_sem();
@@ -613,9 +625,11 @@ asmlinkage int vprintk(const char *fmt, va_list args)
                 * allows the semaphore holder to proceed and to call the
                 * console drivers with the output which we just produced.
                 */
+               printk_cpu = UINT_MAX;
                spin_unlock_irqrestore(&logbuf_lock, flags);
        }
 out:
+       preempt_enable();
        return printed_len;
 }
 EXPORT_SYMBOL(printk);
@@ -623,13 +637,19 @@ EXPORT_SYMBOL(vprintk);
 
 #else
 
-asmlinkage long sys_syslog(int type, char __user * buf, int len)
+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; }
-static void call_console_drivers(unsigned long start, unsigned long end) {}
+int do_syslog(int type, char __user *buf, int len)
+{
+       return 0;
+}
+
+static void call_console_drivers(unsigned long start, unsigned long end)
+{
+}
 
 #endif
 
@@ -835,9 +855,9 @@ EXPORT_SYMBOL(console_start);
  * print any messages that were printed by the kernel before the
  * console driver was initialized.
  */
-void register_console(struct console * console)
+void register_console(struct console *console)
 {
-       int     i;
+       int i;
        unsigned long flags;
 
        if (preferred_console < 0)
@@ -862,7 +882,8 @@ void register_console(struct console * console)
         *      See if this console matches one we selected on
         *      the command line.
         */
-       for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
+       for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
+                       i++) {
                if (strcmp(console_cmdline[i].name, console->name) != 0)
                        continue;
                if (console->index >= 0 &&
@@ -917,9 +938,9 @@ void register_console(struct console * console)
 }
 EXPORT_SYMBOL(register_console);
 
-int unregister_console(struct console * console)
+int unregister_console(struct console *console)
 {
-        struct console *a,*b;
+        struct console *a, *b;
        int res = 1;
 
        acquire_console_sem();
@@ -933,10 +954,10 @@ int unregister_console(struct console * console)
                                b->next = a->next;
                                res = 0;
                                break;
-                       }  
+                       }
                }
        }
-       
+
        /* If last console is removed, we re-enable picking the first
         * one that gets registered. Without that, pmac early boot console
         * would prevent fbcon from taking over.
@@ -978,7 +999,7 @@ void tty_write_message(struct tty_struct *tty, char *msg)
 int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
 {
        static DEFINE_SPINLOCK(ratelimit_lock);
-       static unsigned long toks = 10*5*HZ;
+       static unsigned long toks = 10 * 5 * HZ;
        static unsigned long last_msg;
        static int missed;
        unsigned long flags;
@@ -991,6 +1012,7 @@ int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
                toks = ratelimit_burst * ratelimit_jiffies;
        if (toks >= ratelimit_jiffies) {
                int lost = missed;
+
                missed = 0;
                toks -= ratelimit_jiffies;
                spin_unlock_irqrestore(&ratelimit_lock, flags);
@@ -1005,7 +1027,7 @@ int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
 EXPORT_SYMBOL(__printk_ratelimit);
 
 /* minimum time in jiffies between messages */
-int printk_ratelimit_jiffies = 5*HZ;
+int printk_ratelimit_jiffies = 5 * HZ;
 
 /* number of messages we send before ratelimiting */
 int printk_ratelimit_burst = 10;