Thread (68 messages) 68 messages, 4 authors, 2026-01-23

Re: [RFC PATCH v4 05/38] dmaengine: dw-edma: Add a helper to query linked-list region

From: Frank Li <Frank.li@nxp.com>
Date: 2026-01-22 01:54:49
Also in: dmaengine, linux-devicetree, linux-doc, linux-iommu, linux-kselftest, linux-pci, linux-renesas-soc, lkml

On Thu, Jan 22, 2026 at 10:19:24AM +0900, Koichiro Den wrote:
On Wed, Jan 21, 2026 at 10:24:01AM -0500, Frank Li wrote:
quoted
On Wed, Jan 21, 2026 at 05:41:11PM +0900, Koichiro Den wrote:
quoted
On Wed, Jan 21, 2026 at 10:38:53AM +0900, Koichiro Den wrote:
quoted
On Sun, Jan 18, 2026 at 12:05:47PM -0500, Frank Li wrote:
quoted
On Sun, Jan 18, 2026 at 10:54:07PM +0900, Koichiro Den wrote:
quoted
A remote eDMA provider may need to expose the linked-list (LL) memory
region that was configured by platform glue (typically at boot), so the
peer (host) can map it and operate the remote view of the controller.

Export dw_edma_chan_get_ll_region() to return the LL region associated
with a given dma_chan.
This informaiton passed from dwc epc driver. Is it possible to get it from
EPC driver.
That makes sense, from an API cleanness perspective, thanks.
I'll add a helper function dw_pcie_edma_get_ll_region() in
drivers/pci/controller/dwc/pcie-designware.c, instead of the current
dw_edma_chan_get_ll_region() in dw-edma-core.c.
Hi Frank,

I looked into exposing LL regions from the EPC driver side, but the key
issue is channel identification under possibly concurrent dmaengine users.
In practice, the only stable handle a consumer has is a pointer to struct
dma_chan, and the only reliable way to map that to the eDMA hardware
channel is via dw_edma_chan->id.
If possible, I suggest change to one page pre-channel. So there are a fixed
ll mapping.
I agree that this would make the LL layout more deterministic and would
indeed simplify locating the region for a given dw_edma_chan ID. That said,
my concern was that even with a fixed per-channel layout, we still need a
reliable way to map a struct dma_chan obtained by a consumer to the
corresponding dw_edma_chan ID, especially in the presence of potentially
concurrent dmaengine users.
quoted
quoted
I think an EPC-facing API would still need
that mapping in any case, so keeping the helper in dw-edma seems simpler
and more robust.
If you have another idea, I'd appreciate your insights.
I suggest add generally DMA engine API to get such property, some likes
a kind ioctrl \ dma_get_config().
I think such a helper, combined with your one page per-channel idea, would
resolve the issue cleanly. For example, a helper like dma_get_hw_info()
returning struct dma_hw_info, whose first field is a hw_id, could work
well. Consumers could then use this helper, and if they know they are
dealing with a dw-edma channel, they can derive the LL location
straightforwardly as {hw_id * fixed_stride (e.g. PAGE_SIZE)}. Adding hw_id
to struct dma_slave_caps would make the necessary diff smaller, but I think
it would not semantically fit in the structure.
It is worth to try.

Frank
Thanks,
Koichiro
quoted
Frank
quoted
Regards,
Koichiro
quoted
Thanks for the review,
Koichiro
quoted
Frank
quoted
Signed-off-by: Koichiro Den <redacted>
---
 drivers/dma/dw-edma/dw-edma-core.c | 26 ++++++++++++++++++++++++++
 include/linux/dma/edma.h           | 14 ++++++++++++++
 2 files changed, 40 insertions(+)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 0eb8fc1dcc34..c4fb66a9b5f5 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -1209,6 +1209,32 @@ int dw_edma_chan_register_notify(struct dma_chan *dchan,
 }
 EXPORT_SYMBOL_GPL(dw_edma_chan_register_notify);

+int dw_edma_chan_get_ll_region(struct dma_chan *dchan,
+			       struct dw_edma_region *region)
+{
+	struct dw_edma_chip *chip;
+	struct dw_edma_chan *chan;
+
+	if (!dchan || !region || !dchan->device)
+		return -ENODEV;
+
+	chan = dchan2dw_edma_chan(dchan);
+	if (!chan)
+		return -ENODEV;
+
+	chip = chan->dw->chip;
+	if (!(chip->flags & DW_EDMA_CHIP_LOCAL))
+		return -EINVAL;
+
+	if (chan->dir == EDMA_DIR_WRITE)
+		*region = chip->ll_region_wr[chan->id];
+	else
+		*region = chip->ll_region_rd[chan->id];
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_edma_chan_get_ll_region);
+
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Synopsys DesignWare eDMA controller core driver");
 MODULE_AUTHOR("Gustavo Pimentel <gustavo.pimentel@synopsys.com>");
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 3c538246de07..c9ec426e27ec 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -153,6 +153,14 @@ bool dw_edma_chan_ignore_irq(struct dma_chan *chan);
 int dw_edma_chan_register_notify(struct dma_chan *chan,
 				 void (*cb)(struct dma_chan *chan, void *user),
 				 void *user);
+
+/**
+ * dw_edma_chan_get_ll_region - get linked list (LL) memory for a dma_chan
+ * @chan: the target DMA channel
+ * @region: output parameter returning the corresponding LL region
+ */
+int dw_edma_chan_get_ll_region(struct dma_chan *chan,
+			       struct dw_edma_region *region);
 #else
 static inline int dw_edma_probe(struct dw_edma_chip *chip)
 {
@@ -182,6 +190,12 @@ static inline int dw_edma_chan_register_notify(struct dma_chan *chan,
 {
 	return -ENODEV;
 }
+
+static inline int dw_edma_chan_get_ll_region(struct dma_chan *chan,
+					     struct dw_edma_region *region)
+{
+	return -EINVAL;
+}
 #endif /* CONFIG_DW_EDMA */

 struct pci_epc;
--
2.51.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help