summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/powernv/smp.c
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2017-04-13 20:16:24 +1000
committerMichael Ellerman <mpe@ellerman.id.au>2017-04-13 23:34:34 +1000
commit6b3edefefa6752df57ad636f26baa1b0a502ddab (patch)
treebf00c8ab7b82a22703209b0ba1d0fdddb91fa00b /arch/powerpc/platforms/powernv/smp.c
parenta5adf282461fb6048973ca3aec590495bdbc33f1 (diff)
powerpc/powernv: POWER9 support for msgsnd/doorbell IPI
POWER9 requires msgsync for receiver-side synchronization, and a DD1 workaround restricts IPIs to core-local. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> [mpe: Drop no longer needed asm feature macro changes] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/platforms/powernv/smp.c')
-rw-r--r--arch/powerpc/platforms/powernv/smp.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 33bd4dd2cb41..951a2e230cfa 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -257,6 +257,23 @@ static void pnv_cause_ipi(int cpu)
icp_ops->cause_ipi(cpu);
}
+static void pnv_p9_dd1_cause_ipi(int cpu)
+{
+ int this_cpu = get_cpu();
+
+ /*
+ * POWER9 DD1 has a global addressed msgsnd, but for now we restrict
+ * IPIs to same core, because it requires additional synchronization
+ * for inter-core doorbells which we do not implement.
+ */
+ if (cpumask_test_cpu(cpu, cpu_sibling_mask(this_cpu)))
+ doorbell_global_ipi(cpu);
+ else
+ icp_ops->cause_ipi(cpu);
+
+ put_cpu();
+}
+
static void __init pnv_smp_probe(void)
{
if (xive_enabled())
@@ -264,8 +281,15 @@ static void __init pnv_smp_probe(void)
else
xics_smp_probe();
- if (cpu_has_feature(CPU_FTR_DBELL) && !cpu_has_feature(CPU_FTR_ARCH_300)) {
- smp_ops->cause_ipi = pnv_cause_ipi;
+ if (cpu_has_feature(CPU_FTR_DBELL)) {
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ if (cpu_has_feature(CPU_FTR_POWER9_DD1))
+ smp_ops->cause_ipi = pnv_p9_dd1_cause_ipi;
+ else
+ smp_ops->cause_ipi = doorbell_global_ipi;
+ } else {
+ smp_ops->cause_ipi = pnv_cause_ipi;
+ }
} else {
smp_ops->cause_ipi = icp_ops->cause_ipi;
}