]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/gem/shmem: Introduce __drm_gem_shmem_free_sgt_locked()
authorLyude Paul <lyude@redhat.com>
Fri, 29 May 2026 18:34:03 +0000 (14:34 -0400)
committerLyude Paul <lyude@redhat.com>
Tue, 2 Jun 2026 17:16:40 +0000 (13:16 -0400)
One of the complications of trying to use the shmem helpers to create a
scatterlist for shmem objects is that we need to be able to provide a
guarantee that the driver cannot be unbound for the lifetime of the
scatterlist.

The easiest way of handling this seems to be just hooking up an unmap
operation to devres the first time we create a scatterlist, which allows us
to still take advantage of gem shmem facilities without breaking that
guarantee. To allow for this, we extract __drm_gem_shmem_free_sgt_locked()
- which allows a caller (e.g. the rust bindings) to manually unmap the sgt
for a gem object as needed.

Signed-off-by: Lyude Paul <lyude@redhat.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260529183702.677677-6-lyude@redhat.com
drivers/gpu/drm/drm_gem_shmem_helper.c
include/drm/drm_gem_shmem_helper.h

index 545933c7f71214e9d675225793d9437be397f06a..c989459eb2159105f8eaf72d6789e84d4695b616 100644 (file)
@@ -158,6 +158,30 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t
 }
 EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
 
+/**
+ * __drm_gem_shmem_release_sgt_locked - Unpin and DMA unmap pages, and release the
+ * cached scatter/gather table for an shmem GEM object.
+ * @shmem: shmem GEM object
+ *
+ * If the passed shmem object has an active scatter/gather table for driver
+ * usage, this function will unmap it and release the memory associated with it.
+ * It is the responsibility of the caller to ensure it holds the dma_resv_lock
+ * for this object.
+ *
+ * Drivers should not need to call this function themselves, it is mainly
+ * intended for usage in the Rust shmem bindings.
+ */
+void __drm_gem_shmem_free_sgt_locked(struct drm_gem_shmem_object *shmem)
+{
+       dma_resv_assert_held(shmem->base.resv);
+
+       dma_unmap_sgtable(shmem->base.dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0);
+       sg_free_table(shmem->sgt);
+       kfree(shmem->sgt);
+       shmem->sgt = NULL;
+}
+EXPORT_SYMBOL_GPL(__drm_gem_shmem_free_sgt_locked);
+
 /**
  * drm_gem_shmem_release - Release resources associated with a shmem GEM object.
  * @shmem: shmem GEM object
@@ -176,12 +200,8 @@ void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem)
 
                drm_WARN_ON(obj->dev, refcount_read(&shmem->vmap_use_count));
 
-               if (shmem->sgt) {
-                       dma_unmap_sgtable(obj->dev->dev, shmem->sgt,
-                                         DMA_BIDIRECTIONAL, 0);
-                       sg_free_table(shmem->sgt);
-                       kfree(shmem->sgt);
-               }
+               if (shmem->sgt)
+                       __drm_gem_shmem_free_sgt_locked(shmem);
                if (shmem->pages)
                        drm_gem_shmem_put_pages_locked(shmem);
 
index 5ccdae21b94a97fe5e5b442f1a8ec8554f747a50..b2c23af628e1aba875362de79c0b754e448523e0 100644 (file)
@@ -111,6 +111,7 @@ int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shme
 struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);
 void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem);
 void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);
+void __drm_gem_shmem_free_sgt_locked(struct drm_gem_shmem_object *shmem);
 
 void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem);
 int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem);