X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=kernel%2Fprintk.c;h=b2b5c3a22a36b302da177fafae653740f7eeeddf;hb=54f9f80d6543fb7b157d3b11e2e7911dc1379790;hp=4961410ba3672d5f6137a3b3e6f62e6785485aa3;hpb=eaa944afb206f3fc4393630811ee621b866e3255;p=linux-2.6 diff --git a/kernel/printk.c b/kernel/printk.c index 4961410ba3..b2b5c3a22a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include /* For in_interrupt() */ @@ -162,6 +164,61 @@ out: __setup("log_buf_len=", log_buf_len_setup); +#ifdef CONFIG_BOOT_PRINTK_DELAY + +static unsigned int boot_delay; /* msecs delay after each printk during bootup */ +static unsigned long long printk_delay_msec; /* per msec, based on boot_delay */ + +static int __init boot_delay_setup(char *str) +{ + unsigned long lpj; + unsigned long long loops_per_msec; + + lpj = preset_lpj ? preset_lpj : 1000000; /* some guess */ + loops_per_msec = (unsigned long long)lpj / 1000 * HZ; + + get_option(&str, &boot_delay); + if (boot_delay > 10 * 1000) + boot_delay = 0; + + printk_delay_msec = loops_per_msec; + printk(KERN_DEBUG "boot_delay: %u, preset_lpj: %ld, lpj: %lu, " + "HZ: %d, printk_delay_msec: %llu\n", + boot_delay, preset_lpj, lpj, HZ, printk_delay_msec); + return 1; +} +__setup("boot_delay=", boot_delay_setup); + +static void boot_delay_msec(void) +{ + unsigned long long k; + unsigned long timeout; + + if (boot_delay == 0 || system_state != SYSTEM_BOOTING) + return; + + k = (unsigned long long)printk_delay_msec * boot_delay; + + timeout = jiffies + msecs_to_jiffies(boot_delay); + while (k) { + k--; + cpu_relax(); + /* + * use (volatile) jiffies to prevent + * compiler reduction; loop termination via jiffies + * is secondary and may or may not happen. + */ + if (time_after(jiffies, timeout)) + break; + touch_nmi_watchdog(); + } +} +#else +static inline void boot_delay_msec(void) +{ +} +#endif + /* * Commands to do_syslog: * @@ -449,13 +506,16 @@ static int printk_time = 1; #else static int printk_time = 0; #endif -module_param(printk_time, int, S_IRUGO | S_IWUSR); +module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); static int __init printk_time_setup(char *str) { if (*str) return 0; printk_time = 1; + printk(KERN_NOTICE "The 'time' option is deprecated and " + "is scheduled for removal in early 2008\n"); + printk(KERN_NOTICE "Use 'printk.time=' instead\n"); return 1; } @@ -483,6 +543,9 @@ static int have_callable_console(void) * @fmt: format string * * This is printk(). It can be called from any context. We want it to work. + * Be aware of the fact that if oops_in_progress is not set, we might try to + * wake klogd up which could deadlock on runqueue lock if printk() is called + * from scheduler code. * * 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 @@ -521,6 +584,8 @@ asmlinkage int vprintk(const char *fmt, va_list args) static char printk_buf[1024]; static int log_level_unknown = 1; + boot_delay_msec(); + preempt_disable(); if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id()) /* If a crash is occurring during printk() on this CPU, @@ -726,6 +791,25 @@ int __init add_preferred_console(char *name, int idx, char *options) return 0; } +int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options) +{ + struct console_cmdline *c; + int i; + + for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) + if (strcmp(console_cmdline[i].name, name) == 0 && + console_cmdline[i].index == idx) { + c = &console_cmdline[i]; + memcpy(c->name, name_new, sizeof(c->name)); + c->name[sizeof(c->name) - 1] = 0; + c->options = options; + c->index = idx_new; + return i; + } + /* not found */ + return -1; +} + #ifndef CONFIG_DISABLE_CONSOLE_SUSPEND /** * suspend_console - suspend the console subsystem @@ -942,6 +1026,9 @@ void register_console(struct console *console) if (preferred_console < 0 || bootconsole || !console_drivers) preferred_console = selected_console; + if (console->early_setup) + console->early_setup(); + /* * See if we want to use this console driver. If we * didn't select a console we take the first one @@ -985,12 +1072,15 @@ void register_console(struct console *console) if (!(console->flags & CON_ENABLED)) return; - if (bootconsole) { + if (bootconsole && (console->flags & CON_CONSDEV)) { printk(KERN_INFO "console handover: boot [%s%d] -> real [%s%d]\n", bootconsole->name, bootconsole->index, console->name, console->index); unregister_console(bootconsole); console->flags &= ~CON_PRINTBUFFER; + } else { + printk(KERN_INFO "console [%s%d] enabled\n", + console->name, console->index); } /* @@ -1052,6 +1142,19 @@ int unregister_console(struct console *console) } EXPORT_SYMBOL(unregister_console); +static int __init disable_boot_consoles(void) +{ + if (console_drivers != NULL) { + if (console_drivers->flags & CON_BOOT) { + printk(KERN_INFO "turn off boot console %s%d\n", + console_drivers->name, console_drivers->index); + return unregister_console(console_drivers); + } + } + return 0; +} +late_initcall(disable_boot_consoles); + /** * tty_write_message - write a message to a certain tty, not just the console. * @tty: the destination tty_struct