dmaengine: axi-dmac: terminate early DMA transfers after a partial one
authorAlexandru Ardelean <alexandru.ardelean@analog.com>
Thu, 6 Jun 2019 10:45:49 +0000 (13:45 +0300)
committerVinod Koul <vkoul@kernel.org>
Fri, 14 Jun 2019 05:52:44 +0000 (11:22 +0530)
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>
drivers/dma/dma-axi-dmac.c

index 0101c0ae24c83a45fca7c0068a8b882c29a8f824..368f08cc29aa32cbcdbaa2223d97a65dcaed69c1 100644 (file)
@@ -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;