diff options
| -rw-r--r-- | include/linux/printk.h | 3 | ||||
| -rw-r--r-- | init/Kconfig | 1 | ||||
| -rw-r--r-- | kernel/printk.c | 36 | ||||
| -rw-r--r-- | kernel/time/tick-sched.c | 2 | ||||
| -rw-r--r-- | kernel/timer.c | 1 | 
5 files changed, 22 insertions, 21 deletions
diff --git a/include/linux/printk.h b/include/linux/printk.h index 9afc01e5a0a..86c4b629471 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -98,9 +98,6 @@ int no_printk(const char *fmt, ...)  extern asmlinkage __printf(1, 2)  void early_printk(const char *fmt, ...); -extern int printk_needs_cpu(int cpu); -extern void printk_tick(void); -  #ifdef CONFIG_PRINTK  asmlinkage __printf(5, 0)  int vprintk_emit(int facility, int level, diff --git a/init/Kconfig b/init/Kconfig index cdc152c7572..c575566be47 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1196,6 +1196,7 @@ config HOTPLUG  config PRINTK  	default y  	bool "Enable support for printk" if EXPERT +	select IRQ_WORK  	help  	  This option enables normal printk support. Removing it  	  eliminates most of the message strings from the kernel image diff --git a/kernel/printk.c b/kernel/printk.c index 2d607f4d179..c9104feba5e 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -42,6 +42,7 @@  #include <linux/notifier.h>  #include <linux/rculist.h>  #include <linux/poll.h> +#include <linux/irq_work.h>  #include <asm/uaccess.h> @@ -1955,30 +1956,32 @@ int is_console_locked(void)  static DEFINE_PER_CPU(int, printk_pending);  static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); -void printk_tick(void) +static void wake_up_klogd_work_func(struct irq_work *irq_work)  { -	if (__this_cpu_read(printk_pending)) { -		int pending = __this_cpu_xchg(printk_pending, 0); -		if (pending & PRINTK_PENDING_SCHED) { -			char *buf = __get_cpu_var(printk_sched_buf); -			printk(KERN_WARNING "[sched_delayed] %s", buf); -		} -		if (pending & PRINTK_PENDING_WAKEUP) -			wake_up_interruptible(&log_wait); +	int pending = __this_cpu_xchg(printk_pending, 0); + +	if (pending & PRINTK_PENDING_SCHED) { +		char *buf = __get_cpu_var(printk_sched_buf); +		printk(KERN_WARNING "[sched_delayed] %s", buf);  	} -} -int printk_needs_cpu(int cpu) -{ -	if (cpu_is_offline(cpu)) -		printk_tick(); -	return __this_cpu_read(printk_pending); +	if (pending & PRINTK_PENDING_WAKEUP) +		wake_up_interruptible(&log_wait);  } +static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { +	.func = wake_up_klogd_work_func, +	.flags = IRQ_WORK_LAZY, +}; +  void wake_up_klogd(void)  { -	if (waitqueue_active(&log_wait)) +	preempt_disable(); +	if (waitqueue_active(&log_wait)) {  		this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); +		irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); +	} +	preempt_enable();  }  static void console_cont_flush(char *text, size_t size) @@ -2458,6 +2461,7 @@ int printk_sched(const char *fmt, ...)  	va_end(args);  	__this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); +	irq_work_queue(&__get_cpu_var(wake_up_klogd_work));  	local_irq_restore(flags);  	return r; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f249e8c3e58..822d7572bf2 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,  		time_delta = timekeeping_max_deferment();  	} while (read_seqretry(&xtime_lock, seq)); -	if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) || printk_needs_cpu(cpu) || +	if (rcu_needs_cpu(cpu, &rcu_delta_jiffies) ||  	    arch_needs_cpu(cpu) || irq_work_needs_cpu()) {  		next_jiffies = last_jiffies + 1;  		delta_jiffies = 1; diff --git a/kernel/timer.c b/kernel/timer.c index 367d0085848..ff3b5165737 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1351,7 +1351,6 @@ void update_process_times(int user_tick)  	account_process_tick(p, user_tick);  	run_local_timers();  	rcu_check_callbacks(cpu, user_tick); -	printk_tick();  #ifdef CONFIG_IRQ_WORK  	if (in_irq())  		irq_work_run();  |