Re: [PATCH v3 3/3] drm/gem-dma: Support DRM_MODE_DUMB_KERNEL_MAP flag
From: Chen-Yu Tsai
Date: Fri Mar 27 2026 - 01:47:01 EST
On Thu, Mar 26, 2026 at 6:03 PM Chen-Yu Tsai <wenst@xxxxxxxxxxxx> wrote:
>
> From: Rob Herring <robh@xxxxxxxxxx>
>
> 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@xxxxxxxxxx>
> [wenst@xxxxxxxxxxxx: Rebase onto renamed GEM DMA helpers]
> [wenst@xxxxxxxxxxxx: show "vaddr=(no mapping)" in drm_gem_dma_print_info()]
> [wenst@xxxxxxxxxxxx: Add DRM_MODE_DUMB_KERNEL_MAP to new drivers]
> [wenst@xxxxxxxxxxxx: Add flags field to drm_gem_dma_create_with_handle()
> kerneldoc]
> Signed-off-by: Chen-Yu Tsai <wenst@xxxxxxxxxxxx>
> ---
> 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 <fnkl.kernel@xxxxxxxxx>
> Cc: Janne Grunau <j@xxxxxxxxxx>
> Cc: Liviu Dudau <liviu.dudau@xxxxxxx>
> Cc: Paul Kocialkowski <paulk@xxxxxxxxxxx>
> Cc: Neil Armstrong <neil.armstrong@xxxxxxxxxx>
> Cc: Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx>
> Cc: Tomi Valkeinen <tomi.valkeinen+renesas@xxxxxxxxxxxxxxxx>
> Cc: Kieran Bingham <kieran.bingham+renesas@xxxxxxxxxxxxxxxx>
> Cc: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
> Cc: Yannick Fertre <yannick.fertre@xxxxxxxxxxx>
> Cc: Raphael Gallais-Pou <raphael.gallais-pou@xxxxxxxxxxx>
> Cc: Philippe Cornu <philippe.cornu@xxxxxxxxxxx>
> Cc: Jernej Skrabec <jernej.skrabec@xxxxxxxxx>
> Cc: Maxime Ripard <mripard@xxxxxxxxxx>
> Cc: Dave Stevenson <dave.stevenson@xxxxxxxxxxxxxxx>
> Cc: "Maíra Canal" <mcanal@xxxxxxxxxx>
> Cc: Raspberry Pi Kernel Maintenance <kernel-list@xxxxxxxxxxxxxxx>
> Cc: Icenowy Zheng <zhengxingda@xxxxxxxxxxx>
> Cc: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
> Cc: Tomi Valkeinen <tomi.valkeinen@xxxxxxxxxxxxxxxx>
> ---
> 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