Skip to content

Commit a288fd1

Browse files
povikvinodkoul
authored andcommitted
dmaengine: apple-admac: Handle 'global' interrupt flags
In addition to TX channel and RX channel interrupt flags there's another class of 'global' interrupt flags with unknown semantics. Those weren't being handled up to now, and they are the suspected cause of stuck IRQ states that have been sporadically occurring. Check the global flags and clear them if raised. Fixes: b127315 ("dmaengine: apple-admac: Add Apple ADMAC driver") Signed-off-by: Martin Povišer <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent b771baf commit a288fd1

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

drivers/dma/apple-admac.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575

7676
#define REG_TX_INTSTATE(idx) (0x0030 + (idx) * 4)
7777
#define REG_RX_INTSTATE(idx) (0x0040 + (idx) * 4)
78+
#define REG_GLOBAL_INTSTATE(idx) (0x0050 + (idx) * 4)
7879
#define REG_CHAN_INTSTATUS(ch, idx) (0x8010 + (ch) * 0x200 + (idx) * 4)
7980
#define REG_CHAN_INTMASK(ch, idx) (0x8020 + (ch) * 0x200 + (idx) * 4)
8081

@@ -672,13 +673,14 @@ static void admac_handle_chan_int(struct admac_data *ad, int no)
672673
static irqreturn_t admac_interrupt(int irq, void *devid)
673674
{
674675
struct admac_data *ad = devid;
675-
u32 rx_intstate, tx_intstate;
676+
u32 rx_intstate, tx_intstate, global_intstate;
676677
int i;
677678

678679
rx_intstate = readl_relaxed(ad->base + REG_RX_INTSTATE(ad->irq_index));
679680
tx_intstate = readl_relaxed(ad->base + REG_TX_INTSTATE(ad->irq_index));
681+
global_intstate = readl_relaxed(ad->base + REG_GLOBAL_INTSTATE(ad->irq_index));
680682

681-
if (!tx_intstate && !rx_intstate)
683+
if (!tx_intstate && !rx_intstate && !global_intstate)
682684
return IRQ_NONE;
683685

684686
for (i = 0; i < ad->nchannels; i += 2) {
@@ -693,6 +695,12 @@ static irqreturn_t admac_interrupt(int irq, void *devid)
693695
rx_intstate >>= 1;
694696
}
695697

698+
if (global_intstate) {
699+
dev_warn(ad->dev, "clearing unknown global interrupt flag: %x\n",
700+
global_intstate);
701+
writel_relaxed(~(u32) 0, ad->base + REG_GLOBAL_INTSTATE(ad->irq_index));
702+
}
703+
696704
return IRQ_HANDLED;
697705
}
698706

0 commit comments

Comments
 (0)