| From 69ea463021be0d159ab30f96195fb0dd18ee2272 Mon Sep 17 00:00:00 2001 |
| From: Guo Ren <guoren@linux.alibaba.com> |
| Date: Fri, 5 Nov 2021 17:47:48 +0800 |
| Subject: irqchip/sifive-plic: Fixup EOI failed when masked |
| |
| From: Guo Ren <guoren@linux.alibaba.com> |
| |
| commit 69ea463021be0d159ab30f96195fb0dd18ee2272 upstream. |
| |
| When using "devm_request_threaded_irq(,,,,IRQF_ONESHOT,,)" in a driver, |
| only the first interrupt is handled, and following interrupts are never |
| delivered (initially reported in [1]). |
| |
| That's because the RISC-V PLIC cannot EOI masked interrupts, as explained |
| in the description of Interrupt Completion in the PLIC spec [2]: |
| |
| <quote> |
| The PLIC signals it has completed executing an interrupt handler by |
| writing the interrupt ID it received from the claim to the claim/complete |
| register. The PLIC does not check whether the completion ID is the same |
| as the last claim ID for that target. If the completion ID does not match |
| an interrupt source that *is currently enabled* for the target, the |
| completion is silently ignored. |
| </quote> |
| |
| Re-enable the interrupt before completion if it has been masked during |
| the handling, and remask it afterwards. |
| |
| [1] http://lists.infradead.org/pipermail/linux-riscv/2021-July/007441.html |
| [2] https://github.com/riscv/riscv-plic-spec/blob/8bc15a35d07c9edf7b5d23fec9728302595ffc4d/riscv-plic.adoc |
| |
| Fixes: bb0fed1c60cc ("irqchip/sifive-plic: Switch to fasteoi flow") |
| Reported-by: Vincent Pelletier <plr.vincent@gmail.com> |
| Tested-by: Nikita Shubin <nikita.shubin@maquefel.me> |
| Signed-off-by: Guo Ren <guoren@linux.alibaba.com> |
| Cc: stable@vger.kernel.org |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Palmer Dabbelt <palmer@dabbelt.com> |
| Cc: Atish Patra <atish.patra@wdc.com> |
| Reviewed-by: Anup Patel <anup@brainfault.org> |
| [maz: amended commit message] |
| Signed-off-by: Marc Zyngier <maz@kernel.org> |
| Link: https://lore.kernel.org/r/20211105094748.3894453-1-guoren@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/irqchip/irq-sifive-plic.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/irqchip/irq-sifive-plic.c |
| +++ b/drivers/irqchip/irq-sifive-plic.c |
| @@ -138,7 +138,13 @@ static void plic_irq_eoi(struct irq_data |
| { |
| struct plic_handler *handler = this_cpu_ptr(&plic_handlers); |
| |
| - writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); |
| + if (irqd_irq_masked(d)) { |
| + plic_irq_unmask(d); |
| + writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); |
| + plic_irq_mask(d); |
| + } else { |
| + writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); |
| + } |
| } |
| |
| static struct irq_chip plic_chip = { |