|
@@ -16,6 +16,7 @@
|
|
|
#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>
|
|
@@ -216,9 +217,32 @@ static void kexec_prepare_cpus_wait(int wait_state)
|
|
|
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 */
|