Re: [PATCH 01/15] irq: mips: avoid nested irq_enter()
From: Mark Rutland <mark.rutland@arm.com>
Date: 2021-10-22 15:05:40
Also in:
lkml
On Fri, Oct 22, 2021 at 11:38:23AM +0100, Marc Zyngier wrote:
quoted hunk ↗ jump to hunk
On Thu, 21 Oct 2021 19:02:22 +0100, Mark Rutland [off-list ref] wrote:quoted
As bcm6345_l1_irq_handle() is a chained irqchip handler, it will be invoked within the context of the root irqchip handler, which must have entered IRQ context already. When bcm6345_l1_irq_handle() calls arch/mips's do_IRQ() , this will nest another call to irq_enter(), and the resulting nested increment to `rcu_data.dynticks_nmi_nesting` will cause rcu_is_cpu_rrupt_from_idle() to fail to identify wakeups from idle, resulting in failure to preempt, and RCU stalls. Chained irqchip handlers must invoke IRQ handlers by way of thee core irqchip code, i.e. generic_handle_irq() or generic_handle_domain_irq() and should not call do_IRQ(), which is intended only for root irqchip handlers. Fix bcm6345_l1_irq_handle() by calling generic_handle_irq() directly. Fixes: c7c42ec2baa1de7a ("irqchips/bmips: Add bcm6345-l1 interrupt controller") Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Marc Zyngier <maz@kernel.org> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Cc: Thomas Gleixner <redacted> --- drivers/irqchip/irq-bcm6345-l1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index e3483789f4df..1bd0621c4ce2 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c@@ -140,7 +140,7 @@ static void bcm6345_l1_irq_handle(struct irq_desc *desc) for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { irq = irq_linear_revmap(intc->domain, base + hwirq); if (irq) - do_IRQ(irq); + generic_handle_irq(irq); else spurious_interrupt(); }A marginally better fix would be to have:diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index 1bd0621c4ce2..fd079215c17f 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c@@ -132,16 +132,12 @@ static void bcm6345_l1_irq_handle(struct irq_desc *desc) int base = idx * IRQS_PER_WORD; unsigned long pending; irq_hw_number_t hwirq; - unsigned int irq; pending = __raw_readl(cpu->map_base + reg_status(intc, idx)); pending &= __raw_readl(cpu->map_base + reg_enable(intc, idx)); for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { - irq = irq_linear_revmap(intc->domain, base + hwirq); - if (irq) - generic_handle_irq(irq); - else + if (generic_handle_domain_irq(intc->domain, base + hwirq)) spurious_interrupt(); } }but we can also tackle that separately if you'd rather keep the change minimal.
I'll add that to the series immediately after this patch, to keep this change minimal for backporting. Thanks, Mark. _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel