aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c26
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
219static 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 */
230static 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
243static 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 */