mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Joy Chakraborty <joychakr@google.com>
To: Vinod Koul <vkoul@kernel.org>
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
	devicetree@vger.kernel.org, manugautam@google.com,
	danielmentz@google.com, sjadavani@google.com,
	Joy Chakraborty <joychakr@google.com>
Subject: [PATCH v2 5/6] dmaengine: pl330: Optimize AxSize for peripheral usecases
Date: Fri, 12 May 2023 14:14:44 +0000	[thread overview]
Message-ID: <20230512141445.2026660-6-joychakr@google.com> (raw)
In-Reply-To: <20230512141445.2026660-1-joychakr@google.com>

Add logic to choose the maximum possible AxSize for transactions towards
memory during usecases which copy data between memory and peripherals.

Currently PL330 driver chooses equal AxLen and AxSize for both loads and
stores to/from memory and peripherals which is inefficient towards
memory as the whole bus width is not used for transfers as a peripheral
might be limited to use only a narrow size of the buswidth available.

Example scenario:
    A peripheral might require data byte by byte which would  make AxSize
    = 1 byte and AxLen = 16 for both load from memory and store to
    Peripheral.
    This can be optimized for memory by using maximum AxSize (say
    16bytes) then load from memory can be done with AxSize = 16byte,
    AxLen = 1 and store to peripheral with AxSize = 1byte, AxLen =
    16 beats.

Instruction setup post changes :
    512bytes copy from Memory(16bytes * 4beats) to Peripheral(4bytes *
    16 beats)
    ---
    DMAMOV CCR 0xbd0239
    DMAMOV SAR 0xffffe000
    DMAMOV DAR 0xffffc860
    DMALP_1 7
    DMAFLUSHP 0
    DMAWFPB 0
    DMALDB
    DMASTPB 0
    DMALPENDA_1 bjmpto_7
    DMASEV 3
    DMAEND
    ---

Signed-off-by: Joy Chakraborty <joychakr@google.com>
---
 drivers/dma/pl330.c | 92 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 78 insertions(+), 14 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index e5e610c91f18..46e254fd4007 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2677,6 +2677,52 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, unsigned int brst_s
 	return burst_len;
 }
 
+/*
+ * Returns burst size to be used to copy data from/to memory during a
+ * peripheral transfer
+ */
+static unsigned int get_periph_mem_brst_sz(dma_addr_t addr, size_t len,
+					   struct dma_pl330_chan *pch)
+{
+	unsigned int burst;
+
+	/* Select max possible burst size */
+	burst = pch->dmac->pcfg.data_bus_width / 8;
+
+	/*
+	 * Make sure we use a burst size that aligns with the memory and length.
+	 */
+	while ((addr | len) & (burst - 1))
+		burst /= 2;
+
+	return __ffs(burst);
+}
+
+/*
+ * Returns burst length to be used to copy data from/to memory during a
+ * peripheral transfer
+ */
+static unsigned int get_periph_mem_brst_len(struct dma_pl330_desc *desc,
+					    struct dma_pl330_chan *pch,
+					    unsigned int burst_size)
+{
+	unsigned int burst_len = pch->burst_len;
+
+	if (burst_size != pch->burst_sz) {
+		/* Select max possible burst len */
+		burst_len = get_burst_len(desc, burst_size);
+
+		/*
+		 * Adjust AxLen to keep number of bytes same in Load/Store
+		 */
+		if (burst_size > pch->burst_sz)
+			burst_len = pch->burst_len >> (burst_size - pch->burst_sz);
+		else
+			pch->burst_len = burst_len >> (pch->burst_sz - burst_size);
+	}
+	return burst_len;
+}
+
 static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
 		size_t period_len, enum dma_transfer_direction direction,
@@ -2684,8 +2730,8 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
 {
 	struct dma_pl330_desc *desc = NULL, *first = NULL;
 	struct dma_pl330_chan *pch = to_pchan(chan);
+	unsigned int i, burst_size, burst_len;
 	struct pl330_dmac *pl330 = pch->dmac;
-	unsigned int i;
 	dma_addr_t dst;
 	dma_addr_t src;
 
@@ -2729,28 +2775,35 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
 			return NULL;
 		}
 
+		burst_size = get_periph_mem_brst_sz(dma_addr, period_len, pch);
+		burst_len = get_periph_mem_brst_len(desc, pch, burst_size);
+
 		switch (direction) {
 		case DMA_MEM_TO_DEV:
 			desc->rqcfg.src_inc = 1;
 			desc->rqcfg.dst_inc = 0;
 			src = dma_addr;
 			dst = pch->fifo_dma;
+			desc->rqcfg.src_brst_size = burst_size;
+			desc->rqcfg.src_brst_len = burst_len;
+			desc->rqcfg.dst_brst_size = pch->burst_sz;
+			desc->rqcfg.dst_brst_len = pch->burst_len;
 			break;
 		case DMA_DEV_TO_MEM:
 			desc->rqcfg.src_inc = 0;
 			desc->rqcfg.dst_inc = 1;
 			src = pch->fifo_dma;
 			dst = dma_addr;
+			desc->rqcfg.src_brst_size = pch->burst_sz;
+			desc->rqcfg.src_brst_len = pch->burst_len;
+			desc->rqcfg.dst_brst_size = burst_size;
+			desc->rqcfg.dst_brst_len = burst_len;
 			break;
 		default:
 			break;
 		}
 
 		desc->rqtype = direction;
-		desc->rqcfg.src_brst_size = pch->burst_sz;
-		desc->rqcfg.src_brst_len = pch->burst_len;
-		desc->rqcfg.dst_brst_size = pch->burst_sz;
-		desc->rqcfg.dst_brst_len = pch->burst_len;
 		desc->bytes_requested = period_len;
 		fill_px(&desc->px, dst, src, period_len);
 
@@ -2850,7 +2903,10 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 {
 	struct dma_pl330_desc *first, *desc = NULL;
 	struct dma_pl330_chan *pch = to_pchan(chan);
+	unsigned int burst_size, burst_len;
 	struct scatterlist *sg;
+	dma_addr_t mem_addr;
+	size_t len;
 	int i;
 
 	if (unlikely(!pch || !sgl || !sg_len))
@@ -2882,29 +2938,37 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		else
 			list_add_tail(&desc->node, &first->node);
 
+		mem_addr = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+
+		burst_size = get_periph_mem_brst_sz(mem_addr, len, pch);
+		burst_len = get_periph_mem_brst_len(desc, pch, burst_size);
+
 		switch (direction) {
 		case DMA_MEM_TO_DEV:
 			desc->rqcfg.src_inc = 1;
 			desc->rqcfg.dst_inc = 0;
-			fill_px(&desc->px, pch->fifo_dma, sg_dma_address(sg),
-				sg_dma_len(sg));
+			desc->rqcfg.src_brst_size = burst_size;
+			desc->rqcfg.src_brst_len = burst_len;
+			desc->rqcfg.dst_brst_size = pch->burst_sz;
+			desc->rqcfg.dst_brst_len = pch->burst_len;
+			fill_px(&desc->px, pch->fifo_dma, mem_addr, len);
 			break;
 		case DMA_DEV_TO_MEM:
 			desc->rqcfg.src_inc = 0;
 			desc->rqcfg.dst_inc = 1;
-			fill_px(&desc->px, sg_dma_address(sg), pch->fifo_dma,
-				sg_dma_len(sg));
+			desc->rqcfg.src_brst_size = pch->burst_sz;
+			desc->rqcfg.src_brst_len = pch->burst_len;
+			desc->rqcfg.dst_brst_size = burst_size;
+			desc->rqcfg.dst_brst_len = burst_len;
+			fill_px(&desc->px, mem_addr, pch->fifo_dma, len);
 			break;
 		default:
 			break;
 		}
 
-		desc->rqcfg.src_brst_size = pch->burst_sz;
-		desc->rqcfg.src_brst_len = pch->burst_len;
-		desc->rqcfg.dst_brst_size = pch->burst_sz;
-		desc->rqcfg.dst_brst_len = pch->burst_len;
 		desc->rqtype = direction;
-		desc->bytes_requested = sg_dma_len(sg);
+		desc->bytes_requested = len;
 	}
 
 	/* Return the last desc in the chain */
-- 
2.40.1.606.ga4b1b128d6-goog


  parent reply	other threads:[~2023-05-12 14:15 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-12 14:14 [PATCH v2 0/6] dmaengine: pl330: Updates and logical changes " Joy Chakraborty
2023-05-12 14:14 ` [PATCH v2 1/6] dmaengine: pl330: Separate SRC and DST burst size and len Joy Chakraborty
2023-05-12 14:14 ` [PATCH v2 2/6] dmaengine: pl330: Use FFS to calculate burst size Joy Chakraborty
2023-05-12 14:14 ` [PATCH v2 3/6] dmaengine: pl330: Change if-else to switch-case for consistency Joy Chakraborty
2023-05-12 14:14 ` [PATCH v2 4/6] dmaengine: pl330: Change unused arg "len" from get_burst_len() Joy Chakraborty
2023-05-12 14:14 ` Joy Chakraborty [this message]
2023-05-12 14:14 ` [PATCH v2 6/6] dmaengine: pl330: Use dma singles for peripheral _dregs Joy Chakraborty

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230512141445.2026660-6-joychakr@google.com \
    --to=joychakr@google.com \
    --cc=danielmentz@google.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=manugautam@google.com \
    --cc=sjadavani@google.com \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®