@@ -116,6 +116,8 @@ struct xdma_hw_desc {
CHAN_CTRL_IE_WRITE_ERROR | \
CHAN_CTRL_IE_DESC_ERROR)
+#define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START
+
/* bits of the channel interrupt enable mask */
#define CHAN_IM_DESC_ERROR BIT(19)
#define CHAN_IM_READ_ERROR BIT(9)
@@ -809,15 +809,16 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
desc->completed_desc_num += complete_desc_num;
- if (desc->cyclic) {
- ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS,
- &st);
- if (ret)
- goto out;
-
- regmap_write(xdev->rmap, xchan->base + XDMA_CHAN_STATUS, st);
+ /* clear-on-read the status register */
+ ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC,
+ &st);
+ if (ret)
+ goto out;
- vchan_cyclic_callback(vd);
+ if (desc->cyclic) {
+ st &= XDMA_CHAN_STATUS_MASK;
+ if (st & CHAN_CTRL_IE_DESC_COMPLETED)
+ vchan_cyclic_callback(vd);
goto out;
}
The xdma's channel status register may be read and cleared simultaneously, by accessing it via separate XDMA_CHAN_STATUS_RC register. Therefore, it is possible to simplify the code by just getting rid of a separate redundant write. Also, implement the actual status register checking as well. Previously, the cyclic callback would be scheduled regardless of the status register state. Fix it. Signed-off-by: Jan Kuliga <jankul@alatek.krakow.pl> --- drivers/dma/xilinx/xdma-regs.h | 2 ++ drivers/dma/xilinx/xdma.c | 17 +++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-)