diff options
-rw-r--r-- | arch/powerpc/kernel/machine_kexec_64.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index a0bcec3614e1..583af70c4b14 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init_task.h> | 16 | #include <linux/init_task.h> |
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/cpu.h> | ||
19 | 20 | ||
20 | #include <asm/page.h> | 21 | #include <asm/page.h> |
21 | #include <asm/current.h> | 22 | #include <asm/current.h> |
@@ -216,9 +217,32 @@ static void kexec_prepare_cpus_wait(int wait_state) | |||
216 | mb(); | 217 | mb(); |
217 | } | 218 | } |
218 | 219 | ||
219 | static void kexec_prepare_cpus(void) | 220 | /* |
221 | * We need to make sure each present CPU is online. The next kernel will scan | ||
222 | * the device tree and assume primary threads are online and query secondary | ||
223 | * threads via RTAS to online them if required. If we don't online primary | ||
224 | * threads, they will be stuck. However, we also online secondary threads as we | ||
225 | * may be using 'cede offline'. In this case RTAS doesn't see the secondary | ||
226 | * threads as offline -- and again, these CPUs will be stuck. | ||
227 | * | ||
228 | * So, we online all CPUs that should be running, including secondary threads. | ||
229 | */ | ||
230 | static void wake_offline_cpus(void) | ||
220 | { | 231 | { |
232 | int cpu = 0; | ||
233 | |||
234 | for_each_present_cpu(cpu) { | ||
235 | if (!cpu_online(cpu)) { | ||
236 | printk(KERN_INFO "kexec: Waking offline cpu %d.\n", | ||
237 | cpu); | ||
238 | cpu_up(cpu); | ||
239 | } | ||
240 | } | ||
241 | } | ||
221 | 242 | ||
243 | static void kexec_prepare_cpus(void) | ||
244 | { | ||
245 | wake_offline_cpus(); | ||
222 | smp_call_function(kexec_smp_down, NULL, /* wait */0); | 246 | smp_call_function(kexec_smp_down, NULL, /* wait */0); |
223 | local_irq_disable(); | 247 | local_irq_disable(); |
224 | mb(); /* make sure IRQs are disabled before we say they are */ | 248 | mb(); /* make sure IRQs are disabled before we say they are */ |