summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/85xx/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/85xx/smp.c')
-rw-r--r--arch/powerpc/platforms/85xx/smp.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index ba093f553678..d7c1e69f3070 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -28,6 +28,7 @@
#include <asm/dbell.h>
#include <asm/fsl_guts.h>
#include <asm/code-patching.h>
+#include <asm/cputhreads.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/mpic.h>
@@ -168,6 +169,24 @@ static inline u32 read_spin_table_addr_l(void *spin_table)
return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l);
}
+#ifdef CONFIG_PPC64
+static void wake_hw_thread(void *info)
+{
+ void fsl_secondary_thread_init(void);
+ unsigned long imsr1, inia1;
+ 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));
+
+ smp_generic_kick_cpu(nr);
+}
+#endif
+
static int smp_85xx_kick_cpu(int nr)
{
unsigned long flags;
@@ -183,6 +202,31 @@ static int smp_85xx_kick_cpu(int nr)
pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
+#ifdef CONFIG_PPC64
+ /* Threads don't use the spin table */
+ if (cpu_thread_in_core(nr) != 0) {
+ int primary = cpu_first_thread_sibling(nr);
+
+ if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT)))
+ return -ENOENT;
+
+ if (cpu_thread_in_core(nr) != 1) {
+ pr_err("%s: cpu %d: invalid hw thread %d\n",
+ __func__, nr, cpu_thread_in_core(nr));
+ return -ENOENT;
+ }
+
+ if (!cpu_online(primary)) {
+ pr_err("%s: cpu %d: primary %d not online\n",
+ __func__, nr, primary);
+ return -ENOENT;
+ }
+
+ smp_call_function_single(primary, wake_hw_thread, &nr, 0);
+ return 0;
+ }
+#endif
+
np = of_get_cpu_node(nr, NULL);
cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);