aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-bf561
diff options
context:
space:
mode:
authorYi Li <yi.li@analog.com>2009-12-02 02:58:12 -0500
committerMike Frysinger <vapier@gentoo.org>2009-12-15 00:16:09 -0500
commit578d36f5e160208821e8f51037ac1038e065ecaf (patch)
tree6b1da0d6e7108c0bd217b132e165f2d06007fef8 /arch/blackfin/mach-bf561
parentad774b7cb0604d02c3596b79921fcb812df4dc71 (diff)
Blackfin: SMP: don't start up core b until its state has been completely onlined
When testing PREEMPT_RT kernel on BF561-EZKit, the kernel blocks while booting. When the kernel initializes the ethernet driver, it sleeps and never wakes up. The issue happens when the kernel waits for a timer for Core B to timeout (the timers are per-cpu based: static DEFINE_PER_CPU(struct tvec_base *, tvec_bases) = &boot_tvec_bases). However, the ksoftirqd thread for Core B (note, the ksoftirqd thread is also per-cpu based) cannot work properly, and the timers for Core B never times out. When ksoftirqd() for the first time runs on core B, it is possible core A is still initializing core B (see smp_init() -> cpu_up() -> __cpu_up()). So the "cpu_is_offline()" check may return true and ksoftirqd moves to "wait_to_die". So delay the core b start up until the per-cpu timers have been set up fully. Signed-off-by: Yi Li <yi.li@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/mach-bf561')
-rw-r--r--arch/blackfin/mach-bf561/smp.c17
1 files changed, 7 insertions, 10 deletions
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c
index 510f57641495..0192532e96a2 100644
--- a/arch/blackfin/mach-bf561/smp.c
+++ b/arch/blackfin/mach-bf561/smp.c
@@ -52,8 +52,6 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
52 52
53void __cpuinit platform_secondary_init(unsigned int cpu) 53void __cpuinit platform_secondary_init(unsigned int cpu)
54{ 54{
55 local_irq_disable();
56
57 /* Clone setup for peripheral interrupt sources from CoreA. */ 55 /* Clone setup for peripheral interrupt sources from CoreA. */
58 bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0()); 56 bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
59 bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1()); 57 bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
@@ -70,11 +68,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
70 bfin_write_SICB_IAR7(bfin_read_SICA_IAR7()); 68 bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
71 SSYNC(); 69 SSYNC();
72 70
73 local_irq_enable();
74
75 /* Calibrate loops per jiffy value. */
76 calibrate_delay();
77
78 /* Store CPU-private information to the cpu_data array. */ 71 /* Store CPU-private information to the cpu_data array. */
79 bfin_setup_cpudata(cpu); 72 bfin_setup_cpudata(cpu);
80 73
@@ -108,9 +101,13 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle
108 barrier(); 101 barrier();
109 } 102 }
110 103
111 spin_unlock(&boot_lock); 104 if (cpu_isset(cpu, cpu_callin_map)) {
112 105 cpu_set(cpu, cpu_online_map);
113 return cpu_isset(cpu, cpu_callin_map) ? 0 : -ENOSYS; 106 /* release the lock and let coreb run */
107 spin_unlock(&boot_lock);
108 return 0;
109 } else
110 panic("CPU%u: processor failed to boot\n", cpu);
114} 111}
115 112
116void __init platform_request_ipi(irq_handler_t handler) 113void __init platform_request_ipi(irq_handler_t handler)