aboutsummaryrefslogtreecommitdiff
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorDaniel Thompson <daniel.thompson@linaro.org>2015-03-18 11:07:42 +0000
committerDaniel Thompson <daniel.thompson@linaro.org>2015-03-18 14:18:01 +0000
commita02fe5da35a5188596b3290806cfbc5941444844 (patch)
treec406c23df74c7be817c9a693dc58770994eb3ace /drivers/irqchip
parentd4796e458e69a0d52f8ea017cb424d0a09312130 (diff)
downloadlinux-dev/arm64_nmi-v4.0.tar.gz
arm64: Add support for on-demand backtrace of other CPUsdev/arm64_nmi-v4.0
Currently arm64 has no implementation of arch_trigger_all_cpu_backtace. The patch provides one for arm64 systems that are built with CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS (i.e. those that have a pseudo-NMI). Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-gic-v3.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 3923b2a2150c..bdb134ed4519 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -34,6 +34,16 @@
#include "irq-gic-common.h"
#include "irqchip.h"
+#ifndef SMP_IPI_NMI_MASK
+#define SMP_IPI_NMI_MASK 0
+#endif
+
+/*
+ * Copied from arm-gic.h (which we cannot include here because it conflicts
+ * with arm-gic-v3.h)
+ */
+#define GIC_DIST_PRI 0x400
+
struct redist_region {
void __iomem *redist_base;
phys_addr_t phys_base;
@@ -438,6 +448,7 @@ static int gic_dist_supports_lpis(void)
static void gic_cpu_init(void)
{
void __iomem *rbase;
+ unsigned long nmimask, hwirq;
/* Register ourselves with the rest of the world */
if (gic_populate_rdist())
@@ -455,6 +466,23 @@ static void gic_cpu_init(void)
/* initialise system registers */
gic_cpu_sys_reg_init();
+
+ /* Boost the priority of any IPI in the mask */
+ nmimask = SMP_IPI_NMI_MASK;
+ for_each_set_bit(hwirq, &nmimask, 16) {
+ unsigned int pri_reg = (hwirq / 4) * 4;
+ u32 pri_mask = BIT(6 + ((hwirq % 4) * 8));
+ u32 pri_val = readl_relaxed(rbase + GIC_DIST_PRI + pri_reg);
+ u32 actual;
+
+ pri_mask |= BIT(7 + ((hwirq % 4) * 8));
+ pri_val &= ~pri_mask; /* priority boost */
+ writel_relaxed(pri_val, rbase + GIC_DIST_PRI + pri_reg);
+
+ actual = readl_relaxed(rbase + GIC_DIST_PRI + pri_reg);
+ }
+ gic_dist_wait_for_rwp();
+ gic_redist_wait_for_rwp();
}
#ifdef CONFIG_SMP