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__ */
