Thread (2 messages) 2 messages, 2 authors, 2025-08-13

RE: [PATCH v3] dmaengine: xilinx_dma: Support descriptor setup from dma_vecs

From: "Pandey, Radhey Shyam" <radhey.shyam.pandey@amd.com>
Date: 2025-08-13 06:43:59
Also in: dmaengine, lkml

[Public]
-----Original Message-----
From: Folker Schwesinger <redacted>
Sent: Tuesday, August 12, 2025 12:53 AM
To: dmaengine@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-
kernel@vger.kernel.org
Cc: Vinod Koul <vkoul@kernel.org>; Simek, Michal <michal.simek@amd.com>;
Jernej Skrabec [off-list ref]; Krzysztof Kozlowski
[off-list ref]; Uwe Kleine-König <u.kleine-
koenig@baylibre.com>; Marek Vasut [off-list ref]; Pandey, Radhey Shyam
[off-list ref]
Subject: [PATCH v3] dmaengine: xilinx_dma: Support descriptor setup from
dma_vecs

The DMAEngine provides an interface for obtaining DMA transaction descriptors
from an array of scatter gather buffers represented by struct dma_vec. This interface
is used in the DMABUF API of the IIO framework [1].
To enable DMABUF support through the IIO framework for the Xilinx DMA,
implement callback .device_prep_peripheral_dma_vec() of struct dma_device in the
driver.

[1]: https://elixir.bootlin.com/linux/v6.16-rc1/source/drivers/iio/buffer/industrialio-
buffer-dmaengine.c#L104
Nit - avoid links for existing kernel sources instead can mention source file
name or commit id that introduced the change.
Signed-off-by: Folker Schwesinger <redacted>
Reviewed-by: Suraj Gupta <redacted>
Rest looks fine to me.
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
quoted hunk ↗ jump to hunk
---
Changes in v3:
- Collect R-b tags from v2.
- Rebase onto v6.17-rc1.
- Link to v2:
https://lore.kernel.org/dmaengine/DAQB7EU7UXR3.Z07Q6JQ1V67Y@folker-
schwesinger.de/

Changes in v2:
- Improve commit message to include reasoning behind the change.
- Rebase onto v6.16-rc1.
- Link to v1:
https://lore.kernel.org/dmaengine/D8TV2MP99NTE.1842MMA04VB9N@folker-
schwesinger.de/
---
 drivers/dma/xilinx/xilinx_dma.c | 94 +++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index
a34d8f0ceed8..fabff602065f 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -2172,6 +2172,99 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan,
dma_addr_t dma_dst,
      return NULL;
 }

+/**
+ * xilinx_dma_prep_peripheral_dma_vec - prepare descriptors for a DMA_SLAVE
+ *   transaction from DMA vectors
+ * @dchan: DMA channel
+ * @vecs: Array of DMA vectors that should be transferred
+ * @nb: number of entries in @vecs
+ * @direction: DMA direction
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+*/ static struct dma_async_tx_descriptor
+*xilinx_dma_prep_peripheral_dma_vec(
+     struct dma_chan *dchan, const struct dma_vec *vecs, size_t nb,
+     enum dma_transfer_direction direction, unsigned long flags) {
+     struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+     struct xilinx_dma_tx_descriptor *desc;
+     struct xilinx_axidma_tx_segment *segment, *head, *prev = NULL;
+     size_t copy;
+     size_t sg_used;
+     unsigned int i;
+
+     if (!is_slave_direction(direction) || direction != chan->direction)
+             return NULL;
+
+     desc = xilinx_dma_alloc_tx_descriptor(chan);
+     if (!desc)
+             return NULL;
+
+     dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+     desc->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+     /* Build transactions using information from DMA vectors */
+     for (i = 0; i < nb; i++) {
+             sg_used = 0;
+
+             /* Loop until the entire dma_vec entry is used */
+             while (sg_used < vecs[i].len) {
+                     struct xilinx_axidma_desc_hw *hw;
+
+                     /* Get a free segment */
+                     segment = xilinx_axidma_alloc_tx_segment(chan);
+                     if (!segment)
+                             goto error;
+
+                     /*
+                      * Calculate the maximum number of bytes to transfer,
+                      * making sure it is less than the hw limit
+                      */
+                     copy = xilinx_dma_calc_copysize(chan, vecs[i].len,
+                                     sg_used);
+                     hw = &segment->hw;
+
+                     /* Fill in the descriptor */
+                     xilinx_axidma_buf(chan, hw, vecs[i].addr, sg_used, 0);
+                     hw->control = copy;
+
+                     if (prev)
+                             prev->hw.next_desc = segment->phys;
+
+                     prev = segment;
+                     sg_used += copy;
+
+                     /*
+                      * Insert the segment into the descriptor segments
+                      * list.
+                      */
+                     list_add_tail(&segment->node, &desc->segments);
+             }
+     }
+
+     head = list_first_entry(&desc->segments, struct xilinx_axidma_tx_segment,
node);
+     desc->async_tx.phys = head->phys;
+
+     /* For the last DMA_MEM_TO_DEV transfer, set EOP */
+     if (chan->direction == DMA_MEM_TO_DEV) {
+             segment->hw.control |= XILINX_DMA_BD_SOP;
+             segment = list_last_entry(&desc->segments,
+                                       struct xilinx_axidma_tx_segment,
+                                       node);
+             segment->hw.control |= XILINX_DMA_BD_EOP;
+     }
+
+     if (chan->xdev->has_axistream_connected)
+             desc->async_tx.metadata_ops = &xilinx_dma_metadata_ops;
+
+     return &desc->async_tx;
+
+error:
+     xilinx_dma_free_tx_descriptor(chan, desc);
+     return NULL;
+}
+
 /**
  * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
  * @dchan: DMA channel
@@ -3180,6 +3273,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
      xdev->common.device_config = xilinx_dma_device_config;
      if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
              dma_cap_set(DMA_CYCLIC, xdev->common.cap_mask);
+             xdev->common.device_prep_peripheral_dma_vec =
+xilinx_dma_prep_peripheral_dma_vec;
              xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
              xdev->common.device_prep_dma_cyclic =
                                        xilinx_dma_prep_dma_cyclic;
base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
--
2.50.1
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help