dmaengine: pl330: Improve transfer efficiency for the dregs
authorSugar Zhang <sugar.zhang@rock-chips.com>
Mon, 29 Jun 2020 14:05:43 +0000 (22:05 +0800)
committerVinod Koul <vkoul@kernel.org>
Wed, 15 Jul 2020 05:55:11 +0000 (11:25 +0530)
Only the unaligned burst transfers have the dregs.
so, still use BURST transfer with a reduced size
for better performance.

Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Link: https://lore.kernel.org/r/1593439555-68130-3-git-send-email-sugar.zhang@rock-chips.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/pl330.c

index 7686292..f1f0176 100644 (file)
@@ -1228,8 +1228,9 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
 }
 
 /*
- * transfer dregs with single transfers to peripheral, or a reduced size burst
- * for mem-to-mem.
+ * only the unaligned burst transfers have the dregs.
+ * so, still transfer dregs with a reduced size burst
+ * for mem-to-mem, mem-to-dev or dev-to-mem.
  */
 static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
                const struct _xfer_spec *pxs, int transfer_length)
@@ -1240,22 +1241,31 @@ static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[],
        if (transfer_length == 0)
                return off;
 
+       /*
+        * dregs_len = (total bytes - BURST_TO_BYTE(bursts, ccr)) /
+        *             BRST_SIZE(ccr)
+        * the dregs len must be smaller than burst len,
+        * so, for higher efficiency, we can modify CCR
+        * to use a reduced size burst len for the dregs.
+        */
+       dregs_ccr = pxs->ccr;
+       dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) |
+               (0xf << CC_DSTBRSTLEN_SHFT));
+       dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+               CC_SRCBRSTLEN_SHFT);
+       dregs_ccr |= (((transfer_length - 1) & 0xf) <<
+               CC_DSTBRSTLEN_SHFT);
+
        switch (pxs->desc->rqtype) {
        case DMA_MEM_TO_DEV:
                /* fall through */
        case DMA_DEV_TO_MEM:
-               off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs,
-                       transfer_length, SINGLE);
+               off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr);
+               off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, 1,
+                                       BURST);
                break;
 
        case DMA_MEM_TO_MEM:
-               dregs_ccr = pxs->ccr;
-               dregs_ccr &= ~((0xf << CC_SRCBRSTLEN_SHFT) |
-                       (0xf << CC_DSTBRSTLEN_SHFT));
-               dregs_ccr |= (((transfer_length - 1) & 0xf) <<
-                       CC_SRCBRSTLEN_SHFT);
-               dregs_ccr |= (((transfer_length - 1) & 0xf) <<
-                       CC_DSTBRSTLEN_SHFT);
                off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr);
                off += _ldst_memtomem(dry_run, &buf[off], pxs, 1);
                break;