summaryrefslogtreecommitdiffstats
path: root/drivers/dma/pl330.c
diff options
context:
space:
mode:
authorSugar Zhang <sugar.zhang@rock-chips.com>2020-06-29 16:05:43 +0200
committerVinod Koul <vkoul@kernel.org>2020-07-15 07:55:11 +0200
commit3e7f0bd872087bf4653eeee9a83050f91baae907 (patch)
tree628c22c042f1b88acb272750b5d607830bbfe0e5 /drivers/dma/pl330.c
parentdmaengine: pl330: Remove the burst limit for quirk 'NO-FLUSHP' (diff)
downloadlinux-3e7f0bd872087bf4653eeee9a83050f91baae907.tar.xz
linux-3e7f0bd872087bf4653eeee9a83050f91baae907.zip
dmaengine: pl330: Improve transfer efficiency for the dregs
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>
Diffstat (limited to 'drivers/dma/pl330.c')
-rw-r--r--drivers/dma/pl330.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 7686292bc1db..f1f0176c6c05 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -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;