Re: [PATCH 1/3] dmaengine: Add multi-buffer support in single DMA transfer
From: Robin Murphy
Date: Fri Mar 13 2026 - 11:25:50 EST
On 2026-03-13 6:49 am, Sumit Kumar wrote:
Add dmaengine_prep_batch_sg API for batching multiple independent buffers
in a single DMA transaction. Each scatter-gather entry specifies both
source and destination addresses. This allows multiple non-contiguous
memory regions to be transferred in a single DMA transaction instead of
separate operations, significantly reducing submission overhead and
interrupt overhead.
Extends struct scatterlist with optional dma_dst_address field
and implements support in dw-edma driver.
[...]
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 29f6ceb98d74b118d08b6a3d4eb7f62dcde0495d..20b65ffcd5e2a65ec5026a29344caf6baa09700b 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -19,6 +19,9 @@ struct scatterlist {
#ifdef CONFIG_NEED_SG_DMA_FLAGS
unsigned int dma_flags;
#endif
+#ifdef CONFIG_NEED_SG_DMA_DST_ADDR
+ dma_addr_t dma_dst_address;
+#endif
Eww, no, what does this even mean? Is the regular dma_addr somehow implicitly a "source" now? How could the single piece of memory represented by page_link/offset/length have two different DMA addresses? How are both the DMA mapping code and users supposed to know which one is relevant in any particular situation?
If you want to bring back DMA_MEMCPY_SG yet again, and you have an actual user this time, then do that (although by now it most likely wants to be a dma_vec version). Don't do whatever this is...
If you want to batch multiple dmaengine_slave_config()/dma_prep_slave_single() operations into some many-to-many variant of dmaengine_prep_peripheral_dma_vec(), then surely that requires actual batching of the config part as well - e.g. passing an explicit vector of distinct dma_slave_configs corresponding to each individual dma_vec - in order to be able to work correctly in general?
Thanks,
Robin.
};
/*
@@ -36,6 +39,10 @@ struct scatterlist {
#define sg_dma_len(sg) ((sg)->length)
#endif
+#ifdef CONFIG_NEED_SG_DMA_DST_ADDR
+#define sg_dma_dst_address(sg) ((sg)->dma_dst_address)
+#endif
+
struct sg_table {
struct scatterlist *sgl; /* the list */
unsigned int nents; /* number of mapped entries */
diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig
index 31cfdb6b4bc3e33c239111955d97b3ec160baafa..3539b5b1efe27be7ccbfebb358dbb9cad2868f11 100644
--- a/kernel/dma/Kconfig
+++ b/kernel/dma/Kconfig
@@ -32,6 +32,9 @@ config NEED_SG_DMA_LENGTH
config NEED_DMA_MAP_STATE
bool
+config NEED_SG_DMA_DST_ADDR
+ bool
+
config ARCH_DMA_ADDR_T_64BIT
def_bool 64BIT || PHYS_ADDR_T_64BIT