diff options
author | Yi Li <yi.li@analog.com> | 2009-12-02 02:58:12 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-12-15 00:16:09 -0500 |
commit | 578d36f5e160208821e8f51037ac1038e065ecaf (patch) | |
tree | 6b1da0d6e7108c0bd217b132e165f2d06007fef8 /arch/blackfin/mach-bf561 | |
parent | ad774b7cb0604d02c3596b79921fcb812df4dc71 (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.c | 17 |
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 | ||
53 | void __cpuinit platform_secondary_init(unsigned int cpu) | 53 | void __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 | ||
116 | void __init platform_request_ipi(irq_handler_t handler) | 113 | void __init platform_request_ipi(irq_handler_t handler) |