aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c108
1 files changed, 82 insertions, 26 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index c056f3324432..65ca0688f86f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -24,8 +24,8 @@
24#include <linux/console.h> 24#include <linux/console.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/moduleparam.h>
27#include <linux/interrupt.h> /* For in_interrupt() */ 28#include <linux/interrupt.h> /* For in_interrupt() */
28#include <linux/config.h>
29#include <linux/delay.h> 29#include <linux/delay.h>
30#include <linux/smp.h> 30#include <linux/smp.h>
31#include <linux/security.h> 31#include <linux/security.h>
@@ -52,7 +52,7 @@ int console_printk[4] = {
52 DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */ 52 DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
53}; 53};
54 54
55EXPORT_SYMBOL(console_printk); 55EXPORT_UNUSED_SYMBOL(console_printk); /* June 2006 */
56 56
57/* 57/*
58 * Low lever drivers may need that to know if they can schedule in 58 * Low lever drivers may need that to know if they can schedule in
@@ -67,6 +67,7 @@ EXPORT_SYMBOL(oops_in_progress);
67 * driver system. 67 * driver system.
68 */ 68 */
69static DECLARE_MUTEX(console_sem); 69static DECLARE_MUTEX(console_sem);
70static DECLARE_MUTEX(secondary_console_sem);
70struct console *console_drivers; 71struct console *console_drivers;
71/* 72/*
72 * This is used for debugging the mess that is the VT code by 73 * This is used for debugging the mess that is the VT code by
@@ -76,7 +77,7 @@ struct console *console_drivers;
76 * path in the console code where we end up in places I want 77 * path in the console code where we end up in places I want
77 * locked without the console sempahore held 78 * locked without the console sempahore held
78 */ 79 */
79static int console_locked; 80static int console_locked, console_suspended;
80 81
81/* 82/*
82 * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars 83 * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
@@ -326,7 +327,9 @@ static void __call_console_drivers(unsigned long start, unsigned long end)
326 struct console *con; 327 struct console *con;
327 328
328 for (con = console_drivers; con; con = con->next) { 329 for (con = console_drivers; con; con = con->next) {
329 if ((con->flags & CON_ENABLED) && con->write) 330 if ((con->flags & CON_ENABLED) && con->write &&
331 (cpu_online(smp_processor_id()) ||
332 (con->flags & CON_ANYTIME)))
330 con->write(con, &LOG_BUF(start), end - start); 333 con->write(con, &LOG_BUF(start), end - start);
331 } 334 }
332} 335}
@@ -436,6 +439,7 @@ static int printk_time = 1;
436#else 439#else
437static int printk_time = 0; 440static int printk_time = 0;
438#endif 441#endif
442module_param(printk_time, int, S_IRUGO | S_IWUSR);
439 443
440static int __init printk_time_setup(char *str) 444static int __init printk_time_setup(char *str)
441{ 445{
@@ -452,6 +456,18 @@ __attribute__((weak)) unsigned long long printk_clock(void)
452 return sched_clock(); 456 return sched_clock();
453} 457}
454 458
459/* Check if we have any console registered that can be called early in boot. */
460static int have_callable_console(void)
461{
462 struct console *con;
463
464 for (con = console_drivers; con; con = con->next)
465 if (con->flags & CON_ANYTIME)
466 return 1;
467
468 return 0;
469}
470
455/** 471/**
456 * printk - print a kernel message 472 * printk - print a kernel message
457 * @fmt: format string 473 * @fmt: format string
@@ -502,7 +518,9 @@ asmlinkage int vprintk(const char *fmt, va_list args)
502 zap_locks(); 518 zap_locks();
503 519
504 /* This stops the holder of console_sem just where we want him */ 520 /* This stops the holder of console_sem just where we want him */
505 spin_lock_irqsave(&logbuf_lock, flags); 521 local_irq_save(flags);
522 lockdep_off();
523 spin_lock(&logbuf_lock);
506 printk_cpu = smp_processor_id(); 524 printk_cpu = smp_processor_id();
507 525
508 /* Emit the output into the temporary buffer */ 526 /* Emit the output into the temporary buffer */
@@ -565,27 +583,31 @@ asmlinkage int vprintk(const char *fmt, va_list args)
565 log_level_unknown = 1; 583 log_level_unknown = 1;
566 } 584 }
567 585
568 if (!cpu_online(smp_processor_id())) { 586 if (!down_trylock(&console_sem)) {
569 /* 587 /*
570 * Some console drivers may assume that per-cpu resources have 588 * We own the drivers. We can drop the spinlock and
571 * been allocated. So don't allow them to be called by this 589 * let release_console_sem() print the text, maybe ...
572 * CPU until it is officially up. We shouldn't be calling into
573 * random console drivers on a CPU which doesn't exist yet..
574 */ 590 */
575 printk_cpu = UINT_MAX;
576 spin_unlock_irqrestore(&logbuf_lock, flags);
577 goto out;
578 }
579 if (!down_trylock(&console_sem)) {
580 console_locked = 1; 591 console_locked = 1;
592 printk_cpu = UINT_MAX;
593 spin_unlock(&logbuf_lock);
594
581 /* 595 /*
582 * We own the drivers. We can drop the spinlock and let 596 * Console drivers may assume that per-cpu resources have
583 * release_console_sem() print the text 597 * been allocated. So unless they're explicitly marked as
598 * being able to cope (CON_ANYTIME) don't call them until
599 * this CPU is officially up.
584 */ 600 */
585 printk_cpu = UINT_MAX; 601 if (cpu_online(smp_processor_id()) || have_callable_console()) {
586 spin_unlock_irqrestore(&logbuf_lock, flags); 602 console_may_schedule = 0;
587 console_may_schedule = 0; 603 release_console_sem();
588 release_console_sem(); 604 } else {
605 /* Release by hand to avoid flushing the buffer. */
606 console_locked = 0;
607 up(&console_sem);
608 }
609 lockdep_on();
610 local_irq_restore(flags);
589 } else { 611 } else {
590 /* 612 /*
591 * Someone else owns the drivers. We drop the spinlock, which 613 * Someone else owns the drivers. We drop the spinlock, which
@@ -593,9 +615,11 @@ asmlinkage int vprintk(const char *fmt, va_list args)
593 * console drivers with the output which we just produced. 615 * console drivers with the output which we just produced.
594 */ 616 */
595 printk_cpu = UINT_MAX; 617 printk_cpu = UINT_MAX;
596 spin_unlock_irqrestore(&logbuf_lock, flags); 618 spin_unlock(&logbuf_lock);
619 lockdep_on();
620 local_irq_restore(flags);
597 } 621 }
598out: 622
599 preempt_enable(); 623 preempt_enable();
600 return printed_len; 624 return printed_len;
601} 625}
@@ -698,6 +722,23 @@ int __init add_preferred_console(char *name, int idx, char *options)
698} 722}
699 723
700/** 724/**
725 * suspend_console - suspend the console subsystem
726 *
727 * This disables printk() while we go into suspend states
728 */
729void suspend_console(void)
730{
731 acquire_console_sem();
732 console_suspended = 1;
733}
734
735void resume_console(void)
736{
737 console_suspended = 0;
738 release_console_sem();
739}
740
741/**
701 * acquire_console_sem - lock the console system for exclusive use. 742 * acquire_console_sem - lock the console system for exclusive use.
702 * 743 *
703 * Acquires a semaphore which guarantees that the caller has 744 * Acquires a semaphore which guarantees that the caller has
@@ -708,6 +749,10 @@ int __init add_preferred_console(char *name, int idx, char *options)
708void acquire_console_sem(void) 749void acquire_console_sem(void)
709{ 750{
710 BUG_ON(in_interrupt()); 751 BUG_ON(in_interrupt());
752 if (console_suspended) {
753 down(&secondary_console_sem);
754 return;
755 }
711 down(&console_sem); 756 down(&console_sem);
712 console_locked = 1; 757 console_locked = 1;
713 console_may_schedule = 1; 758 console_may_schedule = 1;
@@ -728,7 +773,7 @@ int is_console_locked(void)
728{ 773{
729 return console_locked; 774 return console_locked;
730} 775}
731EXPORT_SYMBOL(is_console_locked); 776EXPORT_UNUSED_SYMBOL(is_console_locked); /* June 2006 */
732 777
733/** 778/**
734 * release_console_sem - unlock the console system 779 * release_console_sem - unlock the console system
@@ -750,6 +795,10 @@ void release_console_sem(void)
750 unsigned long _con_start, _log_end; 795 unsigned long _con_start, _log_end;
751 unsigned long wake_klogd = 0; 796 unsigned long wake_klogd = 0;
752 797
798 if (console_suspended) {
799 up(&secondary_console_sem);
800 return;
801 }
753 for ( ; ; ) { 802 for ( ; ; ) {
754 spin_lock_irqsave(&logbuf_lock, flags); 803 spin_lock_irqsave(&logbuf_lock, flags);
755 wake_klogd |= log_start - log_end; 804 wake_klogd |= log_start - log_end;
@@ -766,8 +815,15 @@ void release_console_sem(void)
766 console_may_schedule = 0; 815 console_may_schedule = 0;
767 up(&console_sem); 816 up(&console_sem);
768 spin_unlock_irqrestore(&logbuf_lock, flags); 817 spin_unlock_irqrestore(&logbuf_lock, flags);
769 if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) 818 if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) {
770 wake_up_interruptible(&log_wait); 819 /*
820 * If we printk from within the lock dependency code,
821 * from within the scheduler code, then do not lock
822 * up due to self-recursion:
823 */
824 if (!lockdep_internal())
825 wake_up_interruptible(&log_wait);
826 }
771} 827}
772EXPORT_SYMBOL(release_console_sem); 828EXPORT_SYMBOL(release_console_sem);
773 829