summaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common
diff options
context:
space:
mode:
authorYi Li <yi.li@analog.com>2009-12-02 07:58:12 +0000
committerMike Frysinger <vapier@gentoo.org>2009-12-15 00:16:09 -0500
commit578d36f5e160208821e8f51037ac1038e065ecaf (patch)
tree6b1da0d6e7108c0bd217b132e165f2d06007fef8 /arch/blackfin/mach-common
parentad774b7cb0604d02c3596b79921fcb812df4dc71 (diff)
downloadlinux-578d36f5e160208821e8f51037ac1038e065ecaf.tar.gz
linux-578d36f5e160208821e8f51037ac1038e065ecaf.tar.bz2
linux-578d36f5e160208821e8f51037ac1038e065ecaf.zip
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')
-rw-r--r--arch/blackfin/mach-common/smp.c16
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)
ret = platform_boot_secondary(cpu, idle);
- if (ret) {
- cpu_clear(cpu, cpu_present_map);
- printk(KERN_CRIT "CPU%u: processor failed to boot (%d)\n", cpu, ret);
- free_task(idle);
- } else
- cpu_set(cpu, cpu_online_map);
-
secondary_stack = NULL;
return ret;
@@ -418,9 +411,16 @@ void __cpuinit secondary_start_kernel(void)
setup_secondary(cpu);
+ platform_secondary_init(cpu);
+
local_irq_enable();
- platform_secondary_init(cpu);
+ /*
+ * Calibrate loops per jiffy value.
+ * IRQs need to be enabled here - D-cache can be invalidated
+ * in timer irq handler, so core B can read correct jiffies.
+ */
+ calibrate_delay();
cpu_idle();
}