Re: [PATCH 1/3] dmaengine: Add multi-buffer support in single DMA transfer

Robin Murphy <[email protected]> Fri, 13 Mar 2026 15:16:50 +0000
Newsgroups dev.linux.lists.mhi,dev.linux.lists.iommu,org.kernel.vger.dmaengine,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci
Message-ID <[email protected]>
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
>   
>