]> Pileus Git - ~andy/linux/blobdiff - arch/sparc/kernel/smp_32.c
sparc32: refactor smp boot
[~andy/linux] / arch / sparc / kernel / smp_32.c
index 79db45e5134a6df24de2805a597cc35c3b3cc347..9e7e6d718367b18ddc2fe1c354e7509c6c524384 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/seq_file.h>
 #include <linux/cache.h>
 #include <linux/delay.h>
+#include <linux/cpu.h>
 
 #include <asm/ptrace.h>
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/cpudata.h>
+#include <asm/timer.h>
 #include <asm/leon.h>
 
+#include "kernel.h"
 #include "irq.h"
 
 volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
@@ -294,6 +297,89 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
        return ret;
 }
 
+void __cpuinit arch_cpu_pre_starting(void *arg)
+{
+       local_ops->cache_all();
+       local_ops->tlb_all();
+
+       switch(sparc_cpu_model) {
+       case sun4m:
+               sun4m_cpu_pre_starting(arg);
+               break;
+       case sun4d:
+               sun4d_cpu_pre_starting(arg);
+               break;
+       case sparc_leon:
+               leon_cpu_pre_starting(arg);
+               break;
+       default:
+               BUG();
+       }
+}
+
+void __cpuinit arch_cpu_pre_online(void *arg)
+{
+       unsigned int cpuid = hard_smp_processor_id();
+
+       register_percpu_ce(cpuid);
+
+       calibrate_delay();
+       smp_store_cpu_info(cpuid);
+
+       local_ops->cache_all();
+       local_ops->tlb_all();
+
+       switch(sparc_cpu_model) {
+       case sun4m:
+               sun4m_cpu_pre_online(arg);
+               break;
+       case sun4d:
+               sun4d_cpu_pre_online(arg);
+               break;
+       case sparc_leon:
+               leon_cpu_pre_online(arg);
+               break;
+       default:
+               BUG();
+       }
+}
+
+void __cpuinit sparc_start_secondary(void *arg)
+{
+       unsigned int cpu;
+
+       /*
+        * SMP booting is extremely fragile in some architectures. So run
+        * the cpu initialization code first before anything else.
+        */
+       arch_cpu_pre_starting(arg);
+
+       preempt_disable();
+       cpu = smp_processor_id();
+
+       /* Invoke the CPU_STARTING notifier callbacks */
+       notify_cpu_starting(cpu);
+
+       arch_cpu_pre_online(arg);
+
+       /* Set the CPU in the cpu_online_mask */
+       set_cpu_online(cpu, true);
+
+       /* Enable local interrupts now */
+       local_irq_enable();
+
+       wmb();
+       cpu_idle();
+
+       /* We should never reach here! */
+       BUG();
+}
+
+void __cpuinit smp_callin(void)
+{
+       sparc_start_secondary(NULL);
+}
+
 void smp_bogo(struct seq_file *m)
 {
        int i;