powerpc: Change the doorbell IPI calling convention
authorNicholas Piggin <npiggin@gmail.com>
Thu, 13 Apr 2017 10:16:21 +0000 (20:16 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 13 Apr 2017 13:34:33 +0000 (23:34 +1000)
Change the doorbell callers to know about their msgsnd addressing,
rather than have them set a per-cpu target data tag at boot that gets
sent to the cause_ipi functions. The data is only used for doorbell IPI
functions, no other IPI types, so it makes sense to keep that detail
local to doorbell.

Have the platform code understand doorbell IPIs, rather than the
interrupt controller code understand them. Platform code can look at
capabilities it has available and decide which to use.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
14 files changed:
arch/powerpc/include/asm/dbell.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/xics.h
arch/powerpc/kernel/dbell.c
arch/powerpc/kernel/smp.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/sysdev/xics/icp-hv.c
arch/powerpc/sysdev/xics/icp-native.c
arch/powerpc/sysdev/xics/icp-opal.c
arch/powerpc/sysdev/xics/xics-common.c
arch/powerpc/sysdev/xive/common.c

index 378167377065a01b3f98df459d82e75277b1d6fe..a66eb596940cb7fb5102676e25e4b04ebbf9ffb1 100644 (file)
@@ -35,8 +35,6 @@ enum ppc_dbell {
 #ifdef CONFIG_PPC_BOOK3S
 
 #define PPC_DBELL_MSGTYPE              PPC_DBELL_SERVER
-#define SPRN_DOORBELL_CPUTAG           SPRN_TIR
-#define PPC_DBELL_TAG_MASK             0x7f
 
 static inline void _ppc_msgsnd(u32 msg)
 {
@@ -49,8 +47,6 @@ static inline void _ppc_msgsnd(u32 msg)
 #else /* CONFIG_PPC_BOOK3S */
 
 #define PPC_DBELL_MSGTYPE              PPC_DBELL
-#define SPRN_DOORBELL_CPUTAG           SPRN_PIR
-#define PPC_DBELL_TAG_MASK             0x3fff
 
 static inline void _ppc_msgsnd(u32 msg)
 {
@@ -59,9 +55,10 @@ static inline void _ppc_msgsnd(u32 msg)
 
 #endif /* CONFIG_PPC_BOOK3S */
 
-extern void doorbell_cause_ipi(int cpu, unsigned long data);
+extern void doorbell_global_ipi(int cpu);
+extern void doorbell_core_ipi(int cpu);
+extern int doorbell_try_core_ipi(int cpu);
 extern void doorbell_exception(struct pt_regs *regs);
-extern void doorbell_setup_this_cpu(void);
 
 static inline void ppc_msgsnd(enum ppc_dbell type, u32 flags, u32 tag)
 {
index 63fa780b71a0b2c39a9e25c61362527e7a62c26e..d9ed3b02615e7f493e8e074a3cd50f11f69acd50 100644 (file)
@@ -40,7 +40,7 @@ extern int cpu_to_chip_id(int cpu);
 struct smp_ops_t {
        void  (*message_pass)(int cpu, int msg);
 #ifdef CONFIG_PPC_SMP_MUXED_IPI
-       void  (*cause_ipi)(int cpu, unsigned long data);
+       void  (*cause_ipi)(int cpu);
 #endif
        void  (*probe)(void);
        int   (*kick_cpu)(int nr);
@@ -125,7 +125,6 @@ extern int smp_request_message_ipi(int virq, int message);
 extern const char *smp_ipi_name[];
 
 /* for irq controllers with only a single ipi */
-extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
 extern void smp_muxed_ipi_message_pass(int cpu, int msg);
 extern void smp_muxed_ipi_set_message(int cpu, int msg);
 extern irqreturn_t smp_ipi_demux(void);
index e0b9e576905aa2e1c24060db56de70f8b02ea920..7ce2c3ac29643b9c36b94c9e385f2c06263c0920 100644 (file)
@@ -57,7 +57,7 @@ struct icp_ops {
        void (*teardown_cpu)(void);
        void (*flush_ipi)(void);
 #ifdef CONFIG_SMP
-       void (*cause_ipi)(int cpu, unsigned long data);
+       void (*cause_ipi)(int cpu);
        irq_handler_t ipi_action;
 #endif
 };
index 2128f3a96c32dd743908f286d4cf72d6d7701568..5869c66adfd0bbef77e0f4cc624378e919828668 100644 (file)
 #include <asm/kvm_ppc.h>
 
 #ifdef CONFIG_SMP
-void doorbell_setup_this_cpu(void)
+
+/*
+ * Doorbells must only be used if CPU_FTR_DBELL is available.
+ * msgsnd is used in HV, and msgsndp is used in !HV.
+ *
+ * These should be used by platform code that is aware of restrictions.
+ * Other arch code should use ->cause_ipi.
+ *
+ * doorbell_global_ipi() sends a dbell to any target CPU.
+ * Must be used only by architectures that address msgsnd target
+ * by PIR/get_hard_smp_processor_id.
+ */
+void doorbell_global_ipi(int cpu)
 {
-       unsigned long tag = mfspr(SPRN_DOORBELL_CPUTAG) & PPC_DBELL_TAG_MASK;
+       u32 tag = get_hard_smp_processor_id(cpu);
 
-       smp_muxed_ipi_set_data(smp_processor_id(), tag);
+       kvmppc_set_host_ipi(cpu, 1);
+       /* Order previous accesses vs. msgsnd, which is treated as a store */
+       mb();
+       ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
 }
 
-void doorbell_cause_ipi(int cpu, unsigned long data)
+/*
+ * doorbell_core_ipi() sends a dbell to a target CPU in the same core.
+ * Must be used only by architectures that address msgsnd target
+ * by TIR/cpu_thread_in_core.
+ */
+void doorbell_core_ipi(int cpu)
 {
+       u32 tag = cpu_thread_in_core(cpu);
+
+       kvmppc_set_host_ipi(cpu, 1);
        /* Order previous accesses vs. msgsnd, which is treated as a store */
        mb();
-       ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, data);
+       ppc_msgsnd(PPC_DBELL_MSGTYPE, 0, tag);
+}
+
+/*
+ * Attempt to cause a core doorbell if destination is on the same core.
+ * Returns 1 on success, 0 on failure.
+ */
+int doorbell_try_core_ipi(int cpu)
+{
+       int this_cpu = get_cpu();
+       int ret = 0;
+
+       if (cpumask_test_cpu(cpu, cpu_sibling_mask(this_cpu))) {
+               doorbell_core_ipi(cpu);
+               ret = 1;
+       }
+
+       put_cpu();
+
+       return ret;
 }
 
 void doorbell_exception(struct pt_regs *regs)
index 6e61cdb89194d32ef7f31785cfc2c8703dd59d5b..17de938d41c5df26ebcd6c5138f5c4d432f0aded 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 #include <asm/kvm_ppc.h>
+#include <asm/dbell.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
@@ -211,17 +212,9 @@ int smp_request_message_ipi(int virq, int msg)
 #ifdef CONFIG_PPC_SMP_MUXED_IPI
 struct cpu_messages {
        long messages;                  /* current messages */
-       unsigned long data;             /* data for cause ipi */
 };
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_messages, ipi_message);
 
-void smp_muxed_ipi_set_data(int cpu, unsigned long data)
-{
-       struct cpu_messages *info = &per_cpu(ipi_message, cpu);
-
-       info->data = data;
-}
-
 void smp_muxed_ipi_set_message(int cpu, int msg)
 {
        struct cpu_messages *info = &per_cpu(ipi_message, cpu);
@@ -236,14 +229,13 @@ void smp_muxed_ipi_set_message(int cpu, int msg)
 
 void smp_muxed_ipi_message_pass(int cpu, int msg)
 {
-       struct cpu_messages *info = &per_cpu(ipi_message, cpu);
-
        smp_muxed_ipi_set_message(cpu, msg);
+
        /*
         * cause_ipi functions are required to include a full barrier
         * before doing whatever causes the IPI.
         */
-       smp_ops->cause_ipi(cpu, info->data);
+       smp_ops->cause_ipi(cpu);
 }
 
 #ifdef __BIG_ENDIAN__
@@ -254,11 +246,12 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
 
 irqreturn_t smp_ipi_demux(void)
 {
-       struct cpu_messages *info = this_cpu_ptr(&ipi_message);
+       struct cpu_messages *info;
        unsigned long all;
 
        mb();   /* order any irq clear */
 
+       info = this_cpu_ptr(&ipi_message);
        do {
                all = xchg(&info->messages, 0);
 #if defined(CONFIG_KVM_XICS) && defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
index 078097a0b09d476a7b4a1a03196ed1a0acac4808..0975066f76e863d022abac12c25889571a819373 100644 (file)
@@ -461,16 +461,9 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
 }
 #endif /* CONFIG_KEXEC_CORE */
 
-static void smp_85xx_basic_setup(int cpu_nr)
-{
-       if (cpu_has_feature(CPU_FTR_DBELL))
-               doorbell_setup_this_cpu();
-}
-
 static void smp_85xx_setup_cpu(int cpu_nr)
 {
        mpic_setup_this_cpu();
-       smp_85xx_basic_setup(cpu_nr);
 }
 
 void __init mpc85xx_smp_init(void)
@@ -484,7 +477,7 @@ void __init mpc85xx_smp_init(void)
                smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
                smp_85xx_ops.message_pass = smp_mpic_message_pass;
        } else
-               smp_85xx_ops.setup_cpu = smp_85xx_basic_setup;
+               smp_85xx_ops.setup_cpu = NULL;
 
        if (cpu_has_feature(CPU_FTR_DBELL)) {
                /*
@@ -492,7 +485,7 @@ void __init mpc85xx_smp_init(void)
                 * smp_muxed_ipi_message_pass
                 */
                smp_85xx_ops.message_pass = NULL;
-               smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
+               smp_85xx_ops.cause_ipi = doorbell_global_ipi;
                smp_85xx_ops.probe = NULL;
        }
 
index 746ca7321b03c07f8752c63bb81d0c4d03f20fa6..a3207cea360e5f04cb176fcb46faa2d7af1371d3 100644 (file)
@@ -172,7 +172,7 @@ static irqreturn_t psurge_ipi_intr(int irq, void *d)
        return IRQ_HANDLED;
 }
 
-static void smp_psurge_cause_ipi(int cpu, unsigned long data)
+static void smp_psurge_cause_ipi(int cpu)
 {
        psurge_set_ipi(cpu);
 }
index 39296bf7009e2d62c6df7635a0179068d4d18c2d..33bd4dd2cb412f95bf67d9f8f277e22d20442ca6 100644 (file)
@@ -53,11 +53,6 @@ static void pnv_smp_setup_cpu(int cpu)
                xive_smp_setup_cpu();
        else if (cpu != boot_cpuid)
                xics_setup_cpu();
-
-#ifdef CONFIG_PPC_DOORBELL
-       if (cpu_has_feature(CPU_FTR_DBELL))
-               doorbell_setup_this_cpu();
-#endif
 }
 
 static int pnv_smp_kick_cpu(int nr)
@@ -254,17 +249,31 @@ static int pnv_smp_prepare_cpu(int cpu)
        return 0;
 }
 
+static void pnv_cause_ipi(int cpu)
+{
+       if (doorbell_try_core_ipi(cpu))
+               return;
+
+       icp_ops->cause_ipi(cpu);
+}
+
 static void __init pnv_smp_probe(void)
 {
        if (xive_enabled())
                xive_smp_probe();
        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;
+       } else {
+               smp_ops->cause_ipi = icp_ops->cause_ipi;
+       }
 }
 
 static struct smp_ops_t pnv_smp_ops = {
-       .message_pass   = smp_muxed_ipi_message_pass,
-       .cause_ipi      = NULL, /* Filled at runtime by xi{cs,ve}_smp_probe() */
+       .message_pass   = NULL, /* Use smp_muxed_ipi_message_pass */
+       .cause_ipi      = NULL, /* Filled at runtime by pnv_smp_probe() */
        .probe          = pnv_smp_probe,
        .prepare_cpu    = pnv_smp_prepare_cpu,
        .kick_cpu       = pnv_smp_kick_cpu,
index f6f83aeccaaaceafae91940cec0ae513d8d07b62..12ff5bef67fd80b0113062bd7f37b86ea7b9efe2 100644 (file)
  */
 static cpumask_var_t of_spin_mask;
 
-/*
- * If we multiplex IPI mechanisms, store the appropriate XICS IPI mechanism here
- */
-static void  (*xics_cause_ipi)(int cpu, unsigned long data);
-
 /* Query where a cpu is now.  Return codes #defined in plpar_wrappers.h */
 int smp_query_cpu_stopped(unsigned int pcpu)
 {
@@ -143,8 +138,6 @@ static void smp_setup_cpu(int cpu)
 {
        if (cpu != boot_cpuid)
                xics_setup_cpu();
-       if (cpu_has_feature(CPU_FTR_DBELL))
-               doorbell_setup_this_cpu();
 
        if (firmware_has_feature(FW_FEATURE_SPLPAR))
                vpa_init(cpu);
@@ -187,23 +180,23 @@ static int smp_pSeries_kick_cpu(int nr)
        return 0;
 }
 
-/* Only used on systems that support multiple IPI mechanisms */
-static void pSeries_cause_ipi_mux(int cpu, unsigned long data)
+static void smp_pseries_cause_ipi(int cpu)
 {
-       if (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id())))
-               doorbell_cause_ipi(cpu, data);
-       else
-               xics_cause_ipi(cpu, data);
+       /* POWER9 should not use this handler */
+       if (doorbell_try_core_ipi(cpu))
+               return;
+
+       icp_ops->cause_ipi(cpu);
 }
 
 static __init void pSeries_smp_probe(void)
 {
        xics_smp_probe();
 
-       if (cpu_has_feature(CPU_FTR_DBELL)) {
-               xics_cause_ipi = smp_ops->cause_ipi;
-               smp_ops->cause_ipi = pSeries_cause_ipi_mux;
-       }
+       if (cpu_has_feature(CPU_FTR_DBELL))
+               smp_ops->cause_ipi = smp_pseries_cause_ipi;
+       else
+               smp_ops->cause_ipi = icp_ops->cause_ipi;
 }
 
 static struct smp_ops_t pseries_smp_ops = {
index e7fa26c4ff73e1e72171f0628e303d03284575f3..bbc839a98c414906fcc193e98d495f1a6ca1c784 100644 (file)
@@ -138,7 +138,7 @@ static void icp_hv_set_cpu_priority(unsigned char cppr)
 
 #ifdef CONFIG_SMP
 
-static void icp_hv_cause_ipi(int cpu, unsigned long data)
+static void icp_hv_cause_ipi(int cpu)
 {
        icp_hv_set_qirr(cpu, IPI_PRIORITY);
 }
index f0f3f47a3fc9b5418b5aff182587490afa82fa95..2bfb9968d56222ca6060177d9cf6f6a4829d0505 100644 (file)
@@ -143,19 +143,9 @@ static unsigned int icp_native_get_irq(void)
 
 #ifdef CONFIG_SMP
 
-static void icp_native_cause_ipi(int cpu, unsigned long data)
+static void icp_native_cause_ipi(int cpu)
 {
        kvmppc_set_host_ipi(cpu, 1);
-#ifdef CONFIG_PPC_DOORBELL
-       if (cpu_has_feature(CPU_FTR_DBELL)) {
-               if (cpumask_test_cpu(cpu, cpu_sibling_mask(get_cpu()))) {
-                       doorbell_cause_ipi(cpu, data);
-                       put_cpu();
-                       return;
-               }
-               put_cpu();
-       }
-#endif
        icp_native_set_qirr(cpu, IPI_PRIORITY);
 }
 
index b53f80f0b4d822b8ecc77271ee7ece8b734bee5a..c71d2ea42627ad6f4f95854d3a41ab0e38036a21 100644 (file)
@@ -126,7 +126,7 @@ static void icp_opal_eoi(struct irq_data *d)
 
 #ifdef CONFIG_SMP
 
-static void icp_opal_cause_ipi(int cpu, unsigned long data)
+static void icp_opal_cause_ipi(int cpu)
 {
        int hw_cpu = get_hard_smp_processor_id(cpu);
 
index 23efe4e42172210ee7784a9e8db07d6e2f087f7b..2eb53c12ee6e544c7bf3a096dc0b2c032e321b2d 100644 (file)
@@ -143,9 +143,6 @@ static void xics_request_ipi(void)
 
 void __init xics_smp_probe(void)
 {
-       /* Setup cause_ipi callback  based on which ICP is used */
-       smp_ops->cause_ipi = icp_ops->cause_ipi;
-
        /* Register all the IPIs */
        xics_request_ipi();
 }
index d9cd7f705f21fe928438ef8ced16678ca7d94d8f..6a98efb142649a577bb3b8abc32f5aa68c98bef4 100644 (file)
@@ -834,15 +834,15 @@ static void xive_irq_free_data(unsigned int virq)
 
 #ifdef CONFIG_SMP
 
-static void xive_cause_ipi(int cpu, unsigned long msg)
+static void xive_cause_ipi(int cpu)
 {
        struct xive_cpu *xc;
        struct xive_irq_data *xd;
 
        xc = per_cpu(xive_cpu, cpu);
 
-       DBG_VERBOSE("IPI msg#%ld CPU %d -> %d (HW IRQ 0x%x)\n",
-                   msg, smp_processor_id(), cpu, xc->hw_ipi);
+       DBG_VERBOSE("IPI CPU %d -> %d (HW IRQ 0x%x)\n",
+                   smp_processor_id(), cpu, xc->hw_ipi);
 
        xd = &xc->ipi_data;
        if (WARN_ON(!xd->trig_mmio))