Re: [PATCH v2 3/3] irqchip/irq-pruss-intc: Fix processing of IEP interrupts

From: Thomas Gleixner

Date: Sun Feb 22 2026 - 17:55:46 EST


On Wed, Feb 18 2026 at 15:07, Meghana Malladi wrote:
> IEP compare/capture events are level-triggered and remain asserted until
> the IEP CMP/CAP status register is cleared. The PRUSS INTC acknowledges

The INTC does not acknowledge anything. The driver does.

> this event (via SICR) before the IEP source is actually cleared, leaving the
> SECR latch still set. When linux unmasks the interrupt after the threaded
> handler completes, the INTC still sees the event as pending, resulting in
> an unintended second interrupt.
>
> The solution is to actually ack these IRQs from pruss_intc_irq_unmask()

s/IRQ/interrupt/g

> after the IRQ source is cleared in HW.
>
> The interrupt handling sequence is as follows:
> IEP hardware
> ============
> [1] Compare match occurs
> [2] IEP sets CMP/CAP status bit = 1
> [3] Output level stays HIGH until software clears IEP status
>
> PRUSS INTC
> ==========
> [4] Detects level HIGH → sets SECR[event] = 1
> [5] Raises host IRQ to Linux
>
> Linux interrupt flow (oneshot)
> ==============================
> HARD IRQ:
> [6] pruss_intc_irq_handler()
> [7] mask_ack_irq()
> → writes SICR = event
> → tries to clear SECR
> BUT level still HIGH → INTC still sees it pending
>
> THREAD HANDLER:
> [8] icss_iep_cap_cmp_handler()
> → clears IEP CMP/CAP status bit
> → IEP output level goes LOW
>
> IRQ FINALIZATION:
> [9] irq_finalize_oneshot()
> [10] pruss_intc_irq_unmask():
> Without fix:
> - EISR reenables event
> - INTC still thinks event pending (stale SECR)
> → SECOND IRQ (spurious)
>
> With fix:
> - Write SICR again (now level LOW → INTC clears latch)
> - Then EISR enables event cleanly
> → No spurious IRQ

Having the ACK in the unmask is fundamentally wrong and a horrible hack.

The driver uses the wrong handler. That's what handle_fasteoi_irq() is
for.

All you need is to set the IRQCHIP_EOI_THREADED flag on the interrupt
chip and implement irq_eoi() instead of irq_ack().

For the non-threaded cases this spares the mask/unmask dance
completely. For the threaded oneshot case it masks on entry and
irq_finalize_oneshot() does the EOI and the unmask via
unmask_threaded_irq().

No?

Thanks,

tglx