[MIPS] SMP: Fix initialization order bug.
A recent change requires cpu_possible_map to be initialized before smp_sched_init() but most MIPS platforms were initializing their processors in the prom_prepare_cpus callback of smp_prepare_cpus. The simple fix of calling prom_prepare_cpus from one of the earlier SMP initialization hooks doesn't work well either since IPIs may require init_IRQ() to have completed, so bit the bullet and split prom_prepare_cpus into two initialization functions, plat_smp_setup which is called early from setup_arch and plat_prepare_cpus called where prom_prepare_cpus used to be called. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
3e6cb2d38a
commit
9b6695a8ad
|
@ -540,6 +540,9 @@ void __init setup_arch(char **cmdline_p)
|
||||||
sparse_init();
|
sparse_init();
|
||||||
paging_init();
|
paging_init();
|
||||||
resource_init();
|
resource_init();
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
plat_smp_setup();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init fpu_disable(char *s)
|
int __init fpu_disable(char *s)
|
||||||
|
|
|
@ -236,7 +236,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||||
init_new_context(current, &init_mm);
|
init_new_context(current, &init_mm);
|
||||||
current_thread_info()->cpu = 0;
|
current_thread_info()->cpu = 0;
|
||||||
smp_tune_scheduling();
|
smp_tune_scheduling();
|
||||||
prom_prepare_cpus(max_cpus);
|
plat_prepare_cpus(max_cpus);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* preload SMP state for boot cpu */
|
/* preload SMP state for boot cpu */
|
||||||
|
|
|
@ -143,7 +143,7 @@ static struct irqaction irq_call = {
|
||||||
* Make sure all CPU's are in a sensible state before we boot any of the
|
* Make sure all CPU's are in a sensible state before we boot any of the
|
||||||
* secondarys
|
* secondarys
|
||||||
*/
|
*/
|
||||||
void prom_prepare_cpus(unsigned int max_cpus)
|
void plat_smp_setup(void)
|
||||||
{
|
{
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
int i, num;
|
int i, num;
|
||||||
|
@ -179,11 +179,9 @@ void prom_prepare_cpus(unsigned int max_cpus)
|
||||||
write_vpe_c0_vpeconf0(tmp);
|
write_vpe_c0_vpeconf0(tmp);
|
||||||
|
|
||||||
/* Record this as available CPU */
|
/* Record this as available CPU */
|
||||||
if (i < max_cpus) {
|
cpu_set(i, phys_cpu_present_map);
|
||||||
cpu_set(i, phys_cpu_present_map);
|
__cpu_number_map[i] = ++num;
|
||||||
__cpu_number_map[i] = ++num;
|
__cpu_logical_map[num] = i;
|
||||||
__cpu_logical_map[num] = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable multi-threading with TC's */
|
/* disable multi-threading with TC's */
|
||||||
|
@ -241,7 +239,10 @@ void prom_prepare_cpus(unsigned int max_cpus)
|
||||||
set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
|
set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
|
||||||
set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
|
set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init plat_prepare_cpus(unsigned int max_cpus)
|
||||||
|
{
|
||||||
cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
|
cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
|
||||||
cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
|
cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
|
||||||
|
|
||||||
|
|
|
@ -50,37 +50,25 @@ void __init prom_grab_secondary(void)
|
||||||
* We don't want to start the secondary CPU yet nor do we have a nice probing
|
* We don't want to start the secondary CPU yet nor do we have a nice probing
|
||||||
* feature in PMON so we just assume presence of the secondary core.
|
* feature in PMON so we just assume presence of the secondary core.
|
||||||
*/
|
*/
|
||||||
static char maxcpus_string[] __initdata =
|
void __init plat_smp_setup(void)
|
||||||
KERN_WARNING "max_cpus set to 0; using 1 instead\n";
|
|
||||||
|
|
||||||
void __init prom_prepare_cpus(unsigned int max_cpus)
|
|
||||||
{
|
{
|
||||||
int enabled = 0, i;
|
int i;
|
||||||
|
|
||||||
if (max_cpus == 0) {
|
|
||||||
printk(maxcpus_string);
|
|
||||||
max_cpus = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpus_clear(phys_cpu_present_map);
|
cpus_clear(phys_cpu_present_map);
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
if (i == max_cpus)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The boot CPU
|
|
||||||
*/
|
|
||||||
cpu_set(i, phys_cpu_present_map);
|
cpu_set(i, phys_cpu_present_map);
|
||||||
__cpu_number_map[i] = i;
|
__cpu_number_map[i] = i;
|
||||||
__cpu_logical_map[i] = i;
|
__cpu_logical_map[i] = i;
|
||||||
enabled++;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init plat_prepare_cpus(unsigned int max_cpus)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Be paranoid. Enable the IPI only if we're really about to go SMP.
|
* Be paranoid. Enable the IPI only if we're really about to go SMP.
|
||||||
*/
|
*/
|
||||||
if (enabled > 1)
|
if (cpus_weight(cpu_possible_map))
|
||||||
set_c0_status(STATUSF_IP5);
|
set_c0_status(STATUSF_IP5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ static __init void intr_clear_all(nasid_t nasid)
|
||||||
REMOTE_HUB_CLR_INTR(nasid, i);
|
REMOTE_HUB_CLR_INTR(nasid, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init prom_prepare_cpus(unsigned int max_cpus)
|
void __init plat_smp_setup(void)
|
||||||
{
|
{
|
||||||
cnodeid_t cnode;
|
cnodeid_t cnode;
|
||||||
|
|
||||||
|
@ -161,6 +161,11 @@ void __init prom_prepare_cpus(unsigned int max_cpus)
|
||||||
alloc_cpupda(0, 0);
|
alloc_cpupda(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init plat_prepare_cpus(unsigned int max_cpus)
|
||||||
|
{
|
||||||
|
/* We already did everything necessary earlier */
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Launch a slave into smp_bootstrap(). It doesn't take an argument, and we
|
* Launch a slave into smp_bootstrap(). It doesn't take an argument, and we
|
||||||
* set sp to the kernel stack of the newly created idle process, gp to the proc
|
* set sp to the kernel stack of the newly created idle process, gp to the proc
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
*
|
*
|
||||||
* Common setup before any secondaries are started
|
* Common setup before any secondaries are started
|
||||||
*/
|
*/
|
||||||
void __init prom_prepare_cpus(unsigned int max_cpus)
|
void __init plat_smp_setup(void)
|
||||||
{
|
{
|
||||||
int i, num;
|
int i, num;
|
||||||
|
|
||||||
|
@ -40,14 +40,18 @@ void __init prom_prepare_cpus(unsigned int max_cpus)
|
||||||
__cpu_number_map[0] = 0;
|
__cpu_number_map[0] = 0;
|
||||||
__cpu_logical_map[0] = 0;
|
__cpu_logical_map[0] = 0;
|
||||||
|
|
||||||
for (i=1, num=0; i<NR_CPUS; i++) {
|
for (i = 1, num = 0; i < NR_CPUS; i++) {
|
||||||
if (cfe_cpu_stop(i) == 0) {
|
if (cfe_cpu_stop(i) == 0) {
|
||||||
cpu_set(i, phys_cpu_present_map);
|
cpu_set(i, phys_cpu_present_map);
|
||||||
__cpu_number_map[i] = ++num;
|
__cpu_number_map[i] = ++num;
|
||||||
__cpu_logical_map[num] = i;
|
__cpu_logical_map[num] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printk("Detected %i available secondary CPU(s)\n", num);
|
printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init plat_prepare_cpus(unsigned int max_cpus)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -58,7 +58,9 @@ static inline int num_booting_cpus(void)
|
||||||
return cpus_weight(cpu_callout_map);
|
return cpus_weight(cpu_callout_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These are defined by the board-specific code. */
|
/*
|
||||||
|
* These are defined by the board-specific code.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cause the function described by call_data to be executed on the passed
|
* Cause the function described by call_data to be executed on the passed
|
||||||
|
@ -79,7 +81,12 @@ extern void prom_boot_secondary(int cpu, struct task_struct *idle);
|
||||||
extern void prom_init_secondary(void);
|
extern void prom_init_secondary(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detect available CPUs, populate phys_cpu_present_map before smp_init
|
* Populate cpu_possible_map before smp_init, called from setup_arch.
|
||||||
|
*/
|
||||||
|
extern void plat_smp_setup(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called after init_IRQ but before __cpu_up.
|
||||||
*/
|
*/
|
||||||
extern void prom_prepare_cpus(unsigned int max_cpus);
|
extern void prom_prepare_cpus(unsigned int max_cpus);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue