On 1/18/2026 12:35 PM, Farah Kassabri wrote:
> Add drm_gem_prime_self_import() to detect and handle the case where a
> PRIME dma-buf being imported was exported by the same DRM device.
>
> When the dma-buf originates from the importing device and uses the
> expected dma-buf ops, the helper returns the associated GEM object and
> takes an extra reference on it. This allows drivers to bypass the
> generic PRIME import path and avoid taking an additional reference on
> the dma-buf file.
>
> The helper simplifies self-import handling and avoids duplication of
> this pattern across DRM drivers.
>
> Signed-off-by: Farah Kassabri <[email protected]>
> ---
>  drivers/gpu/drm/drm_prime.c | 48 ++++++++++++++++++++++++++++++-------
>  include/drm/drm_prime.h     |  5 +++-
>  2 files changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> index 21809a82187b..6c9ad3957f42 100644
> --- a/drivers/gpu/drm/drm_prime.c
> +++ b/drivers/gpu/drm/drm_prime.c
> @@ -974,15 +974,9 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct 
> drm_device *dev,
>       struct drm_gem_object *obj;
>       int ret;
>  
> -     if (drm_gem_is_prime_exported_dma_buf(dev, dma_buf)) {
> -             /*
> -              * Importing dmabuf exported from our own gem increases
> -              * refcount on gem itself instead of f_count of dmabuf.
> -              */
> -             obj = dma_buf->priv;
> -             drm_gem_object_get(obj);
> +     obj = drm_gem_prime_self_import(dev, dma_buf, 
> &drm_gem_prime_dmabuf_ops);
> +     if (obj)
>               return obj;
> -     }
>  
>       if (!dev->driver->gem_prime_import_sg_table)
>               return ERR_PTR(-EINVAL);
> @@ -1116,3 +1110,41 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, 
> struct sg_table *sg)
>       dma_buf_put(dma_buf);
>  }
>  EXPORT_SYMBOL(drm_prime_gem_destroy);
> +
> +/**
> + * drm_gem_prime_self_import - Attempt to import a dma-buf exported by this 
> DRM device
> + * @dev: DRM device performing the import
> + * @dma_buf: dma-buf to import
> + * @expected_ops: dma-buf ops used by this driver
> + *
> + * If @dma_buf was exported by this DRM device using @expected_ops, return 
> the
> + * corresponding GEM object and take an extra reference on it. In this case,
> + * the import avoids taking a reference on the dma-buf file and instead bumps
> + * the GEM object's refcount directly.
> + *
> + * Returns:
> + * A referenced GEM object on success, or %NULL if the dma-buf was not 
> exported
> + * by this device or does not match @expected_ops.
> + */
> +struct drm_gem_object *drm_gem_prime_self_import(struct drm_device *dev,
> +                                              struct dma_buf *dma_buf,
> +                                              const struct dma_buf_ops 
> *expected_ops)
> +{
> +     struct drm_gem_object *obj;
> +
> +     if (dma_buf->ops != expected_ops)
> +             return NULL;
> +
> +     obj = dma_buf->priv;
> +     if (!obj || obj->dev != dev)

I think checking obj for NULL is redundant. struct dma_buf * is instantiated by 
dma_buf_export,
which assigns the priv member based on priv field in dma_buf_export_info and 
validates that it is not NULL.
All the drivers that implement this pattern (grep "Importing dmabuf exported") 
do not check it.

- Ilia


> +             return NULL;
> +
> +     /*
> +      * Importing dmabuf exported from our own gem increases
> +      * refcount on gem itself instead of f_count of dmabuf.
> +      */
> +     drm_gem_object_get(obj);
> +
> +     return obj;
> +}
> +EXPORT_SYMBOL(drm_gem_prime_self_import);
> diff --git a/include/drm/drm_prime.h b/include/drm/drm_prime.h
> index f50f862f0d8b..4cdb543b9eb7 100644
> --- a/include/drm/drm_prime.h
> +++ b/include/drm/drm_prime.h
> @@ -54,6 +54,7 @@ struct device;
>  struct dma_buf_export_info;
>  struct dma_buf;
>  struct dma_buf_attachment;
> +struct dma_buf_ops;
>  struct iosys_map;
>  
>  enum dma_data_direction;
> @@ -108,6 +109,9 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct 
> drm_device *dev,
>                                               struct device *attach_dev);
>  struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
>                                           struct dma_buf *dma_buf);
> +struct drm_gem_object *drm_gem_prime_self_import(struct drm_device *dev,
> +                                              struct dma_buf *dma_buf,
> +                                              const struct dma_buf_ops 
> *expected_ops);
>  
>  void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
>  
> @@ -115,5 +119,4 @@ int drm_prime_sg_to_page_array(struct sg_table *sgt, 
> struct page **pages,
>                              int max_pages);
>  int drm_prime_sg_to_dma_addr_array(struct sg_table *sgt, dma_addr_t *addrs,
>                                  int max_pages);
> -
>  #endif /* __DRM_PRIME_H__ */


Reply via email to