Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+7 −10
Original line number Diff line number Diff line
@@ -52,8 +52,6 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */

void __cpuinit platform_secondary_init(unsigned int cpu)
{
	local_irq_disable();

	/* Clone setup for peripheral interrupt sources from CoreA. */
	bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
	bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
@@ -70,11 +68,6 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
	bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
	SSYNC();

	local_irq_enable();

	/* Calibrate loops per jiffy value. */
	calibrate_delay();

	/* Store CPU-private information to the cpu_data array. */
	bfin_setup_cpudata(cpu);

@@ -108,9 +101,13 @@ int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle
		barrier();
	}

	if (cpu_isset(cpu, cpu_callin_map)) {
		cpu_set(cpu, cpu_online_map);
		/* release the lock and let coreb run */
		spin_unlock(&boot_lock);

	return cpu_isset(cpu, cpu_callin_map) ? 0 : -ENOSYS;
		return 0;
	} else
		panic("CPU%u: processor failed to boot\n", cpu);
}

void __init platform_request_ipi(irq_handler_t handler)
+8 −8
Original line number Diff line number Diff line
@@ -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();
}