diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/machine_kexec_64.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 040bd1de8d9..1a8de63489a 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -15,6 +15,7 @@ #include <linux/thread_info.h> #include <linux/init_task.h> #include <linux/errno.h> +#include <linux/cpu.h> #include <asm/page.h> #include <asm/current.h> @@ -169,10 +170,34 @@ static void kexec_smp_down(void *arg) /* NOTREACHED */ } +/* + * We need to make sure each present CPU is online. The next kernel will scan + * the device tree and assume primary threads are online and query secondary + * threads via RTAS to online them if required. If we don't online primary + * threads, they will be stuck. However, we also online secondary threads as we + * may be using 'cede offline'. In this case RTAS doesn't see the secondary + * threads as offline -- and again, these CPUs will be stuck. + * + * So, we online all CPUs that should be running, including secondary threads. + */ +static void wake_offline_cpus(void) +{ + int cpu = 0; + + for_each_present_cpu(cpu) { + if (!cpu_online(cpu)) { + printk(KERN_INFO "kexec: Waking offline cpu %d.\n", + cpu); + cpu_up(cpu); + } + } +} + static void kexec_prepare_cpus(void) { int my_cpu, i, notified=-1; + wake_offline_cpus(); smp_call_function(kexec_smp_down, NULL, /* wait */0); my_cpu = get_cpu(); |