diff options
Diffstat (limited to 'kernel/printk.c')
| -rw-r--r-- | kernel/printk.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 267ce780abe8..f24633afa46a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/notifier.h> | 42 | #include <linux/notifier.h> |
| 43 | #include <linux/rculist.h> | 43 | #include <linux/rculist.h> |
| 44 | #include <linux/poll.h> | 44 | #include <linux/poll.h> |
| 45 | #include <linux/irq_work.h> | ||
| 45 | 46 | ||
| 46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
| 47 | 48 | ||
| @@ -1959,30 +1960,32 @@ int is_console_locked(void) | |||
| 1959 | static DEFINE_PER_CPU(int, printk_pending); | 1960 | static DEFINE_PER_CPU(int, printk_pending); |
| 1960 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | 1961 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); |
| 1961 | 1962 | ||
| 1962 | void printk_tick(void) | 1963 | static void wake_up_klogd_work_func(struct irq_work *irq_work) |
| 1963 | { | 1964 | { |
| 1964 | if (__this_cpu_read(printk_pending)) { | 1965 | int pending = __this_cpu_xchg(printk_pending, 0); |
| 1965 | int pending = __this_cpu_xchg(printk_pending, 0); | 1966 | |
| 1966 | if (pending & PRINTK_PENDING_SCHED) { | 1967 | if (pending & PRINTK_PENDING_SCHED) { |
| 1967 | char *buf = __get_cpu_var(printk_sched_buf); | 1968 | char *buf = __get_cpu_var(printk_sched_buf); |
| 1968 | printk(KERN_WARNING "[sched_delayed] %s", buf); | 1969 | printk(KERN_WARNING "[sched_delayed] %s", buf); |
| 1969 | } | ||
| 1970 | if (pending & PRINTK_PENDING_WAKEUP) | ||
| 1971 | wake_up_interruptible(&log_wait); | ||
| 1972 | } | 1970 | } |
| 1973 | } | ||
| 1974 | 1971 | ||
| 1975 | int printk_needs_cpu(int cpu) | 1972 | if (pending & PRINTK_PENDING_WAKEUP) |
| 1976 | { | 1973 | wake_up_interruptible(&log_wait); |
| 1977 | if (cpu_is_offline(cpu)) | ||
| 1978 | printk_tick(); | ||
| 1979 | return __this_cpu_read(printk_pending); | ||
| 1980 | } | 1974 | } |
| 1981 | 1975 | ||
| 1976 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { | ||
| 1977 | .func = wake_up_klogd_work_func, | ||
| 1978 | .flags = IRQ_WORK_LAZY, | ||
| 1979 | }; | ||
| 1980 | |||
| 1982 | void wake_up_klogd(void) | 1981 | void wake_up_klogd(void) |
| 1983 | { | 1982 | { |
| 1984 | if (waitqueue_active(&log_wait)) | 1983 | preempt_disable(); |
| 1984 | if (waitqueue_active(&log_wait)) { | ||
| 1985 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | 1985 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); |
| 1986 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
| 1987 | } | ||
| 1988 | preempt_enable(); | ||
| 1986 | } | 1989 | } |
| 1987 | 1990 | ||
| 1988 | static void console_cont_flush(char *text, size_t size) | 1991 | static void console_cont_flush(char *text, size_t size) |
| @@ -2462,6 +2465,7 @@ int printk_sched(const char *fmt, ...) | |||
| 2462 | va_end(args); | 2465 | va_end(args); |
| 2463 | 2466 | ||
| 2464 | __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); | 2467 | __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); |
| 2468 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
| 2465 | local_irq_restore(flags); | 2469 | local_irq_restore(flags); |
| 2466 | 2470 | ||
| 2467 | return r; | 2471 | return r; |
