Message ID | 20250211023040.180330-1-bo.ye@mediatek.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | genirq: clear IRQS_PENDING in irq descriptor | expand |
On Tue, Feb 11 2025 at 10:30, Bo Ye wrote: > In the kernel-6.6 IRQ subsystem, there is a case of IRQ retrigger: How is kernel 6.6 relevant here? > Due to the possibility of electrical signal glitches causing false > interrupts for edge-triggered type IRQs, it is necessary to clear any > potential false interrupts or re-triggered interrupt signals from the > interrupt source between disabling and enabling the edge-triggered > IRQ. This claim is just wrong. A disable_irq(); enable_irq(); sequence must preserve the pending bit so that interrupts do not get lost. The lazy disabling mechanism is there to guarantee that. > When the module using this IRQ may disable the IRQ as needed and then > If the disabled IRQ is triggered, the IRQ subsystem will set the > istate of the corresponding IRQ descriptor to pending. Rightfully so. > After the module using this IRQ completes other tasks, it clears the > pending state on the GIC using irq_set_irqchip_state(). So this is a problem related to a specific out of tree driver and the GIC, right? > However, the pending state in the IRQ descriptor's istate is not > cleared, which leads to the module receiving the IRQ again after > enabling it, even though the interrupt source has not triggered, > because the IRQ subsystem retriggers the interrupt based on the > pending state in the IRQ descriptor. What's the actual problem here? A driver has to be able to handle spurious interrupts at any given time. > Solution: the corresponding upstream patch modifies the > irq_set_irqchip_state(...) in the IRQ subsystem. Which corresponding upstream patch? > The purpose is to clear the pending state in the IRQ descriptor's > istate when successfully clearing the corresponding IRQ on the GIC. Sure that's the purpose, but you fail to explain the actual problem and the interaction with irq_set_irqchip_state(). Thanks, tglx
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8a936c1ffad3..ad1cefb2e5aa 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -2893,8 +2893,11 @@ int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, #endif } while (data); - if (data) + if (data) { err = chip->irq_set_irqchip_state(data, which, val); + if (!err && which == IRQCHIP_STATE_PENDING && !val) + desc->istate &= ~IRQS_PENDING; + } out_unlock: irq_put_desc_busunlock(desc, flags);