mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
dmaengine: ste_dma40: Return IRQ_NONE when no interrupt is pending
d40_handle_interrupt() returns IRQ_HANDLED even when no terminal-count or
error status bit is pending.
IRQ_NONE is not only used to identify a device on a shared interrupt.
The generic IRQ core also counts it as unhandled for spurious IRQ
detection. DMA40 does not request this IRQ with IRQF_SHARED, so interrupt
sharing is not the purpose of this change.
If the line remains asserted without matching DMA40 status, returning
IRQ_HANDLED hides the stuck interrupt and can leave the CPU servicing it
indefinitely. Track whether any DMA40 status is pending and return IRQ_NONE
when none is present, allowing the generic IRQ core to diagnose and
eventually disable the faulty line.
DMA40 channels can be owned by other SoC cores. Their status means that
the interrupt is real, but Linux must not acknowledge it. Treat foreign
status as handled and leave its acknowledgment to the owning core, while
acknowledging and dispatching only registered Linux channels.
Fixes: 8d318a50b3 ("DMAENGINE: Support for ST-Ericssons DMA40 block v3")
Assisted-by: LLM
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260927-dma40-fixes-v7-8-89f595e8851d@kernel.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
55a35231b8
commit
b96967644c
|
|
@ -1811,6 +1811,7 @@ static void dma_tasklet(struct tasklet_struct *t)
|
|||
|
||||
static irqreturn_t d40_handle_interrupt(int irq, void *data)
|
||||
{
|
||||
irqreturn_t handled = IRQ_NONE;
|
||||
int i;
|
||||
u32 idx;
|
||||
u32 row;
|
||||
|
|
@ -1844,6 +1845,12 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data)
|
|||
row = chan / BITS_PER_LONG;
|
||||
idx = chan & (BITS_PER_LONG - 1);
|
||||
|
||||
/*
|
||||
* Status for a channel owned by another core still explains
|
||||
* the interrupt, but only ACK Linux-owned channels below.
|
||||
*/
|
||||
handled = IRQ_HANDLED;
|
||||
|
||||
if (il[row].offset == D40_PHY_CHAN)
|
||||
d40c = base->lookup_phy_chans[idx];
|
||||
else
|
||||
|
|
@ -1876,7 +1883,7 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data)
|
|||
if (ret > 0)
|
||||
pm_runtime_put_autosuspend(base->dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
return handled;
|
||||
}
|
||||
|
||||
static int d40_validate_conf(struct d40_chan *d40c,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user