aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorDaniel Thompson <daniel.thompson@linaro.org>2015-01-13 15:36:56 +0000
committerDaniel Thompson <daniel.thompson@linaro.org>2015-01-21 17:02:54 +0000
commit73ff7c8248d13dc9288b905d9c04e0e703ca2d00 (patch)
treee8a0c90dcd27e1b4c1abc75e5895813215c2e17f /arch/arm/kernel
parent51d0de72371ef91361e57e245748f09f9a561bb7 (diff)
downloadlinux-73ff7c8248d13dc9288b905d9c04e0e703ca2d00.tar.gz
irq: gic: Add support for NMI routing
This patch provides an implementation of irq_set_nmi_routing by allowing SPIs to be switched between group 1 (IRQ) and group 0 (FIQ). It also repaces the interface used between the default FIQ handler and the GIC. These extensions are required in order to allow SPIs to be acknowledged and completed. Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/traps.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 5645f81ac4cc..445fdf26b1af 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/atomic.h>
@@ -462,6 +463,23 @@ die_sig:
arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
}
+int arch_filter_nmi_handler(irq_handler_t handler)
+{
+ irq_handler_t whitelist[] = {
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(whitelist); i++)
+ if (handler == whitelist[i]) {
+ pr_debug("%pS accepted for use as NMI handler\n",
+ handler);
+ return 0;
+ }
+
+ pr_err("%pS cannot be used as an NMI handler\n", handler);
+ return -EPERM;
+}
+
/*
* Handle FIQ similarly to NMI on x86 systems.
*
@@ -478,19 +496,20 @@ asmlinkage void __exception_irq_entry handle_fiq_as_nmi(struct pt_regs *regs)
{
unsigned int cpu = smp_processor_id();
struct pt_regs *old_regs = set_irq_regs(regs);
+ enum irqreturn irqret = 0;
__inc_irq_stat(cpu, __nmi_count);
nmi_enter();
-#ifdef CONFIG_ARM_GIC
- gic_handle_fiq_ipi();
-#endif
+ irqret = gic_handle_fiq();
+
+ if (irqret == IRQ_NONE) {
#ifdef CONFIG_SMP
- ipi_cpu_backtrace(regs);
+ ipi_cpu_backtrace(regs);
#endif
+ }
nmi_exit();
-
set_irq_regs(old_regs);
}