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-common/smp.c | |
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-common/smp.c')
-rw-r--r-- | arch/blackfin/mach-common/smp.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index d92b168c8328..369e687582b7 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c | |||
@@ -336,13 +336,6 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
336 | 336 | ||
337 | ret = platform_boot_secondary(cpu, idle); | 337 | ret = platform_boot_secondary(cpu, idle); |
338 | 338 | ||
339 | if (ret) { | ||
340 | cpu_clear(cpu, cpu_present_map); | ||
341 | printk(KERN_CRIT "CPU%u: processor failed to boot (%d)\n", cpu, ret); | ||
342 | free_task(idle); | ||
343 | } else | ||
344 | cpu_set(cpu, cpu_online_map); | ||
345 | |||
346 | secondary_stack = NULL; | 339 | secondary_stack = NULL; |
347 | 340 | ||
348 | return ret; | 341 | return ret; |
@@ -418,9 +411,16 @@ void __cpuinit secondary_start_kernel(void) | |||
418 | 411 | ||
419 | setup_secondary(cpu); | 412 | setup_secondary(cpu); |
420 | 413 | ||
414 | platform_secondary_init(cpu); | ||
415 | |||
421 | local_irq_enable(); | 416 | local_irq_enable(); |
422 | 417 | ||
423 | platform_secondary_init(cpu); | 418 | /* |
419 | * Calibrate loops per jiffy value. | ||
420 | * IRQs need to be enabled here - D-cache can be invalidated | ||
421 | * in timer irq handler, so core B can read correct jiffies. | ||
422 | */ | ||
423 | calibrate_delay(); | ||
424 | 424 | ||
425 | cpu_idle(); | 425 | cpu_idle(); |
426 | } | 426 | } |