Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / powerpc / platforms / pseries / rtasd.c
index afad9f5..b3cbac8 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
-#include <linux/delay.h>
+#include <linux/workqueue.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -387,36 +387,51 @@ static void do_event_scan(void)
        } 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();
-       cpu = first_cpu(cpu_online_map);
-       for (;;) {
-               set_cpus_allowed(current, cpumask_of_cpu(cpu));
-               do_event_scan();
-               set_cpus_allowed(current, CPU_MASK_ALL);
-
-               /* Drop hotplug lock, and sleep for the specified delay */
-               put_online_cpus();
-               msleep_interruptible(delay);
-               get_online_cpus();
-
-               cpu = next_cpu(cpu, cpu_online_map);
-               if (cpu == NR_CPUS)
-                       break;
+
+       cpu = next_cpu(smp_processor_id(), cpu_online_map);
+       if (cpu == NR_CPUS) {
+               cpu = first_cpu(cpu_online_map);
+
+               if (first_pass) {
+                       first_pass = 0;
+                       event_scan_delay = 30*HZ/rtas_event_scan_rate;
+
+                       if (surveillance_timeout != -1) {
+                               pr_debug("rtasd: enabling surveillance\n");
+                               enable_surveillance(surveillance_timeout);
+                               pr_debug("rtasd: surveillance enabled\n");
+                       }
+               }
        }
+
+       schedule_delayed_work_on(cpu, &event_scan_work,
+               __round_jiffies_relative(event_scan_delay, cpu));
+
        put_online_cpus();
 }
 
-static int rtasd(void *unused)
+static void start_event_scan(void)
 {
        unsigned int err_type;
        int rc;
 
-       daemonize("rtasd");
-
        printk(KERN_DEBUG "RTAS daemon started\n");
        pr_debug("rtasd: will sleep for %d milliseconds\n",
                 (30000 / rtas_event_scan_rate));
@@ -434,22 +449,8 @@ static int rtasd(void *unused)
                }
        }
 
-       /* First pass. */
-       do_event_scan_all_cpus(1000);
-
-       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;
+       schedule_delayed_work_on(first_cpu(cpu_online_map), &event_scan_work,
+                                event_scan_delay);
 }
 
 static int __init rtas_init(void)
@@ -487,8 +488,7 @@ static int __init rtas_init(void)
        if (!entry)
                printk(KERN_ERR "Failed to create error_log proc entry\n");
 
-       if (kernel_thread(rtasd, NULL, CLONE_FS) < 0)
-               printk(KERN_ERR "Failed to start RTAS daemon\n");
+       start_event_scan();
 
        return 0;
 }