diff options
author | Alexandru Ardelean <alexandru.ardelean@analog.com> | 2019-06-06 12:45:49 +0200 |
---|---|---|
committer | Vinod Koul <vkoul@kernel.org> | 2019-06-14 07:52:44 +0200 |
commit | e28d915528136449ed261a743dfa3f392f555045 (patch) | |
tree | f06d4cda67d27ce12c915f14162eb9d1a0d9c24c /drivers/dma | |
parent | dmaengine: axi-dmac: populate residue info for completed xfers (diff) | |
download | linux-e28d915528136449ed261a743dfa3f392f555045.tar.xz linux-e28d915528136449ed261a743dfa3f392f555045.zip |
dmaengine: axi-dmac: terminate early DMA transfers after a partial one
When a partial transfer is received, the driver should not submit any more
segments to the hardware, as they will be ignored/unused until a new
transfer start operation is done.
This change implements this by adding a new flag on the AXI DMAC
descriptor. This flags is set to true, if there was a partial transfer in
a previously completed segment. When that flag is true, the TLAST flag is
added to the to the submitted segment, signaling the controller to stop
receiving more segments.
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Diffstat (limited to 'drivers/dma')
-rw-r--r-- | drivers/dma/dma-axi-dmac.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 0101c0ae24c8..368f08cc29aa 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -96,6 +96,7 @@ struct axi_dmac_sg { struct axi_dmac_desc { struct virt_dma_desc vdesc; bool cyclic; + bool have_partial_xfer; unsigned int num_submitted; unsigned int num_completed; @@ -220,7 +221,8 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan) } desc->num_submitted++; - if (desc->num_submitted == desc->num_sgs) { + if (desc->num_submitted == desc->num_sgs || + desc->have_partial_xfer) { if (desc->cyclic) desc->num_submitted = 0; /* Start again */ else @@ -294,6 +296,7 @@ static void axi_dmac_dequeue_partial_xfers(struct axi_dmac_chan *chan) if (sg->id == AXI_DMAC_SG_UNUSED) continue; if (sg->id == id) { + desc->have_partial_xfer = true; sg->partial_len = len; found_sg = true; break; |