Thread (13 messages) 13 messages, 3 authors, 2026-03-30

Re: [PATCH v3 3/3] drm/gem-dma: Support DRM_MODE_DUMB_KERNEL_MAP flag

From: Chen-Yu Tsai <wenst@chromium.org>
Date: 2026-03-27 05:46:53
Also in: dri-devel, lkml

On Thu, Mar 26, 2026 at 6:03 PM Chen-Yu Tsai [off-list ref] wrote:
quoted hunk ↗ jump to hunk
From: Rob Herring <robh@kernel.org>

Add support in DMA helpers to handle callers specifying
DRM_MODE_DUMB_KERNEL_MAP flag. Existing behavior is maintained with this
change. drm_gem_dma_dumb_create() always creates a kernel mapping as
before. drm_gem_dma_dumb_create_internal() lets the caller set the flags
as desired.

drm_gem_dma_dumb_create_internal() users have DRM_MODE_DUMB_KERNEL_MAP
added to preserve existing behavior.

A dumb buffer allocated from these devices can be shared (exported) to
another device. The consuming device may require the kernel mapping to
scan out the buffer to its own display. Such devices include DisplayLink
and various MIPI DBI based displays. Therefore altering the behavior
should be given much consideration.

Signed-off-by: Rob Herring <robh@kernel.org>
[wenst@chromium.org: Rebase onto renamed GEM DMA helpers]
[wenst@chromium.org: show "vaddr=(no mapping)" in drm_gem_dma_print_info()]
[wenst@chromium.org: Add DRM_MODE_DUMB_KERNEL_MAP to new drivers]
[wenst@chromium.org: Add flags field to drm_gem_dma_create_with_handle()
                     kerneldoc]
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
Changes since v2:
- Added back DRM_MODE_DUMB_KERNEL_MAP flag to all drivers calling
  drm_gem_dma_dumb_create_internal()
- Expanded commit message to cover display drivers needing the kernel
  mapping to do scan out

Changes since v1:
- Rebased onto renamed GEM DMA helpers
- Added check in drm_fb_dma_get_scanout_buffer() and drm_gem_dma_vmap().
- Made drm_gem_dma_print_info() show "vaddr=(no mapping)" for objects
  allocated without kernel mapping
- Dropped existing DRM_MODE_DUMB_KERNEL_MAP flag addition in various
  drivers
- Added DRM_MODE_DUMB_KERNEL_MAP flag to adp_drm_gem_dumb_create()
- Added flags field kerneldoc for drm_gem_dma_create_with_handle()

Cc: Sasha Finkelstein <redacted>
Cc: Janne Grunau <j@jannau.net>
Cc: Liviu Dudau <liviu.dudau@arm.com>
Cc: Paul Kocialkowski <paulk@sys-base.io>
Cc: Neil Armstrong <neil.armstrong@linaro.org>
Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Cc: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Cc: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
Cc: Biju Das <biju.das.jz@bp.renesas.com>
Cc: Yannick Fertre <yannick.fertre@foss.st.com>
Cc: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
Cc: Philippe Cornu <philippe.cornu@foss.st.com>
Cc: Jernej Skrabec <jernej.skrabec@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>
Cc: "Maíra Canal" <mcanal@igalia.com>
Cc: Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.com>
Cc: Icenowy Zheng <zhengxingda@iscas.ac.cn>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 drivers/gpu/drm/adp/adp_drv.c                 |  1 +
 .../gpu/drm/arm/display/komeda/komeda_kms.c   |  1 +
 drivers/gpu/drm/arm/malidp_drv.c              |  1 +
 drivers/gpu/drm/drm_fb_dma_helper.c           |  4 ++
 drivers/gpu/drm/drm_gem_dma_helper.c          | 67 ++++++++++++-------
 drivers/gpu/drm/logicvc/logicvc_drm.c         |  1 +
 drivers/gpu/drm/meson/meson_drv.c             |  1 +
 drivers/gpu/drm/renesas/rcar-du/rcar_du_kms.c |  2 +
 drivers/gpu/drm/renesas/rz-du/rzg2l_du_kms.c  |  1 +
 drivers/gpu/drm/stm/drv.c                     |  3 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c             |  1 +
 drivers/gpu/drm/vc4/vc4_drv.c                 |  2 +
 drivers/gpu/drm/verisilicon/vs_drm.c          |  2 +
 drivers/gpu/drm/xlnx/zynqmp_kms.c             |  2 +
 14 files changed, 63 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/adp/adp_drv.c b/drivers/gpu/drm/adp/adp_drv.c
index 4554cf75565e..c549b44b3814 100644
--- a/drivers/gpu/drm/adp/adp_drv.c
+++ b/drivers/gpu/drm/adp/adp_drv.c
@@ -95,6 +95,7 @@ static int adp_drm_gem_dumb_create(struct drm_file *file_priv,
 {
        args->height = ALIGN(args->height, 64);
        args->size = args->pitch * args->height;
+       args->flags = DRM_MODE_DUMB_KERNEL_MAP;

        return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
 }
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 6ed504099188..2c096ebaea33 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -29,6 +29,7 @@ static int komeda_gem_dma_dumb_create(struct drm_file *file,
        struct komeda_dev *mdev = dev->dev_private;
        u32 pitch = DIV_ROUND_UP(args->width * args->bpp, 8);

+       args->flags = DRM_MODE_DUMB_KERNEL_MAP;
        args->pitch = ALIGN(pitch, mdev->chip.bus_width);

        return drm_gem_dma_dumb_create_internal(file, dev, args);
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index b765f6c9eea4..5519f48a27c0 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -464,6 +464,7 @@ static int malidp_dumb_create(struct drm_file *file_priv,
        /* allocate for the worst case scenario, i.e. rotated buffers */
        u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 1);

+       args->flags = DRM_MODE_DUMB_KERNEL_MAP;
        args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment);

        return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c
index fd71969d2fb1..12a44accc48c 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -187,6 +187,10 @@ int drm_fb_dma_get_scanout_buffer(struct drm_plane *plane,
        if (!dma_obj->vaddr)
                return -ENODEV;

+       /* Buffer was allocated with NO_KERNEL_MAPPING */
+       if (dma_obj->dma_attrs & DMA_ATTR_NO_KERNEL_MAPPING)
+               return -ENODEV;
+
        iosys_map_set_vaddr(&sb->map[0], dma_obj->vaddr);
        sb->format = fb->format;
        sb->height = fb->height;
diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c
index 9722c9fc86f3..281fb563f061 100644
--- a/drivers/gpu/drm/drm_gem_dma_helper.c
+++ b/drivers/gpu/drm/drm_gem_dma_helper.c
@@ -116,26 +116,8 @@ __drm_gem_dma_create(struct drm_device *drm, size_t size, bool private)
        return ERR_PTR(ret);
 }

-/**
- * drm_gem_dma_create - allocate an object with the given size
- * @drm: DRM device
- * @size: size of the object to allocate
- *
- * This function creates a DMA GEM object and allocates memory as backing store.
- * The allocated memory will occupy a contiguous chunk of bus address space.
- *
- * For devices that are directly connected to the memory bus then the allocated
- * memory will be physically contiguous. For devices that access through an
- * IOMMU, then the allocated memory is not expected to be physically contiguous
- * because having contiguous IOVAs is sufficient to meet a devices DMA
- * requirements.
- *
- * Returns:
- * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
- * error code on failure.
- */
-struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
-                                             size_t size)
+static struct drm_gem_dma_object *
+drm_gem_dma_create_flags(struct drm_device *drm, size_t size, u32 flags)
 {
        struct drm_gem_dma_object *dma_obj;
        int ret;
@@ -146,6 +128,9 @@ struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
        if (IS_ERR(dma_obj))
                return dma_obj;

+       if (!(flags & DRM_MODE_DUMB_KERNEL_MAP))
+               dma_obj->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
+
        if (dma_obj->map_noncoherent) {
                dma_obj->vaddr = dma_alloc_noncoherent(drm_dev_dma_dev(drm),
                                                       size,
@@ -171,6 +156,30 @@ struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
        drm_gem_object_put(&dma_obj->base);
        return ERR_PTR(ret);
 }
+
+/**
+ * drm_gem_dma_create - allocate an object with the given size
+ * @drm: DRM device
+ * @size: size of the object to allocate
+ *
+ * This function creates a DMA GEM object and allocates memory as backing store.
+ * The allocated memory will occupy a contiguous chunk of bus address space.
+ *
+ * For devices that are directly connected to the memory bus then the allocated
+ * memory will be physically contiguous. For devices that access through an
+ * IOMMU, then the allocated memory is not expected to be physically contiguous
+ * because having contiguous IOVAs is sufficient to meet a devices DMA
+ * requirements.
+ *
+ * Returns:
+ * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
+                                             size_t size)
+{
+       return drm_gem_dma_create_flags(drm, size, DRM_MODE_DUMB_KERNEL_MAP);
+}
 EXPORT_SYMBOL_GPL(drm_gem_dma_create);

 /**
@@ -179,6 +188,7 @@ EXPORT_SYMBOL_GPL(drm_gem_dma_create);
  * @file_priv: DRM file-private structure to register the handle for
  * @drm: DRM device
  * @size: size of the object to allocate
+ * @flags: DRM_MODE_DUMB_* flags if any
  * @handle: return location for the GEM handle
  *
  * This function creates a DMA GEM object, allocating a chunk of memory as
@@ -194,14 +204,14 @@ EXPORT_SYMBOL_GPL(drm_gem_dma_create);
  */
 static struct drm_gem_dma_object *
 drm_gem_dma_create_with_handle(struct drm_file *file_priv,
-                              struct drm_device *drm, size_t size,
+                              struct drm_device *drm, size_t size, u32 flags,
                               uint32_t *handle)
 {
        struct drm_gem_dma_object *dma_obj;
        struct drm_gem_object *gem_obj;
        int ret;

-       dma_obj = drm_gem_dma_create(drm, size);
+       dma_obj = drm_gem_dma_create_flags(drm, size, DRM_MODE_DUMB_KERNEL_MAP);
Sashiko pointed out an obvious (to me now) error here: this should pass
`flags`, not the flag directly.

ChenYu
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help