aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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