Restructure the drm_exec object to work with dma_resv references instead
of GEM object references.

Add the new function dma_exec_lock_resv() to lock individual dma_resv
objects and so allow higher level implementations to handle contention
purely on dma_resv objects.

WIP! Don't commit like that!

Signed-off-by: Christian König <[email protected]>
---
 drivers/gpu/drm/drm_exec.c | 75 ++++++++++++++++++++++----------------
 drivers/gpu/drm/drm_gem.c  |  2 +
 include/drm/drm_exec.h     |  9 +++--
 3 files changed, 50 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c
index fa923852fae45..382bf7bcd5ff3 100644
--- a/drivers/gpu/drm/drm_exec.c
+++ b/drivers/gpu/drm/drm_exec.c
@@ -58,8 +58,11 @@ static void drm_exec_unlock_all(struct drm_exec *exec)
                drm_gem_object_put(obj);
        }
 
-       drm_gem_object_put(exec->prelocked);
-       exec->prelocked = NULL;
+       if (exec->prelocked) {
+               dma_resv_unlock(exec->prelocked);
+               dma_resv_put(exec->prelocked);
+               exec->prelocked = NULL;
+       }
 }
 
 /**
@@ -101,7 +104,7 @@ void drm_exec_fini(struct drm_exec *exec)
        drm_exec_unlock_all(exec);
        kvfree(exec->objects);
        if (exec->contended != DRM_EXEC_DUMMY) {
-               drm_gem_object_put(exec->contended);
+               dma_resv_put(exec->contended);
                ww_acquire_fini(&exec->ticket);
        }
 }
@@ -158,50 +161,41 @@ static int drm_exec_obj_locked(struct drm_exec *exec,
 /* Make sure the contended object is locked first */
 static int drm_exec_lock_contended(struct drm_exec *exec)
 {
-       struct drm_gem_object *obj = exec->contended;
+       struct dma_resv *resv = exec->contended;
        int ret;
 
-       if (likely(!obj))
+       if (likely(!resv))
                return 0;
 
        /* Always cleanup the contention so that error handling can kick in */
        exec->contended = NULL;
        if (exec->flags & DRM_EXEC_INTERRUPTIBLE_WAIT) {
-               ret = dma_resv_lock_slow_interruptible(obj->resv,
-                                                      &exec->ticket);
+               ret = dma_resv_lock_slow_interruptible(resv, &exec->ticket);
                if (unlikely(ret))
                        goto error_dropref;
        } else {
-               dma_resv_lock_slow(obj->resv, &exec->ticket);
+               dma_resv_lock_slow(resv, &exec->ticket);
        }
 
-       ret = drm_exec_obj_locked(exec, obj);
-       if (unlikely(ret))
-               goto error_unlock;
-
-       exec->prelocked = obj;
+       exec->prelocked = resv;
        return 0;
 
-error_unlock:
-       dma_resv_unlock(obj->resv);
-
 error_dropref:
-       drm_gem_object_put(obj);
+       dma_resv_put(resv);
        return ret;
 }
 
 /**
- * drm_exec_lock_obj - lock a GEM object for use
+ * drm_exec_lock_resv - lock a dma_resv object
  * @exec: the drm_exec object with the state
- * @obj: the GEM object to lock
+ * @resv: the dma_resv object to lock
  *
- * Lock a GEM object for use and grab a reference to it.
+ * Lock a dma_resv object for use or grab a reference to it on contention.
  *
  * Returns: -EDEADLK if a contention is detected, -EALREADY when object is
- * already locked (can be suppressed by setting the DRM_EXEC_IGNORE_DUPLICATES
- * flag), -ENOMEM when memory allocation failed and zero for success.
+ * already locked, -ENOMEM when memory allocation failed and zero for success.
  */
-int drm_exec_lock_obj(struct drm_exec *exec, struct drm_gem_object *obj)
+int drm_exec_lock_resv(struct drm_exec *exec, struct dma_resv *resv)
 {
        int ret;
 
@@ -209,22 +203,39 @@ int drm_exec_lock_obj(struct drm_exec *exec, struct 
drm_gem_object *obj)
        if (unlikely(ret))
                return ret;
 
-       if (exec->prelocked == obj) {
-               drm_gem_object_put(exec->prelocked);
+       if (exec->prelocked == resv) {
+               dma_resv_put(exec->prelocked);
                exec->prelocked = NULL;
                return 0;
        }
 
        if (exec->flags & DRM_EXEC_INTERRUPTIBLE_WAIT)
-               ret = dma_resv_lock_interruptible(obj->resv, &exec->ticket);
+               ret = dma_resv_lock_interruptible(resv, &exec->ticket);
        else
-               ret = dma_resv_lock(obj->resv, &exec->ticket);
+               ret = dma_resv_lock(resv, &exec->ticket);
 
-       if (unlikely(ret == -EDEADLK)) {
-               drm_gem_object_get(obj);
-               exec->contended = obj;
-               return -EDEADLK;
-       }
+       if (unlikely(ret == -EDEADLK))
+               exec->contended = dma_resv_get(resv);
+       return ret;
+}
+EXPORT_SYMBOL(drm_exec_lock_resv);
+
+/**
+ * drm_exec_lock_obj - lock a GEM object for use
+ * @exec: the drm_exec object with the state
+ * @obj: the GEM object to lock
+ *
+ * Lock a GEM object for use and grab a reference to it.
+ *
+ * Returns: -EDEADLK if a contention is detected, -EALREADY when object is
+ * already locked (can be suppressed by setting the DRM_EXEC_IGNORE_DUPLICATES
+ * flag), -ENOMEM when memory allocation failed and zero for success.
+ */
+int drm_exec_lock_obj(struct drm_exec *exec, struct drm_gem_object *obj)
+{
+       int ret;
+
+       ret = drm_exec_lock_resv(exec, obj->resv);
 
        if (unlikely(ret == -EALREADY) &&
            exec->flags & DRM_EXEC_IGNORE_DUPLICATES)
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index bbcbd25f014f0..f5cf9ad596a67 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -229,6 +229,8 @@ void drm_gem_private_object_init(struct drm_device *dev,
        obj->size = size;
        mutex_init(&obj->gpuva.lock);
        dma_resv_init(&obj->_resv);
+
+       /* TODO: This needs to go away for drm_exec to work correctly!!! */
        if (!obj->resv)
                obj->resv = dma_resv_get(&obj->_resv);
 
diff --git a/include/drm/drm_exec.h b/include/drm/drm_exec.h
index 8725ba92ff916..9daedb676d7b1 100644
--- a/include/drm/drm_exec.h
+++ b/include/drm/drm_exec.h
@@ -47,14 +47,14 @@ struct drm_exec {
        struct drm_gem_object   **objects;
 
        /**
-        * @contended: contended GEM object we backed off for
+        * @contended: contended dma_resv object we backed off for
         */
-       struct drm_gem_object   *contended;
+       struct dma_resv         *contended;
 
        /**
-        * @prelocked: already locked GEM object due to contention
+        * @prelocked: already locked dma_resv object due to contention
         */
-       struct drm_gem_object *prelocked;
+       struct dma_resv         *prelocked;
 };
 
 /**
@@ -175,6 +175,7 @@ static inline struct ww_acquire_ctx *drm_exec_ticket(struct 
drm_exec *exec)
 void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr);
 void drm_exec_fini(struct drm_exec *exec);
 bool drm_exec_cleanup(struct drm_exec *exec);
+int drm_exec_lock_resv(struct drm_exec *exec, struct dma_resv *resv);
 int drm_exec_lock_obj(struct drm_exec *exec, struct drm_gem_object *obj);
 void drm_exec_unlock_obj(struct drm_exec *exec, struct drm_gem_object *obj);
 int drm_exec_prepare_obj(struct drm_exec *exec, struct drm_gem_object *obj,
-- 
2.43.0

Reply via email to