* [PATCH] udmabuf: respect the device's maximum segment size
@ 2026-09-26 7:12 Karl Mehltretter
2026-09-28 8:27 ` Christian König
0 siblings, 1 reply; 3+ messages in thread
From: Karl Mehltretter @ 2026-09-26 7:12 UTC (permalink / raw)
To: Gerd Hoffmann, Vivek Kasireddy
Cc: Karl Mehltretter, Sumit Semwal, Christian König,
Jason Gunthorpe, dri-devel, linux-media, linaro-mm-sig,
linux-kernel
get_sg_table() merges physically contiguous pages without accounting
for the mapping device's maximum segment size. This affects both
importer mappings and the udmabuf misc device mapping used for CPU
access.
With DMA_API_DEBUG enabled, DMA_BUF_IOCTL_SYNC on a 64 MiB udmabuf
reports:
DMA-API: misc udmabuf: mapping sg segment longer than device claims to support [len=65884160] [max=65536]
Use sg_alloc_table_from_pages_segment() with the mapping device's
maximum segment size. Keep a PAGE_SIZE minimum because the allocator
warns and returns -EINVAL for smaller limits.
Before commit 5bf888673e0d ("udmabuf: Do not create malformed
scatterlists"), each entry covered one page.
Fixes: 5bf888673e0d ("udmabuf: Do not create malformed scatterlists")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
Notes:
Tested on v7.3-rc4-70-gfe2ec83746e5 in QEMU (x86_64, TCG) with
DMA_API_DEBUG (all_errors=1) and DMABUF_DEBUG, A/B against the same
base:
before after
DMA_BUF_IOCTL_SYNC, 64 MiB udmabuf 1 report 0
vivid import, 4 MiB udmabuf 2 reports 0
vivid import, 2 MiB hugetlb udmabuf 2 reports 0
frames captured 5/5 5/5
vb2-dma-contig rejected the non-contiguous import in both runs.
drivers/dma-buf/udmabuf.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index df6dd00462423..09f1eb8432f19 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -139,9 +139,13 @@ static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf,
if (!sg)
return ERR_PTR(-ENOMEM);
- ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->pagecount, 0,
- ubuf->pagecount << PAGE_SHIFT,
- GFP_KERNEL);
+ /* The SG allocator requires a segment limit of at least PAGE_SIZE. */
+ ret = sg_alloc_table_from_pages_segment(sg, ubuf->pages, ubuf->pagecount,
+ 0, ubuf->pagecount << PAGE_SHIFT,
+ max_t(unsigned int,
+ dma_get_max_seg_size(dev),
+ PAGE_SIZE),
+ GFP_KERNEL);
if (ret < 0)
goto err_alloc;
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] udmabuf: respect the device's maximum segment size
2026-09-26 7:12 [PATCH] udmabuf: respect the device's maximum segment size Karl Mehltretter
@ 2026-09-28 8:27 ` Christian König
2026-09-28 12:58 ` Jason Gunthorpe
0 siblings, 1 reply; 3+ messages in thread
From: Christian König @ 2026-09-28 8:27 UTC (permalink / raw)
To: Karl Mehltretter, Gerd Hoffmann, Vivek Kasireddy
Cc: Sumit Semwal, Jason Gunthorpe, dri-devel, linux-media,
linaro-mm-sig, linux-kernel
On 9/26/26 09:12, Karl Mehltretter wrote:
> get_sg_table() merges physically contiguous pages without accounting
> for the mapping device's maximum segment size. This affects both
> importer mappings and the udmabuf misc device mapping used for CPU
> access.
>
> With DMA_API_DEBUG enabled, DMA_BUF_IOCTL_SYNC on a 64 MiB udmabuf
> reports:
>
> DMA-API: misc udmabuf: mapping sg segment longer than device claims to support [len=65884160] [max=65536]
>
> Use sg_alloc_table_from_pages_segment() with the mapping device's
> maximum segment size. Keep a PAGE_SIZE minimum because the allocator
> warns and returns -EINVAL for smaller limits.
>
> Before commit 5bf888673e0d ("udmabuf: Do not create malformed
> scatterlists"), each entry covered one page.
>
> Fixes: 5bf888673e0d ("udmabuf: Do not create malformed scatterlists")
> Assisted-by: LLM
> Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
> ---
>
> Notes:
> Tested on v7.3-rc4-70-gfe2ec83746e5 in QEMU (x86_64, TCG) with
> DMA_API_DEBUG (all_errors=1) and DMABUF_DEBUG, A/B against the same
> base:
>
> before after
> DMA_BUF_IOCTL_SYNC, 64 MiB udmabuf 1 report 0
> vivid import, 4 MiB udmabuf 2 reports 0
> vivid import, 2 MiB hugetlb udmabuf 2 reports 0
> frames captured 5/5 5/5
>
> vb2-dma-contig rejected the non-contiguous import in both runs.
>
> drivers/dma-buf/udmabuf.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
> index df6dd00462423..09f1eb8432f19 100644
> --- a/drivers/dma-buf/udmabuf.c
> +++ b/drivers/dma-buf/udmabuf.c
> @@ -139,9 +139,13 @@ static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf,
> if (!sg)
> return ERR_PTR(-ENOMEM);
>
> - ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->pagecount, 0,
> - ubuf->pagecount << PAGE_SHIFT,
> - GFP_KERNEL);
> + /* The SG allocator requires a segment limit of at least PAGE_SIZE. */
> + ret = sg_alloc_table_from_pages_segment(sg, ubuf->pages, ubuf->pagecount,
> + 0, ubuf->pagecount << PAGE_SHIFT,
> + max_t(unsigned int,
> + dma_get_max_seg_size(dev),
> + PAGE_SIZE),
Please return -EINVAL instead when dma_get_max_seg_size() returns that the segment size is smaller than a page.
In general I think that the sg_alloc_table_from_pages_segment() approach is because of the broken design of the old DMA API. Stuff like that should be handled by the iterator going over the DMA segments instead. But yeah that is not something you can fix in one patch.
So apart from the error handling the patch looks good to me.
Regards,
Christian.
> + GFP_KERNEL);
> if (ret < 0)
> goto err_alloc;
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] udmabuf: respect the device's maximum segment size
2026-09-28 8:27 ` Christian König
@ 2026-09-28 12:58 ` Jason Gunthorpe
0 siblings, 0 replies; 3+ messages in thread
From: Jason Gunthorpe @ 2026-09-28 12:58 UTC (permalink / raw)
To: Christian König
Cc: Karl Mehltretter, Gerd Hoffmann, Vivek Kasireddy, Sumit Semwal,
dri-devel, linux-media, linaro-mm-sig, linux-kernel
On Mon, Sep 28, 2026 at 10:27:32AM +0200, Christian König wrote:
> In general I think that the sg_alloc_table_from_pages_segment()
> approach is because of the broken design of the old DMA API.
The scatterlist and the DMA API use of it is very specialized to serve
the needs of the storage stack without performance cost. Segmentation
is intended to make the sgl entries map 1:1 to HW entries so the block
layer can schedule correctly.
Nothing else needs something like this but still has to tip toe around
these rules. It makes it more complicated to map and then in some
cases you have to undo it when programming HW :\
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Jason
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-28 12:58 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-26 7:12 [PATCH] udmabuf: respect the device's maximum segment size Karl Mehltretter
2026-09-28 8:27 ` Christian König
2026-09-28 12:58 ` Jason Gunthorpe
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®