diff options
author | Scott Wood <scottwood@freescale.com> | 2015-10-06 22:48:12 -0500 |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2015-10-27 18:13:25 -0500 |
commit | f34b3e19fd060b87e97c89050f2b40b8ada468a9 (patch) | |
tree | a4aad95d90cda53bd75398feef7e863284e14091 /arch/powerpc/platforms/85xx/smp.c | |
parent | 939fbf00805b395743e2406755ca20f5f959a598 (diff) | |
download | op-kernel-dev-f34b3e19fd060b87e97c89050f2b40b8ada468a9.zip op-kernel-dev-f34b3e19fd060b87e97c89050f2b40b8ada468a9.tar.gz |
powerpc/e6500: kexec: Handle hardware threads
The new kernel will be expecting secondary threads to be disabled,
not spinning.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'arch/powerpc/platforms/85xx/smp.c')
-rw-r--r-- | arch/powerpc/platforms/85xx/smp.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 2e46684..712764f 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -374,9 +374,55 @@ static void mpc85xx_smp_kexec_down(void *arg) #else void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) { + int cpu = smp_processor_id(); + int sibling = cpu_last_thread_sibling(cpu); + bool notified = false; + int disable_cpu; + int disable_threadbit = 0; + long start = mftb(); + long now; + local_irq_disable(); hard_irq_disable(); mpic_teardown_this_cpu(secondary); + + if (cpu == crashing_cpu && cpu_thread_in_core(cpu) != 0) { + /* + * We enter the crash kernel on whatever cpu crashed, + * even if it's a secondary thread. If that's the case, + * disable the corresponding primary thread. + */ + disable_threadbit = 1; + disable_cpu = cpu_first_thread_sibling(cpu); + } else if (sibling != crashing_cpu && + cpu_thread_in_core(cpu) == 0 && + cpu_thread_in_core(sibling) != 0) { + disable_threadbit = 2; + disable_cpu = sibling; + } + + if (disable_threadbit) { + while (paca[disable_cpu].kexec_state < KEXEC_STATE_REAL_MODE) { + barrier(); + now = mftb(); + if (!notified && now - start > 1000000) { + pr_info("%s/%d: waiting for cpu %d to enter KEXEC_STATE_REAL_MODE (%d)\n", + __func__, smp_processor_id(), + disable_cpu, + paca[disable_cpu].kexec_state); + notified = true; + } + } + + if (notified) { + pr_info("%s: cpu %d done waiting\n", + __func__, disable_cpu); + } + + mtspr(SPRN_TENC, disable_threadbit); + while (mfspr(SPRN_TENSR) & disable_threadbit) + cpu_relax(); + } } #endif |