Merge tag 'irqchip-fixes-5.4-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / irqchip / irq-sifive-plic.c
index b1a33f97db03b408264ba119c1804f721e22315e..7d0a12fe2714a72979cf56281be5a78fa644064a 100644 (file)
@@ -245,6 +245,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);
@@ -267,10 +268,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;
@@ -280,8 +287,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++;