From: Christoph Hellwig <h...@lst.de>

[ Upstream commit 9ce06497c2722a0f9109e4cc3ce35b7a69617886 ]

When running in M-mode, the S-mode plic handlers are still listed in the
device tree.  Ignore them by setting the maximum threshold.

Signed-off-by: Christoph Hellwig <h...@lst.de>
Acked-by: Marc Zyngier <m...@kernel.org>
Signed-off-by: Paul Walmsley <paul.walms...@sifive.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/irqchip/irq-sifive-plic.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c 
b/drivers/irqchip/irq-sifive-plic.c
index cf755964f2f8b..c72c036aea768 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -244,6 +244,7 @@ static int __init plic_init(struct device_node *node,
                struct plic_handler *handler;
                irq_hw_number_t hwirq;
                int cpu, hartid;
+               u32 threshold = 0;
 
                if (of_irq_parse_one(node, i, &parent)) {
                        pr_err("failed to parse parent for context %d.\n", i);
@@ -266,10 +267,16 @@ static int __init plic_init(struct device_node *node,
                        continue;
                }
 
+               /*
+                * When running in M-mode we need to ignore the S-mode handler.
+                * Here we assume it always comes later, but that might be a
+                * little fragile.
+                */
                handler = per_cpu_ptr(&plic_handlers, cpu);
                if (handler->present) {
                        pr_warn("handler already present for context %d.\n", i);
-                       continue;
+                       threshold = 0xffffffff;
+                       goto done;
                }
 
                handler->present = true;
@@ -279,8 +286,9 @@ static int __init plic_init(struct device_node *node,
                handler->enable_base =
                        plic_regs + ENABLE_BASE + i * ENABLE_PER_HART;
 
+done:
                /* priority must be > threshold to trigger an interrupt */
-               writel(0, handler->hart_base + CONTEXT_THRESHOLD);
+               writel(threshold, handler->hart_base + CONTEXT_THRESHOLD);
                for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
                        plic_toggle(handler, hwirq, 0);
                nr_handlers++;
-- 
2.20.1



Reply via email to