[PATCH v10 04/19] arm: smp: Introduce a special IPI signalled using FIQ

From: Daniel Thompson
Date: Tue Aug 19 2014 - 12:47:13 EST


Cross CPU signalling based on FIQ is especially useful for kgdb since
it makes stopping all the CPUs during breakpointing more robust (some
of the other architectures already roundup the CPUs using NMIs).

The approach taken provides infrastructure that can be called (or not) by
the driver's FIQ handler depending upon it requirements. In other words
nothing is added here that prevents the driver from accessing "bare metal"
performance.

Signed-off-by: Daniel Thompson <daniel.thompson@xxxxxxxxxx>
---
arch/arm/include/asm/hardirq.h | 2 +-
arch/arm/include/asm/smp.h | 7 +++++++
arch/arm/kernel/smp.c | 15 +++++++++++++++
3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index fe3ea77..5df33e3 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -5,7 +5,7 @@
#include <linux/threads.h>
#include <asm/irq.h>

-#define NR_IPI 8
+#define NR_IPI 9

typedef struct {
unsigned int __softirq_pending;
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 2ec765c..215c927 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -20,6 +20,9 @@

#define raw_smp_processor_id() (current_thread_info()->cpu)

+/* bitmap of IPIs that must be signalled using FIQ */
+#define SMP_IPI_FIQ_MASK 0x0100
+
struct seq_file;

/*
@@ -87,6 +90,10 @@ extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask);

extern int register_ipi_completion(struct completion *completion, int cpu);

+#ifdef CONFIG_FIQ
+extern void send_fiq_ipi_mask(const struct cpumask *);
+#endif
+
struct smp_operations {
#ifdef CONFIG_SMP
/*
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 9388a3d..d386c32 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -72,6 +72,7 @@ enum ipi_msg_type {
IPI_CPU_STOP,
IPI_IRQ_WORK,
IPI_COMPLETION,
+ IPI_FIQ,
};

static DECLARE_COMPLETION(cpu_running);
@@ -451,6 +452,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
S(IPI_CPU_STOP, "CPU stop interrupts"),
S(IPI_IRQ_WORK, "IRQ work interrupts"),
S(IPI_COMPLETION, "completion interrupts"),
+ S(IPI_FIQ, "FIQ interrupts"),
};

static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
@@ -552,6 +554,13 @@ static void ipi_complete(unsigned int cpu)
complete(per_cpu(cpu_completion, cpu));
}

+#ifdef CONFIG_FIQ
+void send_fiq_ipi_mask(const struct cpumask *mask)
+{
+ smp_cross_call(mask, IPI_FIQ);
+}
+#endif
+
/*
* Main handler for inter-processor interrupts
*/
@@ -618,6 +627,12 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
irq_exit();
break;

+#ifdef CONFIG_FIQ
+ case IPI_FIQ:
+ pr_crit("CPU%u: IPI FIQ delivered via IRQ vector\n", cpu);
+ break;
+#endif
+
default:
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
cpu, ipinr);
--
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/