dmaengine: stm32-mdma: rework interrupt handler

[ Upstream commit 1d3dd68749b9f4a4da272f39608d03b4bae0b69f ]

To avoid multiple entries in MDMA interrupt handler for each flag&interrupt
enable, manage all flags set at once.

Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
Link: https://lore.kernel.org/r/20201120143320.30367-5-amelie.delaunay@st.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Amelie Delaunay
2020-11-20 15:33:20 +01:00
committed by Greg Kroah-Hartman
parent 0f87bd8b5f
commit 13d8d11dfa

View File

@@ -1345,7 +1345,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
{ {
struct stm32_mdma_device *dmadev = devid; struct stm32_mdma_device *dmadev = devid;
struct stm32_mdma_chan *chan = devid; struct stm32_mdma_chan *chan = devid;
u32 reg, id, ien, status, flag; u32 reg, id, ccr, ien, status;
/* Find out which channel generates the interrupt */ /* Find out which channel generates the interrupt */
status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0); status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0);
@@ -1357,67 +1357,71 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid)
chan = &dmadev->chan[id]; chan = &dmadev->chan[id];
if (!chan) { if (!chan) {
dev_dbg(mdma2dev(dmadev), "MDMA channel not initialized\n"); dev_warn(mdma2dev(dmadev), "MDMA channel not initialized\n");
goto exit; return IRQ_NONE;
} }
/* Handle interrupt for the channel */ /* Handle interrupt for the channel */
spin_lock(&chan->vchan.lock); spin_lock(&chan->vchan.lock);
status = stm32_mdma_read(dmadev, STM32_MDMA_CISR(chan->id)); status = stm32_mdma_read(dmadev, STM32_MDMA_CISR(id));
ien = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)); /* Mask Channel ReQuest Active bit which can be set in case of MEM2MEM */
ien &= STM32_MDMA_CCR_IRQ_MASK; status &= ~STM32_MDMA_CISR_CRQA;
ien >>= 1; ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(id));
ien = (ccr & STM32_MDMA_CCR_IRQ_MASK) >> 1;
if (!(status & ien)) { if (!(status & ien)) {
spin_unlock(&chan->vchan.lock); spin_unlock(&chan->vchan.lock);
dev_dbg(chan2dev(chan), dev_warn(chan2dev(chan),
"spurious it (status=0x%04x, ien=0x%04x)\n", "spurious it (status=0x%04x, ien=0x%04x)\n",
status, ien); status, ien);
return IRQ_NONE; return IRQ_NONE;
} }
flag = __ffs(status & ien); reg = STM32_MDMA_CIFCR(id);
reg = STM32_MDMA_CIFCR(chan->id);
switch (1 << flag) { if (status & STM32_MDMA_CISR_TEIF) {
case STM32_MDMA_CISR_TEIF: dev_err(chan2dev(chan), "Transfer Err: stat=0x%08x\n",
id = chan->id; readl_relaxed(dmadev->base + STM32_MDMA_CESR(id)));
status = readl_relaxed(dmadev->base + STM32_MDMA_CESR(id));
dev_err(chan2dev(chan), "Transfer Err: stat=0x%08x\n", status);
stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CTEIF); stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CTEIF);
break; status &= ~STM32_MDMA_CISR_TEIF;
}
case STM32_MDMA_CISR_CTCIF: if (status & STM32_MDMA_CISR_CTCIF) {
stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CCTCIF); stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CCTCIF);
status &= ~STM32_MDMA_CISR_CTCIF;
stm32_mdma_xfer_end(chan); stm32_mdma_xfer_end(chan);
break; }
case STM32_MDMA_CISR_BRTIF: if (status & STM32_MDMA_CISR_BRTIF) {
stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CBRTIF); stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CBRTIF);
break; status &= ~STM32_MDMA_CISR_BRTIF;
}
case STM32_MDMA_CISR_BTIF: if (status & STM32_MDMA_CISR_BTIF) {
stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CBTIF); stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CBTIF);
status &= ~STM32_MDMA_CISR_BTIF;
chan->curr_hwdesc++; chan->curr_hwdesc++;
if (chan->desc && chan->desc->cyclic) { if (chan->desc && chan->desc->cyclic) {
if (chan->curr_hwdesc == chan->desc->count) if (chan->curr_hwdesc == chan->desc->count)
chan->curr_hwdesc = 0; chan->curr_hwdesc = 0;
vchan_cyclic_callback(&chan->desc->vdesc); vchan_cyclic_callback(&chan->desc->vdesc);
} }
break; }
case STM32_MDMA_CISR_TCIF: if (status & STM32_MDMA_CISR_TCIF) {
stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CLTCIF); stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CLTCIF);
break; status &= ~STM32_MDMA_CISR_TCIF;
}
default: if (status) {
dev_err(chan2dev(chan), "it %d unhandled (status=0x%04x)\n", stm32_mdma_set_bits(dmadev, reg, status);
1 << flag, status); dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status);
if (!(ccr & STM32_MDMA_CCR_EN))
dev_err(chan2dev(chan), "chan disabled by HW\n");
} }
spin_unlock(&chan->vchan.lock); spin_unlock(&chan->vchan.lock);
exit:
return IRQ_HANDLED; return IRQ_HANDLED;
} }