Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b3edefe authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman
Browse files

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: default avatarNicholas Piggin <npiggin@gmail.com>
[mpe: Drop no longer needed asm feature macro changes]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent a5adf282
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@ static inline void ppc_msgsnd_sync(void)
/* sync after taking message interrupt */
static inline void ppc_msgsync(void)
{
	/* sync is not required when taking messages from the same core */
	__asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGSYNC " ; lwsync", "", %0)
				: : "i" (CPU_FTR_HVMODE|CPU_FTR_ARCH_300));
}

#else /* CONFIG_PPC_BOOK3S */
+2 −0
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@
#define PPC_INST_MFTMR			0x7c0002dc
#define PPC_INST_MSGSND			0x7c00019c
#define PPC_INST_MSGCLR			0x7c0001dc
#define PPC_INST_MSGSYNC		0x7c0006ec
#define PPC_INST_MSGSNDP		0x7c00011c
#define PPC_INST_MTTMR			0x7c0003dc
#define PPC_INST_NOP			0x60000000
@@ -345,6 +346,7 @@
					___PPC_RB(b) | __PPC_EH(eh))
#define PPC_MSGSND(b)		stringify_in_c(.long PPC_INST_MSGSND | \
					___PPC_RB(b))
#define PPC_MSGSYNC		stringify_in_c(.long PPC_INST_MSGSYNC)
#define PPC_MSGCLR(b)		stringify_in_c(.long PPC_INST_MSGCLR | \
					___PPC_RB(b))
#define PPC_MSGSNDP(b)		stringify_in_c(.long PPC_INST_MSGSNDP | \
+26 −2
Original line number Diff line number Diff line
@@ -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)) {
	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;
	}