提交 f8729e85 编写于 作者: A Anton Blanchard 提交者: Benjamin Herrenschmidt

powerpc: Convert RTAS event scan from kernel thread to workqueue

RTAS event scan has to run across all cpus. Right now we use a kernel
thread and set_cpus_allowed but in doing so we wake up the previous cpu
unnecessarily.

Some ftrace output shows this:

previous cpu (2):
[002]  7.022331: sched_switch: task swapper:0 [140] ==> rtasd:194 [120]
[002]  7.022338: sched_switch: task rtasd:194 [120] ==> migration/2:9 [0]
[002]  7.022344: sched_switch: task migration/2:9 [0] ==> swapper:0 [140]

next cpu (3):
[003]  7.022345: sched_switch: task swapper:0 [140] ==> rtasd:194 [120]
[003]  7.022371: sched_switch: task rtasd:194 [120] ==> swapper:0 [140]

We can use schedule_delayed_work_on and avoid the unnecessary wakeup.
Signed-off-by: NAnton Blanchard <anton@samba.org>
Signed-off-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
上级 0512a9a8
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/delay.h> #include <linux/workqueue.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -387,36 +387,51 @@ static void do_event_scan(void) ...@@ -387,36 +387,51 @@ static void do_event_scan(void)
} while(error == 0); } while(error == 0);
} }
static void do_event_scan_all_cpus(long delay) static void rtas_event_scan(struct work_struct *w);
DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan);
/*
* Delay should be at least one second since some machines have problems if
* we call event-scan too quickly.
*/
static unsigned long event_scan_delay = 1*HZ;
static int first_pass = 1;
static void rtas_event_scan(struct work_struct *w)
{ {
int cpu; unsigned int cpu;
do_event_scan();
get_online_cpus(); get_online_cpus();
cpu = first_cpu(cpu_online_map);
for (;;) { cpu = next_cpu(smp_processor_id(), cpu_online_map);
set_cpus_allowed(current, cpumask_of_cpu(cpu)); if (cpu == NR_CPUS) {
do_event_scan(); cpu = first_cpu(cpu_online_map);
set_cpus_allowed(current, CPU_MASK_ALL);
if (first_pass) {
/* Drop hotplug lock, and sleep for the specified delay */ first_pass = 0;
put_online_cpus(); event_scan_delay = 30*HZ/rtas_event_scan_rate;
msleep_interruptible(delay);
get_online_cpus(); if (surveillance_timeout != -1) {
pr_debug("rtasd: enabling surveillance\n");
cpu = next_cpu(cpu, cpu_online_map); enable_surveillance(surveillance_timeout);
if (cpu == NR_CPUS) pr_debug("rtasd: surveillance enabled\n");
break; }
}
} }
schedule_delayed_work_on(cpu, &event_scan_work,
__round_jiffies_relative(event_scan_delay, cpu));
put_online_cpus(); put_online_cpus();
} }
static int rtasd(void *unused) static void start_event_scan(void)
{ {
unsigned int err_type; unsigned int err_type;
int rc; int rc;
daemonize("rtasd");
printk(KERN_DEBUG "RTAS daemon started\n"); printk(KERN_DEBUG "RTAS daemon started\n");
pr_debug("rtasd: will sleep for %d milliseconds\n", pr_debug("rtasd: will sleep for %d milliseconds\n",
(30000 / rtas_event_scan_rate)); (30000 / rtas_event_scan_rate));
...@@ -434,22 +449,8 @@ static int rtasd(void *unused) ...@@ -434,22 +449,8 @@ static int rtasd(void *unused)
} }
} }
/* First pass. */ schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work,
do_event_scan_all_cpus(1000); event_scan_delay);
if (surveillance_timeout != -1) {
pr_debug("rtasd: enabling surveillance\n");
enable_surveillance(surveillance_timeout);
pr_debug("rtasd: surveillance enabled\n");
}
/* Delay should be at least one second since some
* machines have problems if we call event-scan too
* quickly. */
for (;;)
do_event_scan_all_cpus(30000/rtas_event_scan_rate);
return -EINVAL;
} }
static int __init rtas_init(void) static int __init rtas_init(void)
...@@ -487,8 +488,7 @@ static int __init rtas_init(void) ...@@ -487,8 +488,7 @@ static int __init rtas_init(void)
if (!entry) if (!entry)
printk(KERN_ERR "Failed to create error_log proc entry\n"); printk(KERN_ERR "Failed to create error_log proc entry\n");
if (kernel_thread(rtasd, NULL, CLONE_FS) < 0) start_event_scan();
printk(KERN_ERR "Failed to start RTAS daemon\n");
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册