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:

committed by
Greg Kroah-Hartman

parent
0f87bd8b5f
commit
13d8d11dfa
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user