Commit 9b6695a8 authored by Ralf Baechle's avatar Ralf Baechle

[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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 3e6cb2d3
...@@ -540,6 +540,9 @@ void __init setup_arch(char **cmdline_p) ...@@ -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) ...@@ -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 = { ...@@ -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,12 +179,10 @@ void prom_prepare_cpus(unsigned int max_cpus) ...@@ -179,12 +179,10 @@ 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 */
write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE); write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
...@@ -241,7 +239,10 @@ void prom_prepare_cpus(unsigned int max_cpus) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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); ...@@ -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);
......
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