aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/printk.h3
-rw-r--r--init/Kconfig1
-rw-r--r--kernel/printk.c36
-rw-r--r--kernel/time/tick-sched.c2
-rw-r--r--kernel/timer.c1
5 files changed, 22 insertions, 21 deletions
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 9afc01e5a0a6..86c4b6294713 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -98,9 +98,6 @@ int no_printk(const char *fmt, ...)
98extern asmlinkage __printf(1, 2) 98extern asmlinkage __printf(1, 2)
99void early_printk(const char *fmt, ...); 99void early_printk(const char *fmt, ...);
100 100
101extern int printk_needs_cpu(int cpu);
102extern void printk_tick(void);
103
104#ifdef CONFIG_PRINTK 101#ifdef CONFIG_PRINTK
105asmlinkage __printf(5, 0) 102asmlinkage __printf(5, 0)
106int vprintk_emit(int facility, int level, 103int vprintk_emit(int facility, int level,
diff --git a/init/Kconfig b/init/Kconfig
index cdc152c75727..c575566be47d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1196,6 +1196,7 @@ config HOTPLUG
1196config PRINTK 1196config PRINTK
1197 default y 1197 default y
1198 bool "Enable support for printk" if EXPERT 1198 bool "Enable support for printk" if EXPERT
1199 select IRQ_WORK
1199 help 1200 help
1200 This option enables normal printk support. Removing it 1201 This option enables normal printk support. Removing it
1201 eliminates most of the message strings from the kernel image 1202 eliminates most of the message strings from the kernel image
diff --git a/kernel/printk.c b/kernel/printk.c
index 2d607f4d1797..c9104feba5ec 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
@@ -1955,30 +1956,32 @@ int is_console_locked(void)
1955static DEFINE_PER_CPU(int, printk_pending); 1956static DEFINE_PER_CPU(int, printk_pending);
1956static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); 1957static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
1957 1958
1958void printk_tick(void) 1959static void wake_up_klogd_work_func(struct irq_work *irq_work)
1959{ 1960{
1960 if (__this_cpu_read(printk_pending)) { 1961 int pending = __this_cpu_xchg(printk_pending, 0);
1961 int pending = __this_cpu_xchg(printk_pending, 0); 1962
1962 if (pending & PRINTK_PENDING_SCHED) { 1963 if (pending & PRINTK_PENDING_SCHED) {
1963 char *buf = __get_cpu_var(printk_sched_buf); 1964 char *buf = __get_cpu_var(printk_sched_buf);
1964 printk(KERN_WARNING "[sched_delayed] %s", buf); 1965 printk(KERN_WARNING "[sched_delayed] %s", buf);
1965 }
1966 if (pending & PRINTK_PENDING_WAKEUP)
1967 wake_up_interruptible(&log_wait);
1968 } 1966 }
1969}
1970 1967
1971int printk_needs_cpu(int cpu) 1968 if (pending & PRINTK_PENDING_WAKEUP)
1972{ 1969 wake_up_interruptible(&log_wait);
1973 if (cpu_is_offline(cpu))
1974 printk_tick();
1975 return __this_cpu_read(printk_pending);
1976} 1970}
1977 1971
1972static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
1973 .func = wake_up_klogd_work_func,
1974 .flags = IRQ_WORK_LAZY,
1975};
1976
1978void wake_up_klogd(void) 1977void wake_up_klogd(void)
1979{ 1978{
1980 if (waitqueue_active(&log_wait)) 1979 preempt_disable();
1980 if (waitqueue_active(&log_wait)) {
1981 this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); 1981 this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
1982 irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
1983 }
1984 preempt_enable();
1982} 1985}
1983 1986
1984static void console_cont_flush(char *text, size_t size) 1987static void console_cont_flush(char *text, size_t size)
@@ -2458,6 +2461,7 @@ int printk_sched(const char *fmt, ...)
2458 va_end(args); 2461 va_end(args);
2459 2462
2460 __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); 2463 __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED);
2464 irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
2461 local_irq_restore(flags); 2465 local_irq_restore(flags);
2462 2466
2463 return r; 2467 return r;
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index f249e8c3e58e..822d7572bf2d 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -289,7 +289,7 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
289 time_delta = timekeeping_max_deferment(); 289 time_delta = timekeeping_max_deferment();
290 } while (read_seqretry(&xtime_lock, seq)); 290 } while (read_seqretry(&xtime_lock, seq));
291 291
292 if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || printk_needs_cpu(cpu) || 292 if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) ||
293 arch_needs_cpu(cpu) || irq_work_needs_cpu()) { 293 arch_needs_cpu(cpu) || irq_work_needs_cpu()) {
294 next_jiffies = last_jiffies + 1; 294 next_jiffies = last_jiffies + 1;
295 delta_jiffies = 1; 295 delta_jiffies = 1;
diff --git a/kernel/timer.c b/kernel/timer.c
index 367d00858482..ff3b5165737b 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1351,7 +1351,6 @@ void update_process_times(int user_tick)
1351 account_process_tick(p, user_tick); 1351 account_process_tick(p, user_tick);
1352 run_local_timers(); 1352 run_local_timers();
1353 rcu_check_callbacks(cpu, user_tick); 1353 rcu_check_callbacks(cpu, user_tick);
1354 printk_tick();
1355#ifdef CONFIG_IRQ_WORK 1354#ifdef CONFIG_IRQ_WORK
1356 if (in_irq()) 1355 if (in_irq())
1357 irq_work_run(); 1356 irq_work_run();