diff options
author | Bob Breuer <breuerr@mc.net> | 2006-03-23 22:36:19 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-23 22:36:19 -0800 |
commit | a54123e27779049d27d21e6c8adfee73aa2c0734 (patch) | |
tree | 265849e706e4ebe3b75127ebe6e3cbfe2a78850a /arch/sparc/kernel/smp.c | |
parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) |
[SPARC]: Try to start getting SMP back into shape.
Todo items:
- IRQ_INPROGRESS flag - use sparc64 irq buckets, or generic irq_desc?
- sun4d
- re-indent large chunks of sun4m_smp.c
- some places assume sequential cpu numbering (i.e. 0,1 instead of 0,2)
Last I checked (with 2.6.14), random programs segfault with dual
HyperSPARC. And with SuperSPARC II's, it seems stable but will
eventually die from a write lock error (wrong lock owner or something).
I haven't tried the HyperSPARC + highmem combination recently, so that
may still be a problem.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/smp.c')
-rw-r--r-- | arch/sparc/kernel/smp.c | 84 |
1 files changed, 63 insertions, 21 deletions
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index ea5682ce703..2be81211519 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -45,6 +45,7 @@ volatile int __cpu_logical_map[NR_CPUS]; cpumask_t cpu_online_map = CPU_MASK_NONE; cpumask_t phys_cpu_present_map = CPU_MASK_NONE; +cpumask_t smp_commenced_mask = CPU_MASK_NONE; /* The only guaranteed locking primitive available on all Sparc * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically @@ -57,11 +58,6 @@ cpumask_t phys_cpu_present_map = CPU_MASK_NONE; /* Used to make bitops atomic */ unsigned char bitops_spinlock = 0; -volatile unsigned long ipi_count; - -volatile int smp_process_available=0; -volatile int smp_commenced = 0; - void __init smp_store_cpu_info(int id) { int cpu_node; @@ -79,6 +75,22 @@ void __init smp_store_cpu_info(int id) void __init smp_cpus_done(unsigned int max_cpus) { + extern void smp4m_smp_done(void); + unsigned long bogosum = 0; + int cpu, num; + + for (cpu = 0, num = 0; cpu < NR_CPUS; cpu++) + if (cpu_online(cpu)) { + num++; + bogosum += cpu_data(cpu).udelay_val; + } + + printk("Total of %d processors activated (%lu.%02lu BogoMIPS).\n", + num, bogosum/(500000/HZ), + (bogosum/(5000/HZ))%100); + + BUG_ON(sparc_cpu_model != sun4m); + smp4m_smp_done(); } void cpu_panic(void) @@ -89,17 +101,6 @@ void cpu_panic(void) struct linux_prom_registers smp_penguin_ctable __initdata = { 0 }; -void __init smp_boot_cpus(void) -{ - extern void smp4m_boot_cpus(void); - extern void smp4d_boot_cpus(void); - - if (sparc_cpu_model == sun4m) - smp4m_boot_cpus(); - else - smp4d_boot_cpus(); -} - void smp_send_reschedule(int cpu) { /* See sparc64 */ @@ -252,20 +253,61 @@ int setup_profiling_timer(unsigned int multiplier) return 0; } -void __init smp_prepare_cpus(unsigned int maxcpus) +void __init smp_prepare_cpus(unsigned int max_cpus) { + extern void smp4m_boot_cpus(void); + int i, cpuid, ncpus, extra; + + BUG_ON(sparc_cpu_model != sun4m); + printk("Entering SMP Mode...\n"); + + ncpus = 1; + extra = 0; + for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) { + if (cpuid == boot_cpu_id) + continue; + if (cpuid < NR_CPUS && ncpus++ < max_cpus) + cpu_set(cpuid, phys_cpu_present_map); + else + extra++; + } + if (max_cpus >= NR_CPUS && extra) + printk("Warning: NR_CPUS is too low to start all cpus\n"); + + smp_store_cpu_info(boot_cpu_id); + + smp4m_boot_cpus(); } void __devinit smp_prepare_boot_cpu(void) { - current_thread_info()->cpu = hard_smp_processor_id(); - cpu_set(smp_processor_id(), cpu_online_map); - cpu_set(smp_processor_id(), phys_cpu_present_map); + int cpuid = hard_smp_processor_id(); + + if (cpuid >= NR_CPUS) { + prom_printf("Serious problem, boot cpu id >= NR_CPUS\n"); + prom_halt(); + } + if (cpuid != 0) + printk("boot cpu id != 0, this could work but is untested\n"); + + current_thread_info()->cpu = cpuid; + cpu_set(cpuid, cpu_online_map); + cpu_set(cpuid, phys_cpu_present_map); } int __devinit __cpu_up(unsigned int cpu) { - panic("smp doesn't work\n"); + extern int smp4m_boot_one_cpu(int); + int ret; + + ret = smp4m_boot_one_cpu(cpu); + + if (!ret) { + cpu_set(cpu, smp_commenced_mask); + while (!cpu_online(cpu)) + mb(); + } + return ret; } void smp_bogo(struct seq_file *m) |