dma-buf: add dma_resv_for_each_fence v3
authorChristian König <christian.koenig@amd.com>
Tue, 15 Jun 2021 13:10:03 +0000 (15:10 +0200)
committerChristian König <christian.koenig@amd.com>
Thu, 7 Oct 2021 12:49:11 +0000 (14:49 +0200)
A simpler version of the iterator to be used when the dma_resv object is
locked.

v2: fix index check here as well
v3: minor coding improvement, some documentation cleanup

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211006123609.2026-1-christian.koenig@amd.com
drivers/dma-buf/dma-resv.c
include/linux/dma-resv.h

index a480af9..2f98caa 100644 (file)
@@ -424,6 +424,57 @@ struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor)
 EXPORT_SYMBOL(dma_resv_iter_next_unlocked);
 
 /**
+ * dma_resv_iter_first - first fence from a locked dma_resv object
+ * @cursor: cursor to record the current position
+ *
+ * Return the first fence in the dma_resv object while holding the
+ * &dma_resv.lock.
+ */
+struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor)
+{
+       struct dma_fence *fence;
+
+       dma_resv_assert_held(cursor->obj);
+
+       cursor->index = 0;
+       if (cursor->all_fences)
+               cursor->fences = dma_resv_shared_list(cursor->obj);
+       else
+               cursor->fences = NULL;
+
+       fence = dma_resv_excl_fence(cursor->obj);
+       if (!fence)
+               fence = dma_resv_iter_next(cursor);
+
+       cursor->is_restarted = true;
+       return fence;
+}
+EXPORT_SYMBOL_GPL(dma_resv_iter_first);
+
+/**
+ * dma_resv_iter_next - next fence from a locked dma_resv object
+ * @cursor: cursor to record the current position
+ *
+ * Return the next fences from the dma_resv object while holding the
+ * &dma_resv.lock.
+ */
+struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor)
+{
+       unsigned int idx;
+
+       dma_resv_assert_held(cursor->obj);
+
+       cursor->is_restarted = false;
+       if (!cursor->fences || cursor->index >= cursor->fences->shared_count)
+               return NULL;
+
+       idx = cursor->index++;
+       return rcu_dereference_protected(cursor->fences->shared[idx],
+                                        dma_resv_held(cursor->obj));
+}
+EXPORT_SYMBOL_GPL(dma_resv_iter_next);
+
+/**
  * dma_resv_copy_fences - Copy all fences from src to dst.
  * @dst: the destination reservation object
  * @src: the source reservation object
index 764138a..491359c 100644 (file)
@@ -179,6 +179,8 @@ struct dma_resv_iter {
 
 struct dma_fence *dma_resv_iter_first_unlocked(struct dma_resv_iter *cursor);
 struct dma_fence *dma_resv_iter_next_unlocked(struct dma_resv_iter *cursor);
+struct dma_fence *dma_resv_iter_first(struct dma_resv_iter *cursor);
+struct dma_fence *dma_resv_iter_next(struct dma_resv_iter *cursor);
 
 /**
  * dma_resv_iter_begin - initialize a dma_resv_iter object
@@ -244,6 +246,24 @@ static inline bool dma_resv_iter_is_restarted(struct dma_resv_iter *cursor)
        for (fence = dma_resv_iter_first_unlocked(cursor);              \
             fence; fence = dma_resv_iter_next_unlocked(cursor))
 
+/**
+ * dma_resv_for_each_fence - fence iterator
+ * @cursor: a struct dma_resv_iter pointer
+ * @obj: a dma_resv object pointer
+ * @all_fences: true if all fences should be returned
+ * @fence: the current fence
+ *
+ * Iterate over the fences in a struct dma_resv object while holding the
+ * &dma_resv.lock. @all_fences controls if the shared fences are returned as
+ * well. The cursor initialisation is part of the iterator and the fence stays
+ * valid as long as the lock is held and so no extra reference to the fence is
+ * taken.
+ */
+#define dma_resv_for_each_fence(cursor, obj, all_fences, fence)        \
+       for (dma_resv_iter_begin(cursor, obj, all_fences),      \
+            fence = dma_resv_iter_first(cursor); fence;        \
+            fence = dma_resv_iter_next(cursor))
+
 #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
 #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)