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


Reply via email to