diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/printk.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 19a955619294..6b89dd9d11b6 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -327,7 +327,9 @@ static void __call_console_drivers(unsigned long start, unsigned long end) | |||
| 327 | struct console *con; | 327 | struct console *con; |
| 328 | 328 | ||
| 329 | for (con = console_drivers; con; con = con->next) { | 329 | for (con = console_drivers; con; con = con->next) { |
| 330 | 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))) | ||
| 331 | con->write(con, &LOG_BUF(start), end - start); | 333 | con->write(con, &LOG_BUF(start), end - start); |
| 332 | } | 334 | } |
| 333 | } | 335 | } |
| @@ -453,6 +455,18 @@ __attribute__((weak)) unsigned long long printk_clock(void) | |||
| 453 | return sched_clock(); | 455 | return sched_clock(); |
| 454 | } | 456 | } |
| 455 | 457 | ||
| 458 | /* Check if we have any console registered that can be called early in boot. */ | ||
| 459 | static int have_callable_console(void) | ||
| 460 | { | ||
| 461 | struct console *con; | ||
| 462 | |||
| 463 | for (con = console_drivers; con; con = con->next) | ||
| 464 | if (con->flags & CON_ANYTIME) | ||
| 465 | return 1; | ||
| 466 | |||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 456 | /** | 470 | /** |
| 457 | * printk - print a kernel message | 471 | * printk - print a kernel message |
| 458 | * @fmt: format string | 472 | * @fmt: format string |
| @@ -566,27 +580,29 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
| 566 | log_level_unknown = 1; | 580 | log_level_unknown = 1; |
| 567 | } | 581 | } |
| 568 | 582 | ||
| 569 | if (!cpu_online(smp_processor_id())) { | 583 | if (!down_trylock(&console_sem)) { |
| 570 | /* | 584 | /* |
| 571 | * Some console drivers may assume that per-cpu resources have | 585 | * We own the drivers. We can drop the spinlock and |
| 572 | * been allocated. So don't allow them to be called by this | 586 | * let release_console_sem() print the text, maybe ... |
| 573 | * CPU until it is officially up. We shouldn't be calling into | ||
| 574 | * random console drivers on a CPU which doesn't exist yet.. | ||
| 575 | */ | 587 | */ |
| 588 | console_locked = 1; | ||
| 576 | printk_cpu = UINT_MAX; | 589 | printk_cpu = UINT_MAX; |
| 577 | spin_unlock_irqrestore(&logbuf_lock, flags); | 590 | spin_unlock_irqrestore(&logbuf_lock, flags); |
| 578 | goto out; | 591 | |
| 579 | } | ||
| 580 | if (!down_trylock(&console_sem)) { | ||
| 581 | console_locked = 1; | ||
| 582 | /* | 592 | /* |
| 583 | * We own the drivers. We can drop the spinlock and let | 593 | * Console drivers may assume that per-cpu resources have |
| 584 | * release_console_sem() print the text | 594 | * been allocated. So unless they're explicitly marked as |
| 595 | * being able to cope (CON_ANYTIME) don't call them until | ||
| 596 | * this CPU is officially up. | ||
| 585 | */ | 597 | */ |
| 586 | printk_cpu = UINT_MAX; | 598 | if (cpu_online(smp_processor_id()) || have_callable_console()) { |
| 587 | spin_unlock_irqrestore(&logbuf_lock, flags); | 599 | console_may_schedule = 0; |
| 588 | console_may_schedule = 0; | 600 | release_console_sem(); |
| 589 | release_console_sem(); | 601 | } else { |
| 602 | /* Release by hand to avoid flushing the buffer. */ | ||
| 603 | console_locked = 0; | ||
| 604 | up(&console_sem); | ||
| 605 | } | ||
| 590 | } else { | 606 | } else { |
| 591 | /* | 607 | /* |
| 592 | * Someone else owns the drivers. We drop the spinlock, which | 608 | * Someone else owns the drivers. We drop the spinlock, which |
| @@ -596,7 +612,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
| 596 | printk_cpu = UINT_MAX; | 612 | printk_cpu = UINT_MAX; |
| 597 | spin_unlock_irqrestore(&logbuf_lock, flags); | 613 | spin_unlock_irqrestore(&logbuf_lock, flags); |
| 598 | } | 614 | } |
| 599 | out: | 615 | |
| 600 | preempt_enable(); | 616 | preempt_enable(); |
| 601 | return printed_len; | 617 | return printed_len; |
| 602 | } | 618 | } |
