handle_irq() called irq_to_desc() before irq_enter(), so that lookup ran with the preempt count still saying task context and with RCU not yet watching. Generic code called from an interrupt handler should see hardirq context, and irq_to_desc() is more than an array index once SPARSE_IRQ is in use.
Move irq_enter() to the top of the function and add the matching irq_exit() to the invalid interrupt path. Assisted-by: Claude:claude-opus-5 Signed-off-by: Matt Turner <[email protected]> --- arch/alpha/kernel/irq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 4a6a8b1d5a8b..5867a1655045 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -107,18 +107,21 @@ handle_irq(int irq) * handled by some other CPU. (or is disabled) */ static unsigned int illegal_count=0; - struct irq_desc *desc = irq_to_desc(irq); - + struct irq_desc *desc; + + irq_enter(); + + desc = irq_to_desc(irq); if (!desc || ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS)) { irq_err_count++; illegal_count++; printk(KERN_CRIT "device_interrupt: invalid interrupt %d\n", irq); + irq_exit(); return; } - irq_enter(); generic_handle_irq_desc(desc); irq_exit(); } -- 2.54.0

