The only place where it's safe to call drm_gem_lru_remove() is when
we know the drm_gem_object::lru field can't be concurrently updated,
which we know is the case when the drm_gem_object is destroyed.

Rather than trying to make that safe, let's kill the function and inline
its content in drm_gem_object_release().

Signed-off-by: Boris Brezillon <[email protected]>
---
 drivers/gpu/drm/drm_gem.c | 90 ++++++++++++++++++++---------------------------
 include/drm/drm_gem.h     |  1 -
 2 files changed, 39 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 0e087c770883..c85a39b8b163 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1108,6 +1108,15 @@ drm_gem_release(struct drm_device *dev, struct drm_file 
*file_private)
        idr_destroy(&file_private->object_idr);
 }
 
+static void
+drm_gem_lru_remove_locked(struct drm_gem_object *obj)
+{
+       obj->lru->count -= obj->size >> PAGE_SHIFT;
+       WARN_ON(obj->lru->count < 0);
+       list_del(&obj->lru_node);
+       obj->lru = NULL;
+}
+
 /**
  * drm_gem_object_release - release GEM buffer object resources
  * @obj: GEM buffer object
@@ -1118,13 +1127,42 @@ drm_gem_release(struct drm_device *dev, struct drm_file 
*file_private)
 void
 drm_gem_object_release(struct drm_gem_object *obj)
 {
+       struct drm_gem_lru *lru;
+
        if (obj->filp)
                fput(obj->filp);
 
        drm_gem_private_object_fini(obj);
 
        drm_gem_free_mmap_offset(obj);
-       drm_gem_lru_remove(obj);
+
+       /*
+        * We do the lru != NULL check without the lru->lock held, which
+        * means we might end up with a stale lru value by the time the
+        * lock is acquired.
+        *
+        * This is deemed safe because:
+        * 1. the LRU is assumed to outlive any GEM object it was attached
+        *    (LRUs are usually bound to a drm_device). So even if obj->lru
+        *    has become NULL, it still point to a valid object that can
+        *    safely be dereferenced to get the lock.
+        *
+        * 2. all LRUs a GEM object might be attached to must share the same
+        *    lock (lock that's usually part of the driver-specific device
+        *    object), so taking the lock on the 'old' LRU is equivalent
+        *    to taking it on the new one (if any)
+        */
+       lru = obj->lru;
+       if (lru) {
+               guard(mutex)(lru->lock);
+
+               /* Check a second time with the lock held to make sure we're
+                * not racing with the drm_gem_lru_remove_locked() call in
+                * drm_gem_lru_scan().
+                */
+               if (obj->lru)
+                       drm_gem_lru_remove_locked(obj);
+       }
 }
 EXPORT_SYMBOL(drm_gem_object_release);
 
@@ -1552,56 +1590,6 @@ drm_gem_lru_init(struct drm_gem_lru *lru, struct mutex 
*lock)
 }
 EXPORT_SYMBOL(drm_gem_lru_init);
 
-static void
-drm_gem_lru_remove_locked(struct drm_gem_object *obj)
-{
-       obj->lru->count -= obj->size >> PAGE_SHIFT;
-       WARN_ON(obj->lru->count < 0);
-       list_del(&obj->lru_node);
-       obj->lru = NULL;
-}
-
-/**
- * drm_gem_lru_remove - remove object from whatever LRU it is in
- *
- * If the object is currently in any LRU, remove it.
- *
- * @obj: The GEM object to remove from current LRU
- */
-void
-drm_gem_lru_remove(struct drm_gem_object *obj)
-{
-       struct drm_gem_lru *lru = obj->lru;
-
-       /*
-        * We do the lru != NULL check without the lru->lock held, which
-        * means we might end up with a stale lru value by the time the
-        * lock is acquired.
-        *
-        * This is deemed safe because:
-        * 1. the LRU is assumed to outlive any GEM object it was attached
-        *    (LRUs are usually bound to a drm_device). So even if obj->lru
-        *    has become NULL, it still point to a valid object that can
-        *    safely be dereferenced to get the lock.
-        *
-        * 2. all LRUs a GEM object might be attached to must share the same
-        *    lock (lock that's usually part of the driver-specific device
-        *    object), so taking the lock on the 'old' LRU is equivalent
-        *    to taking it on the new one (if any)
-        */
-       if (!lru)
-               return;
-
-       mutex_lock(lru->lock);
-       /* Check a second time with the lock held to make sure we're not racing
-        * with another drm_gem_lru_remove[_locked]() call.
-        */
-       if (obj->lru)
-               drm_gem_lru_remove_locked(obj);
-       mutex_unlock(lru->lock);
-}
-EXPORT_SYMBOL(drm_gem_lru_remove);
-
 /**
  * drm_gem_lru_move_tail_locked - move the object to the tail of the LRU
  *
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index 86f5846154f7..d527df98d142 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -611,7 +611,6 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct 
drm_device *dev,
                            u32 handle, u64 *offset);
 
 void drm_gem_lru_init(struct drm_gem_lru *lru, struct mutex *lock);
-void drm_gem_lru_remove(struct drm_gem_object *obj);
 void drm_gem_lru_move_tail_locked(struct drm_gem_lru *lru, struct 
drm_gem_object *obj);
 void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object 
*obj);
 unsigned long

-- 
2.54.0

Reply via email to