diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2006-02-23 07:23:27 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-02-27 12:30:36 -0500 |
commit | 9b6695a8adfe0916e81ddd810a5b9db3eb8b0e46 (patch) | |
tree | 62ba9475530c88ccf2149cd58eabd97ebe096aca | |
parent | 3e6cb2d38a9c9758170813497a860c64543643d5 (diff) |
[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>
-rw-r--r-- | arch/mips/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/smp_mt.c | 13 | ||||
-rw-r--r-- | arch/mips/pmc-sierra/yosemite/smp.c | 24 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-smp.c | 7 | ||||
-rw-r--r-- | arch/mips/sibyte/cfe/smp.c | 10 | ||||
-rw-r--r-- | include/asm-mips/smp.h | 11 |
7 files changed, 39 insertions, 31 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index d86affa21278..d9293c558e41 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
@@ -540,6 +540,9 @@ void __init setup_arch(char **cmdline_p) | |||
540 | sparse_init(); | 540 | sparse_init(); |
541 | paging_init(); | 541 | paging_init(); |
542 | resource_init(); | 542 | resource_init(); |
543 | #ifdef CONFIG_SMP | ||
544 | plat_smp_setup(); | ||
545 | #endif | ||
543 | } | 546 | } |
544 | 547 | ||
545 | int __init fpu_disable(char *s) | 548 | int __init fpu_disable(char *s) |
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 5e189862e523..06ed90752424 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -236,7 +236,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
236 | init_new_context(current, &init_mm); | 236 | init_new_context(current, &init_mm); |
237 | current_thread_info()->cpu = 0; | 237 | current_thread_info()->cpu = 0; |
238 | smp_tune_scheduling(); | 238 | smp_tune_scheduling(); |
239 | prom_prepare_cpus(max_cpus); | 239 | plat_prepare_cpus(max_cpus); |
240 | } | 240 | } |
241 | 241 | ||
242 | /* preload SMP state for boot cpu */ | 242 | /* preload SMP state for boot cpu */ |
diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp_mt.c index c930364830d0..993b8bf56aaf 100644 --- a/arch/mips/kernel/smp_mt.c +++ b/arch/mips/kernel/smp_mt.c | |||
@@ -143,7 +143,7 @@ static struct irqaction irq_call = { | |||
143 | * Make sure all CPU's are in a sensible state before we boot any of the | 143 | * Make sure all CPU's are in a sensible state before we boot any of the |
144 | * secondarys | 144 | * secondarys |
145 | */ | 145 | */ |
146 | void prom_prepare_cpus(unsigned int max_cpus) | 146 | void plat_smp_setup(void) |
147 | { | 147 | { |
148 | unsigned long val; | 148 | unsigned long val; |
149 | int i, num; | 149 | int i, num; |
@@ -179,11 +179,9 @@ void prom_prepare_cpus(unsigned int max_cpus) | |||
179 | write_vpe_c0_vpeconf0(tmp); | 179 | write_vpe_c0_vpeconf0(tmp); |
180 | 180 | ||
181 | /* Record this as available CPU */ | 181 | /* Record this as available CPU */ |
182 | if (i < max_cpus) { | 182 | cpu_set(i, phys_cpu_present_map); |
183 | cpu_set(i, phys_cpu_present_map); | 183 | __cpu_number_map[i] = ++num; |
184 | __cpu_number_map[i] = ++num; | 184 | __cpu_logical_map[num] = i; |
185 | __cpu_logical_map[num] = i; | ||
186 | } | ||
187 | } | 185 | } |
188 | 186 | ||
189 | /* disable multi-threading with TC's */ | 187 | /* disable multi-threading with TC's */ |
@@ -241,7 +239,10 @@ void prom_prepare_cpus(unsigned int max_cpus) | |||
241 | set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); | 239 | set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); |
242 | set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); | 240 | set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); |
243 | } | 241 | } |
242 | } | ||
244 | 243 | ||
244 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
245 | { | ||
245 | cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ; | 246 | cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ; |
246 | cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ; | 247 | cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ; |
247 | 248 | ||
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index 7f8fda962190..c197311e15d3 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c | |||
@@ -50,37 +50,25 @@ void __init prom_grab_secondary(void) | |||
50 | * We don't want to start the secondary CPU yet nor do we have a nice probing | 50 | * We don't want to start the secondary CPU yet nor do we have a nice probing |
51 | * feature in PMON so we just assume presence of the secondary core. | 51 | * feature in PMON so we just assume presence of the secondary core. |
52 | */ | 52 | */ |
53 | static char maxcpus_string[] __initdata = | 53 | void __init plat_smp_setup(void) |
54 | KERN_WARNING "max_cpus set to 0; using 1 instead\n"; | ||
55 | |||
56 | void __init prom_prepare_cpus(unsigned int max_cpus) | ||
57 | { | 54 | { |
58 | int enabled = 0, i; | 55 | int i; |
59 | |||
60 | if (max_cpus == 0) { | ||
61 | printk(maxcpus_string); | ||
62 | max_cpus = 1; | ||
63 | } | ||
64 | 56 | ||
65 | cpus_clear(phys_cpu_present_map); | 57 | cpus_clear(phys_cpu_present_map); |
66 | 58 | ||
67 | for (i = 0; i < 2; i++) { | 59 | for (i = 0; i < 2; i++) { |
68 | if (i == max_cpus) | ||
69 | break; | ||
70 | |||
71 | /* | ||
72 | * The boot CPU | ||
73 | */ | ||
74 | cpu_set(i, phys_cpu_present_map); | 60 | cpu_set(i, phys_cpu_present_map); |
75 | __cpu_number_map[i] = i; | 61 | __cpu_number_map[i] = i; |
76 | __cpu_logical_map[i] = i; | 62 | __cpu_logical_map[i] = i; |
77 | enabled++; | ||
78 | } | 63 | } |
64 | } | ||
79 | 65 | ||
66 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
67 | { | ||
80 | /* | 68 | /* |
81 | * Be paranoid. Enable the IPI only if we're really about to go SMP. | 69 | * Be paranoid. Enable the IPI only if we're really about to go SMP. |
82 | */ | 70 | */ |
83 | if (enabled > 1) | 71 | if (cpus_weight(cpu_possible_map)) |
84 | set_c0_status(STATUSF_IP5); | 72 | set_c0_status(STATUSF_IP5); |
85 | } | 73 | } |
86 | 74 | ||
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index dbef3f6b5650..09fa7f5216f0 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c | |||
@@ -140,7 +140,7 @@ static __init void intr_clear_all(nasid_t nasid) | |||
140 | REMOTE_HUB_CLR_INTR(nasid, i); | 140 | REMOTE_HUB_CLR_INTR(nasid, i); |
141 | } | 141 | } |
142 | 142 | ||
143 | void __init prom_prepare_cpus(unsigned int max_cpus) | 143 | void __init plat_smp_setup(void) |
144 | { | 144 | { |
145 | cnodeid_t cnode; | 145 | cnodeid_t cnode; |
146 | 146 | ||
@@ -161,6 +161,11 @@ void __init prom_prepare_cpus(unsigned int max_cpus) | |||
161 | alloc_cpupda(0, 0); | 161 | alloc_cpupda(0, 0); |
162 | } | 162 | } |
163 | 163 | ||
164 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
165 | { | ||
166 | /* We already did everything necessary earlier */ | ||
167 | } | ||
168 | |||
164 | /* | 169 | /* |
165 | * Launch a slave into smp_bootstrap(). It doesn't take an argument, and we | 170 | * Launch a slave into smp_bootstrap(). It doesn't take an argument, and we |
166 | * set sp to the kernel stack of the newly created idle process, gp to the proc | 171 | * set sp to the kernel stack of the newly created idle process, gp to the proc |
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c index 4477af3d8074..eab20e2db323 100644 --- a/arch/mips/sibyte/cfe/smp.c +++ b/arch/mips/sibyte/cfe/smp.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * | 31 | * |
32 | * Common setup before any secondaries are started | 32 | * Common setup before any secondaries are started |
33 | */ | 33 | */ |
34 | void __init prom_prepare_cpus(unsigned int max_cpus) | 34 | void __init plat_smp_setup(void) |
35 | { | 35 | { |
36 | int i, num; | 36 | int i, num; |
37 | 37 | ||
@@ -40,14 +40,18 @@ void __init prom_prepare_cpus(unsigned int max_cpus) | |||
40 | __cpu_number_map[0] = 0; | 40 | __cpu_number_map[0] = 0; |
41 | __cpu_logical_map[0] = 0; | 41 | __cpu_logical_map[0] = 0; |
42 | 42 | ||
43 | for (i=1, num=0; i<NR_CPUS; i++) { | 43 | for (i = 1, num = 0; i < NR_CPUS; i++) { |
44 | if (cfe_cpu_stop(i) == 0) { | 44 | if (cfe_cpu_stop(i) == 0) { |
45 | cpu_set(i, phys_cpu_present_map); | 45 | cpu_set(i, phys_cpu_present_map); |
46 | __cpu_number_map[i] = ++num; | 46 | __cpu_number_map[i] = ++num; |
47 | __cpu_logical_map[num] = i; | 47 | __cpu_logical_map[num] = i; |
48 | } | 48 | } |
49 | } | 49 | } |
50 | printk("Detected %i available secondary CPU(s)\n", num); | 50 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); |
51 | } | ||
52 | |||
53 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
54 | { | ||
51 | } | 55 | } |
52 | 56 | ||
53 | /* | 57 | /* |
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h index 5618f1e12f40..75c6fe7c2126 100644 --- a/include/asm-mips/smp.h +++ b/include/asm-mips/smp.h | |||
@@ -58,7 +58,9 @@ static inline int num_booting_cpus(void) | |||
58 | return cpus_weight(cpu_callout_map); | 58 | return cpus_weight(cpu_callout_map); |
59 | } | 59 | } |
60 | 60 | ||
61 | /* These are defined by the board-specific code. */ | 61 | /* |
62 | * These are defined by the board-specific code. | ||
63 | */ | ||
62 | 64 | ||
63 | /* | 65 | /* |
64 | * Cause the function described by call_data to be executed on the passed | 66 | * 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 | extern void prom_init_secondary(void); | 81 | extern void prom_init_secondary(void); |
80 | 82 | ||
81 | /* | 83 | /* |
82 | * Detect available CPUs, populate phys_cpu_present_map before smp_init | 84 | * Populate cpu_possible_map before smp_init, called from setup_arch. |
85 | */ | ||
86 | extern void plat_smp_setup(void); | ||
87 | |||
88 | /* | ||
89 | * Called after init_IRQ but before __cpu_up. | ||
83 | */ | 90 | */ |
84 | extern void prom_prepare_cpus(unsigned int max_cpus); | 91 | extern void prom_prepare_cpus(unsigned int max_cpus); |
85 | 92 | ||