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>
This commit is contained in:
Sugar Zhang 2020-06-29 22:05:43 +08:00 committed by Vinod Koul
parent 05611a93b8
commit 3e7f0bd872

View 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;