]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - kernel/smpboot.c
smp, idle: Allocate idle thread for each possible cpu during boot
[karo-tx-linux.git] / kernel / smpboot.c
index ed1576981801858a9e83185d018d716194d69084..e1a797e028a320d62c01e77a47f533e0998adaa3 100644 (file)
@@ -6,64 +6,42 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/percpu.h>
-#include <linux/workqueue.h>
 
 #include "smpboot.h"
 
 #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
-struct create_idle {
-       struct work_struct      work;
-       struct task_struct      *idle;
-       struct completion       done;
-       unsigned int cpu;
-};
-
-static void __cpuinit do_fork_idle(struct work_struct *work)
-{
-       struct create_idle *c = container_of(work, struct create_idle, work);
-
-       c->idle = fork_idle(c->cpu);
-       complete(&c->done);
-}
-
-static struct task_struct * __cpuinit idle_thread_create(unsigned int cpu)
-{
-       struct create_idle c_idle = {
-               .cpu    = cpu,
-               .done   = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
-       };
-
-       INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
-       schedule_work(&c_idle.work);
-       wait_for_completion(&c_idle.done);
-       destroy_work_on_stack(&c_idle.work);
-       return c_idle.idle;
-}
-
 /*
  * For the hotplug case we keep the task structs around and reuse
  * them.
  */
 static DEFINE_PER_CPU(struct task_struct *, idle_threads);
 
-static inline struct task_struct *get_idle_for_cpu(unsigned int cpu)
+struct task_struct * __cpuinit idle_thread_get(unsigned int cpu)
 {
        struct task_struct *tsk = per_cpu(idle_threads, cpu);
 
        if (!tsk)
-               return idle_thread_create(cpu);
+               return ERR_PTR(-ENOMEM);
        init_idle(tsk, cpu);
        return tsk;
 }
 
-struct task_struct * __cpuinit idle_thread_get(unsigned int cpu)
+void __init idle_thread_set_boot_cpu(void)
 {
-       return per_cpu(idle_threads, cpu);
+       per_cpu(idle_threads, smp_processor_id()) = current;
 }
 
-void __init idle_thread_set_boot_cpu(void)
+static inline void idle_init(unsigned int cpu)
 {
-       per_cpu(idle_threads, smp_processor_id()) = current;
+       struct task_struct *tsk = per_cpu(idle_threads, cpu);
+
+       if (!tsk) {
+               tsk = fork_idle(cpu);
+               if (IS_ERR(tsk))
+                       pr_err("SMP: fork_idle() failed for CPU %u\n", cpu);
+               else
+                       per_cpu(idle_threads, cpu) = tsk;
+       }
 }
 
 /**
@@ -72,25 +50,13 @@ void __init idle_thread_set_boot_cpu(void)
  *
  * Creates the thread if it does not exist.
  */
-static int __cpuinit idle_thread_init(unsigned int cpu)
+void __init idle_threads_init(void)
 {
-       struct task_struct *idle = get_idle_for_cpu(cpu);
+       unsigned int cpu;
 
-       if (IS_ERR(idle)) {
-               printk(KERN_ERR "failed fork for CPU %u\n", cpu);
-               return PTR_ERR(idle);
+       for_each_possible_cpu(cpu) {
+               if (cpu != smp_processor_id())
+                       idle_init(cpu);
        }
-       per_cpu(idle_threads, cpu) = idle;
-       return 0;
 }
-#else
-static inline int idle_thread_init(unsigned int cpu) { return 0; }
 #endif
-
-/**
- * smpboot_prepare - generic smpboot preparation
- */
-int __cpuinit smpboot_prepare(unsigned int cpu)
-{
-       return idle_thread_init(cpu);
-}