#include <linux/init_task.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
+#include <linux/cpu.h>
 
 #include <asm/page.h>
 #include <asm/current.h>
        mb();
 }
 
-static void kexec_prepare_cpus(void)
+/*
+ * 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)
+{
+       wake_offline_cpus();
        smp_call_function(kexec_smp_down, NULL, /* wait */0);
        local_irq_disable();
        mb(); /* make sure IRQs are disabled before we say they are */