summaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorAlexandru Ardelean <alexandru.ardelean@analog.com>2019-06-06 12:45:49 +0200
committerVinod Koul <vkoul@kernel.org>2019-06-14 07:52:44 +0200
commite28d915528136449ed261a743dfa3f392f555045 (patch)
treef06d4cda67d27ce12c915f14162eb9d1a0d9c24c /drivers/dma
parentdmaengine: axi-dmac: populate residue info for completed xfers (diff)
downloadlinux-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.c5
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;