* [PATCH 0/3] dma-buf: heaps: cma: respect the importer's maximum segment size
@ 2026-10-05 6:46 Karl Mehltretter
2026-10-05 6:46 ` [PATCH 1/3] media: tegra-vde: set an unlimited DMA " Karl Mehltretter
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Karl Mehltretter @ 2026-10-05 6:46 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Karl Mehltretter, Benjamin Gaignard, Brian Starkey, John Stultz,
T . J . Mercier, Jason Gunthorpe, Dmitry Osipenko,
Mauro Carvalho Chehab, Thierry Reding, Jonathan Hunter,
Russell King, David Airlie, Simona Vetter, linux-media, dri-devel,
linaro-mm-sig, linux-tegra, linux-kernel
The CMA heap builds attachment scatterlists without considering the
importing device's maximum DMA segment size. When an entry exceeds
that limit, DMA_API_DEBUG reports "mapping sg segment longer than
device claims to support". Patch 3 uses the importer's limit. A
corresponding udmabuf fix was posted in [1].
With patch 3, an importer that keeps the 64 KiB default gets a larger
buffer in several entries. Two in-tree importers require a single
entry and never set a limit: tegra-vde without an IOMMU domain, and
armada. Patches 1 and 2 set an unlimited segment size there. I found
them by searching the importers for checks on the number of entries
and on the length of the first entry. etnaviv has a fast path for
single-entry buffers but already declares a 2 GiB limit.
Patches 1 and 2 are valid on their own and can go through their own
trees. Patch 3 should only be applied after them, and is marked
stable+noautosel for that reason.
Tested in QEMU only, not on real hardware: patch 3 on a custom model
of the SAM9X75 Curiosity, and all three patches on xilinx-zynq-a9
with tegra-vde and armada probing from stub device tree nodes. The
notes of each patch have the details.
[1] https://lore.kernel.org/r/20260929054835.94118-1-kmehltretter@gmail.com/
Karl Mehltretter (3):
media: tegra-vde: set an unlimited DMA segment size
drm/armada: set an unlimited DMA segment size
dma-buf: heaps: cma: respect the device's maximum segment size
drivers/dma-buf/heaps/cma_heap.c | 14 ++++++++++----
drivers/gpu/drm/armada/armada_drv.c | 3 +++
drivers/media/platform/nvidia/tegra-vde/vde.c | 2 ++
3 files changed, 15 insertions(+), 4 deletions(-)
base-commit: fe2ec83746e501645709761605c2464a44fd2929
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] media: tegra-vde: set an unlimited DMA segment size
2026-10-05 6:46 [PATCH 0/3] dma-buf: heaps: cma: respect the importer's maximum segment size Karl Mehltretter
@ 2026-10-05 6:46 ` Karl Mehltretter
2026-10-05 6:46 ` [PATCH 2/3] drm/armada: " Karl Mehltretter
2026-10-05 6:46 ` [PATCH 3/3] dma-buf: heaps: cma: respect the device's maximum " Karl Mehltretter
2 siblings, 0 replies; 5+ messages in thread
From: Karl Mehltretter @ 2026-10-05 6:46 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Karl Mehltretter, Benjamin Gaignard, Brian Starkey, John Stultz,
T . J . Mercier, Jason Gunthorpe, Dmitry Osipenko,
Mauro Carvalho Chehab, Thierry Reding, Jonathan Hunter,
Russell King, David Airlie, Simona Vetter, linux-media, dri-devel,
linaro-mm-sig, linux-tegra, linux-kernel
The driver never sets a maximum DMA segment size, so the device claims
the 64 KiB default. With DMA_API_DEBUG, mapping a larger buffer
reports:
DMA-API: tegra-vde 6001a000.vde: mapping sg segment longer than
device claims to support [len=1228800] [max=65536]
Without an IOMMU domain the driver also needs each imported buffer as
one entry. An exporter that respects the 64 KiB claim has to split a
larger buffer, and queueing it fails with "Sparse DMA region is
unsupported, please enable IOMMU".
Set the maximum segment size to UINT_MAX.
Verified with a QEMU stub. Not tested on real hardware.
Fixes: cd6c56feb591 ("media: staging: media: Introduce NVIDIA Tegra video decoder driver")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
Notes:
Tested on v7.3-rc4-70-gfe2ec83746e5 with DMA_API_DEBUG on QEMU's
xilinx-zynq-a9. The driver probed from a stub device tree node, so all
registers read 0, and needed a test-only change to probe without a
Tegra PMC.
Queueing a capture buffer of 1228800-byte CMA heap buffers works
before and after this patch, with 7 segment-length reports before and
none after. With patch 3 alone it fails. With patches 1 and 3 it
works.
drivers/media/platform/nvidia/tegra-vde/vde.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/platform/nvidia/tegra-vde/vde.c b/drivers/media/platform/nvidia/tegra-vde/vde.c
index c3097085ad9d..6a47e8ba083c 100644
--- a/drivers/media/platform/nvidia/tegra-vde/vde.c
+++ b/drivers/media/platform/nvidia/tegra-vde/vde.c
@@ -238,6 +238,8 @@ static int tegra_vde_probe(struct platform_device *pdev)
vde->soc = of_device_get_match_data(&pdev->dev);
vde->dev = dev;
+ dma_set_max_seg_size(dev, UINT_MAX);
+
vde->sxe = devm_platform_ioremap_resource_byname(pdev, "sxe");
if (IS_ERR(vde->sxe))
return PTR_ERR(vde->sxe);
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] drm/armada: set an unlimited DMA segment size
2026-10-05 6:46 [PATCH 0/3] dma-buf: heaps: cma: respect the importer's maximum segment size Karl Mehltretter
2026-10-05 6:46 ` [PATCH 1/3] media: tegra-vde: set an unlimited DMA " Karl Mehltretter
@ 2026-10-05 6:46 ` Karl Mehltretter
2026-10-05 6:46 ` [PATCH 3/3] dma-buf: heaps: cma: respect the device's maximum " Karl Mehltretter
2 siblings, 0 replies; 5+ messages in thread
From: Karl Mehltretter @ 2026-10-05 6:46 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Karl Mehltretter, Benjamin Gaignard, Brian Starkey, John Stultz,
T . J . Mercier, Jason Gunthorpe, Dmitry Osipenko,
Mauro Carvalho Chehab, Thierry Reding, Jonathan Hunter,
Russell King, David Airlie, Simona Vetter, linux-media, dri-devel,
linaro-mm-sig, linux-tegra, linux-kernel
The driver never sets a maximum DMA segment size, so the device claims
the 64 KiB default. With DMA_API_DEBUG, importing a larger contiguous
dma-buf reports:
DMA-API: armada-drm armada-drm: mapping sg segment longer than
device claims to support [len=1228800] [max=65536]
armada_gem_map_import() also needs the buffer as one entry. An exporter
that respects the 64 KiB claim has to split a larger buffer, and the
import fails with "dma_buf_map_attachment() returned an (unsupported)
scattered list".
Set the maximum segment size to UINT_MAX.
Verified with a QEMU stub. Not tested on real hardware.
Fixes: 96f60e37dc66 ("DRM: Armada: Add Armada DRM driver")
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
Notes:
Tested on v7.3-rc4-70-gfe2ec83746e5 with DMA_API_DEBUG on QEMU's
xilinx-zynq-a9. The LCD controller probed from a stub device tree
node, so all registers read 0. A test module registered the
armada-drm platform device, because nothing in mainline registers it.
Creating a framebuffer from an imported 1228800-byte CMA heap buffer
works before and after this patch, with one segment-length report
before and none after. With patch 3 alone it fails. With patches 2
and 3 it works.
drivers/gpu/drm/armada/armada_drv.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index cae25ad66c74..42498fc77e54 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -6,6 +6,7 @@
#include <linux/aperture.h>
#include <linux/clk.h>
#include <linux/component.h>
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
@@ -101,6 +102,8 @@ static int armada_drm_bind(struct device *dev)
dev_set_drvdata(dev, &priv->drm);
+ dma_set_max_seg_size(dev, UINT_MAX);
+
/* Mode setting support */
drm_mode_config_init(&priv->drm);
priv->drm.mode_config.min_width = 320;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] dma-buf: heaps: cma: respect the device's maximum segment size
2026-10-05 6:46 [PATCH 0/3] dma-buf: heaps: cma: respect the importer's maximum segment size Karl Mehltretter
2026-10-05 6:46 ` [PATCH 1/3] media: tegra-vde: set an unlimited DMA " Karl Mehltretter
2026-10-05 6:46 ` [PATCH 2/3] drm/armada: " Karl Mehltretter
@ 2026-10-05 6:46 ` Karl Mehltretter
2026-10-09 18:36 ` Jason Gunthorpe
2 siblings, 1 reply; 5+ messages in thread
From: Karl Mehltretter @ 2026-10-05 6:46 UTC (permalink / raw)
To: Sumit Semwal, Christian König
Cc: Karl Mehltretter, Benjamin Gaignard, Brian Starkey, John Stultz,
T . J . Mercier, Jason Gunthorpe, Dmitry Osipenko,
Mauro Carvalho Chehab, Thierry Reding, Jonathan Hunter,
Russell King, David Airlie, Simona Vetter, linux-media, dri-devel,
linaro-mm-sig, linux-tegra, linux-kernel
cma_heap_attach() merges the physically contiguous buffer into one
scatterlist entry without considering the importing device's maximum
segment size. With DMA_API_DEBUG, importing a buffer larger than that
limit reports, here with atmel-hlcdc:
DMA-API: atmel-hlcdc-display-controller atmel-hlcdc-dc: mapping sg
segment longer than device claims to support [len=307200] [max=65536]
Build each attachment table using the importing device's segment limit.
Return -EINVAL if the limit is smaller than PAGE_SIZE because the
page-based allocator cannot honor it.
An importer that needs the whole buffer as one entry has to declare a
segment size that covers it. tegra-vde without an IOMMU domain and
armada did not. Their limits must be raised before this change is
applied.
Reproduced with a custom QEMU model of the SAM9X75 Curiosity. Not
tested on real hardware.
Fixes: b61614ec318a ("dma-buf: heaps: Add CMA heap to dmabuf heaps")
Cc: stable+noautosel@kernel.org # needs the tegra-vde and armada segment size changes first
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
Notes:
Tested on v7.3-rc4-70-gfe2ec83746e5 with DMA_API_DEBUG and
DMABUF_DEBUG, on a custom QEMU model of the SAM9X75 Curiosity
(ARM926EJ-S, TCG) with an XLCDC model.
vivid captures into three 307200-byte CMA heap buffers, which
atmel-hlcdc imports and scans out. All 8 frames are shown before and
after the patch, with 3 DMA-API reports before and none after.
A test importer maps a 256 KiB CMA heap buffer with different
maximum segment sizes (4 KiB pages):
max segment (bytes) before after
2048 1 x 256 KiB attach returns -EINVAL
4096 1 x 256 KiB 64 x 4 KiB
65536 1 x 256 KiB 4 x 64 KiB
UINT_MAX 1 x 256 KiB 1 x 256 KiB
The first three cases gave a DMA-API report before the patch and
none after it.
drivers/dma-buf/heaps/cma_heap.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 3fb4b946c91a..9d61d14688b8 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -58,16 +58,22 @@ static int cma_heap_attach(struct dma_buf *dmabuf,
{
struct cma_heap_buffer *buffer = dmabuf->priv;
struct dma_heap_attachment *a;
+ unsigned int max_segment;
int ret;
+ max_segment = dma_get_max_seg_size(attachment->dev);
+ /* The SG allocator requires a segment limit of at least PAGE_SIZE. */
+ if (max_segment < PAGE_SIZE)
+ return -EINVAL;
+
a = kzalloc_obj(*a);
if (!a)
return -ENOMEM;
- ret = sg_alloc_table_from_pages(&a->table, buffer->pages,
- buffer->pagecount, 0,
- buffer->pagecount << PAGE_SHIFT,
- GFP_KERNEL);
+ ret = sg_alloc_table_from_pages_segment(&a->table, buffer->pages,
+ buffer->pagecount, 0,
+ buffer->pagecount << PAGE_SHIFT,
+ max_segment, GFP_KERNEL);
if (ret) {
kfree(a);
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 3/3] dma-buf: heaps: cma: respect the device's maximum segment size
2026-10-05 6:46 ` [PATCH 3/3] dma-buf: heaps: cma: respect the device's maximum " Karl Mehltretter
@ 2026-10-09 18:36 ` Jason Gunthorpe
0 siblings, 0 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2026-10-09 18:36 UTC (permalink / raw)
To: Karl Mehltretter
Cc: Sumit Semwal, Christian König, Benjamin Gaignard,
Brian Starkey, John Stultz, T . J . Mercier, Dmitry Osipenko,
Mauro Carvalho Chehab, Thierry Reding, Jonathan Hunter,
Russell King, David Airlie, Simona Vetter, linux-media, dri-devel,
linaro-mm-sig, linux-tegra, linux-kernel
On Mon, Oct 05, 2026 at 08:46:40AM +0200, Karl Mehltretter wrote:
> diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
> index 3fb4b946c91a..9d61d14688b8 100644
> --- a/drivers/dma-buf/heaps/cma_heap.c
> +++ b/drivers/dma-buf/heaps/cma_heap.c
> @@ -58,16 +58,22 @@ static int cma_heap_attach(struct dma_buf *dmabuf,
> {
> struct cma_heap_buffer *buffer = dmabuf->priv;
> struct dma_heap_attachment *a;
> + unsigned int max_segment;
> int ret;
>
> + max_segment = dma_get_max_seg_size(attachment->dev);
> + /* The SG allocator requires a segment limit of at least PAGE_SIZE. */
> + if (max_segment < PAGE_SIZE)
> + return -EINVAL;
This seems like unnecessary AI paranoia.. If something like this
should exist it should be inside sg_alloc_table_from_pages_segment().
I guess pretty much every DRM user has this latent issue? Given few
importers even seem to use the segment size, it would be nicer to
solve it by just not using segment size here.
This is possible with the new dma api, and adding a new
dma_buf_pages_to_sgt() using that approach looked OK from an AI draft.
However, the dma_sync_sgtable_for_device() in the heap doesn't seem to
have a straightforward conversion.. We never made streaming functions
for the new dma api, and drivers are not permitted to call the cache
flushing functions by themselves.
Something to think about at least.
Jason
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-09 18:37 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-05 6:46 [PATCH 0/3] dma-buf: heaps: cma: respect the importer's maximum segment size Karl Mehltretter
2026-10-05 6:46 ` [PATCH 1/3] media: tegra-vde: set an unlimited DMA " Karl Mehltretter
2026-10-05 6:46 ` [PATCH 2/3] drm/armada: " Karl Mehltretter
2026-10-05 6:46 ` [PATCH 3/3] dma-buf: heaps: cma: respect the device's maximum " Karl Mehltretter
2026-10-09 18:36 ` Jason Gunthorpe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox