Commit 578d36f5 authored by Yi Li's avatar Yi Li Committed by Mike Frysinger

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: default avatarYi Li <yi.li@analog.com>
Signed-off-by: default avatarMike Frysinger <vapier@gentoo.org>
parent ad774b7c
...@@ -52,8 +52,6 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */ ...@@ -52,8 +52,6 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
void __cpuinit platform_secondary_init(unsigned int cpu) void __cpuinit platform_secondary_init(unsigned int cpu)
{ {
local_irq_disable();
/* Clone setup for peripheral interrupt sources from CoreA. */ /* Clone setup for peripheral interrupt sources from CoreA. */
bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0()); bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1()); bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
...@@ -70,11 +68,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu) ...@@ -70,11 +68,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
bfin_write_SICB_IAR7(bfin_read_SICA_IAR7()); bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
SSYNC(); SSYNC();
local_irq_enable();
/* Calibrate loops per jiffy value. */
calibrate_delay();
/* Store CPU-private information to the cpu_data array. */ /* Store CPU-private information to the cpu_data array. */
bfin_setup_cpudata(cpu); bfin_setup_cpudata(cpu);
...@@ -108,9 +101,13 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle ...@@ -108,9 +101,13 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle
barrier(); barrier();
} }
spin_unlock(&boot_lock); if (cpu_isset(cpu, cpu_callin_map)) {
cpu_set(cpu, cpu_online_map);
return cpu_isset(cpu, cpu_callin_map) ? 0 : -ENOSYS; /* release the lock and let coreb run */
spin_unlock(&boot_lock);
return 0;
} else
panic("CPU%u: processor failed to boot\n", cpu);
} }
void __init platform_request_ipi(irq_handler_t handler) void __init platform_request_ipi(irq_handler_t handler)
......
...@@ -336,13 +336,6 @@ int __cpuinit __cpu_up(unsigned int cpu) ...@@ -336,13 +336,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
ret = platform_boot_secondary(cpu, idle); 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; secondary_stack = NULL;
return ret; return ret;
...@@ -418,9 +411,16 @@ void __cpuinit secondary_start_kernel(void) ...@@ -418,9 +411,16 @@ void __cpuinit secondary_start_kernel(void)
setup_secondary(cpu); setup_secondary(cpu);
platform_secondary_init(cpu);
local_irq_enable(); 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(); cpu_idle();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment