summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2015-10-07 05:48:05 +0200
committerScott Wood <scottwood@freescale.com>2015-10-17 07:36:35 +0200
commit01c593d749f4764a87abd8efa397976f2adb8f49 (patch)
tree33d64bc1e8789e476e39fce4b79aee94404f7959 /arch/powerpc
parentpowerpc/b4860: Renamed the L2 caches (diff)
downloadlinux-01c593d749f4764a87abd8efa397976f2adb8f49.tar.xz
linux-01c593d749f4764a87abd8efa397976f2adb8f49.zip
powerpc/fsl-booke-64: Allow booting from the secondary thread
This allows SMP kernels to work as kdump crash kernels. While crash kernels don't really need to be SMP, this prevents things from breaking if a user does it anyway (which is not something you want to only find out once the main kernel has crashed in the field, especially if whether it works or not depends on which cpu crashed). Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/85xx/smp.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index b8b821697910..c2ded034ef53 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -173,15 +173,22 @@ static inline u32 read_spin_table_addr_l(void *spin_table)
static void wake_hw_thread(void *info)
{
void fsl_secondary_thread_init(void);
- unsigned long imsr1, inia1;
+ unsigned long imsr, inia;
int nr = *(const int *)info;
- imsr1 = MSR_KERNEL;
- inia1 = *(unsigned long *)fsl_secondary_thread_init;
-
- mttmr(TMRN_IMSR1, imsr1);
- mttmr(TMRN_INIA1, inia1);
- mtspr(SPRN_TENS, TEN_THREAD(1));
+ imsr = MSR_KERNEL;
+ inia = *(unsigned long *)fsl_secondary_thread_init;
+
+ if (cpu_thread_in_core(nr) == 0) {
+ /* For when we boot on a secondary thread with kdump */
+ mttmr(TMRN_IMSR0, imsr);
+ mttmr(TMRN_INIA0, inia);
+ mtspr(SPRN_TENS, TEN_THREAD(0));
+ } else {
+ mttmr(TMRN_IMSR1, imsr);
+ mttmr(TMRN_INIA1, inia);
+ mtspr(SPRN_TENS, TEN_THREAD(1));
+ }
smp_generic_kick_cpu(nr);
}
@@ -224,6 +231,12 @@ static int smp_85xx_kick_cpu(int nr)
smp_call_function_single(primary, wake_hw_thread, &nr, 0);
return 0;
+ } else if (cpu_thread_in_core(boot_cpuid) != 0 &&
+ cpu_first_thread_sibling(boot_cpuid) == nr) {
+ if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
+ return -ENOENT;
+
+ smp_call_function_single(boot_cpuid, wake_hw_thread, &nr, 0);
}
#endif