|
@@ -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;
|