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@xxxxxxxxxxxxxxxx> --- drivers/dma/xilinx/xdma-regs.h | 2 ++ drivers/dma/xilinx/xdma.c | 17 +++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/dma/xilinx/xdma-regs.h b/drivers/dma/xilinx/xdma-regs.h index 654c5e41112d..6bf7ae84e452 100644 --- a/drivers/dma/xilinx/xdma-regs.h +++ b/drivers/dma/xilinx/xdma-regs.h @@ -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) diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c index 58539a093de2..dc7f43f17103 100644 --- a/drivers/dma/xilinx/xdma.c +++ b/drivers/dma/xilinx/xdma.c @@ -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; } -- 2.34.1