[PATCH 08/11] dma-buf: improve shared fence abstraction

Christian König ckoenig.leichtzumerken at gmail.com
Mon May 17 14:11:26 UTC 2021


Put access to the shared fences behind an interator.
This way we don't need to expose the internal implementation any more.

Signed-off-by: Christian König <christian.koenig at amd.com>
---
 drivers/dma-buf/dma-buf.c                   | 46 ++++++----------
 drivers/dma-buf/dma-resv.c                  | 61 +++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c |  9 +--
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c    | 14 ++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c     | 14 ++---
 drivers/gpu/drm/etnaviv/etnaviv_gem.c       | 15 ++---
 drivers/gpu/drm/i915/gem/i915_gem_busy.c    | 16 ++----
 drivers/gpu/drm/nouveau/nouveau_fence.c     | 24 ++++----
 drivers/gpu/drm/qxl/qxl_debugfs.c           | 10 ++--
 drivers/gpu/drm/radeon/radeon_sync.c        | 14 ++---
 drivers/gpu/drm/ttm/ttm_bo.c                | 15 ++---
 include/linux/dma-resv.h                    | 40 ++++++--------
 12 files changed, 140 insertions(+), 138 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 5abf6b8c89ac..c51c1fca4c1b 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -206,12 +206,12 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
 
 static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 {
+	struct dma_fence *fence_excl, *fence_shared;
+	struct dma_resv_cursor cursor;
 	struct dma_buf *dmabuf;
 	struct dma_resv *resv;
-	struct dma_resv_list *fobj;
-	struct dma_fence *fence_excl;
 	__poll_t events;
-	unsigned shared_count, seq;
+	unsigned seq;
 
 	dmabuf = file->private_data;
 	if (!dmabuf || !dmabuf->resv)
@@ -229,22 +229,18 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 	seq = read_seqcount_begin(&resv->seq);
 	rcu_read_lock();
 
-	fobj = rcu_dereference(resv->fence);
-	if (fobj)
-		shared_count = fobj->shared_count;
-	else
-		shared_count = 0;
+	fence_shared = dma_resv_first_shared(resv, &cursor);
 	fence_excl = dma_resv_exclusive(resv);
 	if (read_seqcount_retry(&resv->seq, seq)) {
 		rcu_read_unlock();
 		goto retry;
 	}
 
-	if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) {
+	if (fence_excl && (!(events & EPOLLOUT) || !fence_shared)) {
 		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
 		__poll_t pevents = EPOLLIN;
 
-		if (shared_count == 0)
+		if (fence_shared)
 			pevents |= EPOLLOUT;
 
 		spin_lock_irq(&dmabuf->poll.lock);
@@ -275,9 +271,8 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 		}
 	}
 
-	if ((events & EPOLLOUT) && shared_count > 0) {
+	if ((events & EPOLLOUT) && fence_shared) {
 		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_shared;
-		int i;
 
 		/* Only queue a new callback if no event has fired yet */
 		spin_lock_irq(&dmabuf->poll.lock);
@@ -290,13 +285,11 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 		if (!(events & EPOLLOUT))
 			goto out;
 
-		for (i = 0; i < shared_count; ++i) {
-			struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
-
-			if (!dma_fence_get_rcu(fence)) {
+		do {
+			if (!dma_fence_get_rcu(fence_shared)) {
 				/*
 				 * fence refcount dropped to zero, this means
-				 * that fobj has been freed
+				 * that the shared fence has been freed
 				 *
 				 * call dma_buf_poll_cb and force a recheck!
 				 */
@@ -304,17 +297,17 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 				dma_buf_poll_cb(NULL, &dcb->cb);
 				break;
 			}
-			if (!dma_fence_add_callback(fence, &dcb->cb,
+			if (!dma_fence_add_callback(fence_shared, &dcb->cb,
 						    dma_buf_poll_cb)) {
-				dma_fence_put(fence);
+				dma_fence_put(fence_shared);
 				events &= ~EPOLLOUT;
 				break;
 			}
-			dma_fence_put(fence);
-		}
+			dma_fence_put(fence_shared);
+		} while ((fence_shared = dma_resv_next_shared(resv, &cursor)));
 
 		/* No callback queued, wake up any additional waiters. */
-		if (i == shared_count)
+		if (!fence_shared)
 			dma_buf_poll_cb(NULL, &dcb->cb);
 	}
 
@@ -1353,10 +1346,9 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 	struct dma_buf *buf_obj;
 	struct dma_buf_attachment *attach_obj;
 	struct dma_resv *robj;
-	struct dma_resv_list *fobj;
 	struct dma_fence *fence;
 	unsigned seq;
-	int count = 0, attach_count, shared_count, i;
+	int count = 0, attach_count;
 	size_t size = 0;
 
 	ret = mutex_lock_interruptible(&db_list.lock);
@@ -1369,6 +1361,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 		   "size", "flags", "mode", "count", "ino");
 
 	list_for_each_entry(buf_obj, &db_list.head, list_node) {
+		struct dma_resv_cursor cursor;
 
 		ret = dma_resv_lock_interruptible(buf_obj->resv, NULL);
 		if (ret)
@@ -1392,10 +1385,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 				   fence->ops->get_timeline_name(fence),
 				   dma_fence_is_signaled(fence) ? "" : "un");
 
-		fobj = rcu_dereference(robj->fence);
-		shared_count = fobj ? fobj->shared_count : 0;
-		for (i = 0; i < shared_count; i++) {
-			fence = rcu_dereference(fobj->shared[i]);
+		dma_resv_for_each_shared(robj, &cursor, fence) {
 			if (!dma_fence_get_rcu(fence))
 				continue;
 			seq_printf(s, "\tShared fence: %s %s %ssignalled\n",
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 5703e328b8ac..ef7e0464e08d 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -39,6 +39,19 @@
 #include <linux/sched/mm.h>
 #include <linux/mmu_notifier.h>
 
+/**
+ * struct dma_resv_list - a list of shared fences
+ * @rcu: for internal use
+ * @shared_count: table of shared fences
+ * @shared_max: for growing shared fence table
+ * @shared: shared fence table
+ */
+struct dma_resv_list {
+	struct rcu_head rcu;
+	u32 shared_count, shared_max;
+	struct dma_fence __rcu *shared[];
+};
+
 /**
  * DOC: Reservation Object Overview
  *
@@ -146,6 +159,54 @@ void dma_resv_fini(struct dma_resv *obj)
 }
 EXPORT_SYMBOL(dma_resv_fini);
 
+/**
+ * dma_resv_shared - get the reservation object's shared fence list
+ * @obj: the reservation object
+ *
+ * Returns the shared fence list. The obj->lock or rcu read side must be held.
+ */
+static inline struct dma_resv_list *dma_resv_shared(struct dma_resv *obj)
+{
+	return rcu_dereference_check(obj->fence, dma_resv_held(obj));
+}
+
+/**
+ * dma_resv_first_shared - get first shared fence
+ * @obj: the reservation object
+ * @cursor: cursor to record the position
+ *
+ * Return the first shared fence of the resv object and initialize the cursor to
+ * track the position inside the list.
+ */
+struct dma_fence *dma_resv_first_shared(struct dma_resv *obj,
+					struct dma_resv_cursor *cursor)
+{
+	cursor->fences = dma_resv_shared(obj);
+	if (!cursor->fences)
+		return NULL;
+
+	cursor->i = 0;
+	return dma_resv_next_shared(obj, cursor);
+}
+EXPORT_SYMBOL(dma_resv_first_shared);
+
+/**
+ * dma_resv_next_shared - get the next shared fence from the resv object
+ * @obj: the reservation object
+ * @cursor: cursor to record the position
+ *
+ * Return the next shared fence of the resv object where cursor points to.
+ */
+struct dma_fence *dma_resv_next_shared(struct dma_resv *obj,
+				       struct dma_resv_cursor *cursor)
+{
+	if (cursor->i >= cursor->fences->shared_count)
+		return NULL;
+
+	return dma_resv_list_fence(obj, cursor->fences, cursor->i++);
+}
+EXPORT_SYMBOL(dma_resv_next_shared);
+
 /**
  * dma_resv_reserve_shared - Reserve space to add shared fences to
  * a dma_resv.
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 0371947ba96b..67cef80e25c8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -95,20 +95,15 @@ __dma_resv_make_exclusive(struct dma_resv *obj)
 	unsigned int count;
 	int r;
 
-	if (!dma_resv_shared(obj)) /* no shared fences to convert */
-		return 0;
-
 	r = dma_resv_get_fences_rcu(obj, NULL, &count, &fences);
 	if (r)
 		return r;
 
-	if (count == 0) {
-		/* Now that was unexpected. */
-	} else if (count == 1) {
+	if (count == 1) {
 		dma_resv_add_excl_fence(obj, fences[0]);
 		dma_fence_put(fences[0]);
 		kfree(fences);
-	} else {
+	} else if (count > 1) {
 		struct dma_fence_array *array;
 
 		array = dma_fence_array_create(count, fences,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index c50d9f92a0cd..a4478332a79e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -201,10 +201,9 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
 		     struct dma_resv *resv, enum amdgpu_sync_mode mode,
 		     void *owner)
 {
-	struct dma_resv_list *flist;
+	struct dma_resv_cursor cursor;
 	struct dma_fence *f;
-	unsigned i;
-	int r = 0;
+	int r;
 
 	if (resv == NULL)
 		return -EINVAL;
@@ -212,17 +211,12 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
 	/* always sync to the exclusive fence */
 	f = dma_resv_exclusive(resv);
 	r = amdgpu_sync_fence(sync, f);
-
-	flist = dma_resv_shared(resv);
-	if (!flist || r)
+	if (r)
 		return r;
 
-	for (i = 0; i < flist->shared_count; ++i) {
+	dma_resv_for_each_shared(resv, &cursor, f) {
 		void *fence_owner;
 
-		f = rcu_dereference_protected(flist->shared[i],
-					      dma_resv_held(resv));
-
 		fence_owner = amdgpu_sync_get_owner(f);
 
 		/* Always sync to moves, no matter what */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 6ab50810bd54..ba89e35c1b84 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1394,10 +1394,9 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
 					    const struct ttm_place *place)
 {
 	unsigned long num_pages = bo->mem.num_pages;
+	struct dma_resv_cursor resv_cursor;
 	struct amdgpu_res_cursor cursor;
-	struct dma_resv_list *flist;
 	struct dma_fence *f;
-	int i;
 
 	if (bo->type == ttm_bo_type_kernel &&
 	    !amdgpu_vm_evictable(ttm_to_amdgpu_bo(bo)))
@@ -1407,14 +1406,9 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
 	 * If true, then return false as any KFD process needs all its BOs to
 	 * be resident to run successfully
 	 */
-	flist = dma_resv_shared(bo->base.resv);
-	if (flist) {
-		for (i = 0; i < flist->shared_count; ++i) {
-			f = rcu_dereference_protected(flist->shared[i],
-				dma_resv_held(bo->base.resv));
-			if (amdkfd_fence_check_mm(f, current->mm))
-				return false;
-		}
+	dma_resv_for_each_shared(bo->base.resv, &resv_cursor, f) {
+		if (amdkfd_fence_check_mm(f, current->mm))
+			return false;
 	}
 
 	switch (bo->mem.mem_type) {
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 4d43b8630f0e..52e9eaa43f2e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -450,10 +450,10 @@ static void etnaviv_gem_describe_fence(struct dma_fence *fence,
 static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 {
 	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	unsigned long off = drm_vma_node_start(&obj->vma_node);
 	struct dma_resv *robj = obj->resv;
-	struct dma_resv_list *fobj;
+	struct dma_resv_cursor cursor;
 	struct dma_fence *fence;
-	unsigned long off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
 			etnaviv_obj->flags, is_active(etnaviv_obj) ? 'A' : 'I',
@@ -461,15 +461,8 @@ static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 			off, etnaviv_obj->vaddr, obj->size);
 
 	rcu_read_lock();
-	fobj = dma_resv_shared(robj);
-	if (fobj) {
-		unsigned int i, shared_count = fobj->shared_count;
-
-		for (i = 0; i < shared_count; i++) {
-			fence = rcu_dereference(fobj->shared[i]);
-			etnaviv_gem_describe_fence(fence, "Shared", m);
-		}
-	}
+	dma_resv_for_each_shared(robj, &cursor, fence)
+		etnaviv_gem_describe_fence(fence, "Shared", m);
 
 	fence = dma_resv_exclusive(robj);
 	if (fence)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
index 3f94becac541..1028df6cee67 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -82,7 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_i915_gem_busy *args = data;
 	struct drm_i915_gem_object *obj;
-	struct dma_resv_list *list;
+	struct dma_resv_cursor cursor;
+	struct dma_fence *fence;
 	unsigned int seq;
 	int err;
 
@@ -116,17 +117,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 	args->busy = busy_check_writer(dma_resv_exclusive(obj->base.resv));
 
 	/* Translate shared fences to READ set of engines */
-	list = dma_resv_shared(obj->base.resv);
-	if (list) {
-		unsigned int shared_count = list->shared_count, i;
-
-		for (i = 0; i < shared_count; ++i) {
-			struct dma_fence *fence =
-				rcu_dereference(list->shared[i]);
-
-			args->busy |= busy_check_reader(fence);
-		}
-	}
+	dma_resv_for_each_shared(obj->base.resv, &cursor, fence)
+		args->busy |= busy_check_reader(fence);
 
 	if (args->busy && read_seqcount_retry(&obj->base.resv->seq, seq))
 		goto retry;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 5ce441c655ea..9efe47932b42 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -342,11 +342,11 @@ int
 nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive, bool intr)
 {
 	struct nouveau_fence_chan *fctx = chan->fence;
-	struct dma_fence *fence;
 	struct dma_resv *resv = nvbo->bo.base.resv;
-	struct dma_resv_list *fobj;
+	struct dma_fence *fence, *shared;
+	struct dma_resv_cursor cursor;
 	struct nouveau_fence *f;
-	int ret = 0, i;
+	int ret = 0;
 
 	if (!exclusive) {
 		ret = dma_resv_reserve_shared(resv, 1);
@@ -355,10 +355,10 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 			return ret;
 	}
 
-	fobj = dma_resv_shared(resv);
+	shared = dma_resv_first_shared(resv, &cursor);
 	fence = dma_resv_exclusive(resv);
 
-	if (fence && (!exclusive || !fobj || !fobj->shared_count)) {
+	if (fence && (!exclusive || !shared)) {
 		struct nouveau_channel *prev = NULL;
 		bool must_wait = true;
 
@@ -377,17 +377,15 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 		return ret;
 	}
 
-	if (!exclusive || !fobj)
+	if (!exclusive || !shared)
 		return ret;
 
-	for (i = 0; i < fobj->shared_count && !ret; ++i) {
+
+	do {
 		struct nouveau_channel *prev = NULL;
 		bool must_wait = true;
 
-		fence = rcu_dereference_protected(fobj->shared[i],
-						dma_resv_held(resv));
-
-		f = nouveau_local_fence(fence, chan->drm);
+		f = nouveau_local_fence(shared, chan->drm);
 		if (f) {
 			rcu_read_lock();
 			prev = rcu_dereference(f->channel);
@@ -397,8 +395,8 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 		}
 
 		if (must_wait)
-			ret = dma_fence_wait(fence, intr);
-	}
+			ret = dma_fence_wait(shared, intr);
+	} while ((shared = dma_resv_next_shared(resv, &cursor)));
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c
index 0acc70a6d3dd..1d24e02f4652 100644
--- a/drivers/gpu/drm/qxl/qxl_debugfs.c
+++ b/drivers/gpu/drm/qxl/qxl_debugfs.c
@@ -57,12 +57,14 @@ qxl_debugfs_buffers_info(struct seq_file *m, void *data)
 	struct qxl_bo *bo;
 
 	list_for_each_entry(bo, &qdev->gem.objects, list) {
-		struct dma_resv_list *fobj;
-		int rel;
+		struct dma_resv_cursor cursor;
+		struct dma_fence *f;
+		int rel = 0;
 
+		/* TODO: Is this sufficient fast enough ? */
 		rcu_read_lock();
-		fobj = dma_resv_shared(bo->tbo.base.resv);
-		rel = fobj ? fobj->shared_count : 0;
+		dma_resv_for_each_shared(bo->tbo.base.resv, &cursor, f)
+			++rel;
 		rcu_read_unlock();
 
 		seq_printf(m, "size %ld, pc %d, num releases %d\n",
diff --git a/drivers/gpu/drm/radeon/radeon_sync.c b/drivers/gpu/drm/radeon/radeon_sync.c
index a9cdb88da173..915ac0de0633 100644
--- a/drivers/gpu/drm/radeon/radeon_sync.c
+++ b/drivers/gpu/drm/radeon/radeon_sync.c
@@ -91,11 +91,10 @@ int radeon_sync_resv(struct radeon_device *rdev,
 		     struct dma_resv *resv,
 		     bool shared)
 {
-	struct dma_resv_list *flist;
-	struct dma_fence *f;
+	struct dma_resv_cursor cursor;
 	struct radeon_fence *fence;
-	unsigned i;
-	int r = 0;
+	struct dma_fence *f;
+	int r;
 
 	/* always sync to the exclusive fence */
 	f = dma_resv_exclusive(resv);
@@ -105,13 +104,10 @@ int radeon_sync_resv(struct radeon_device *rdev,
 	else if (f)
 		r = dma_fence_wait(f, true);
 
-	flist = dma_resv_shared(resv);
-	if (shared || !flist || r)
+	if (shared || r)
 		return r;
 
-	for (i = 0; i < flist->shared_count; ++i) {
-		f = rcu_dereference_protected(flist->shared[i],
-					      dma_resv_held(resv));
+	dma_resv_for_each_shared(resv, &cursor, f) {
 		fence = to_radeon_fence(f);
 		if (fence && fence->rdev == rdev)
 			radeon_sync_fence(sync, fence);
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 9d453c2ca800..16b869d9b1d6 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -254,22 +254,17 @@ static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo)
 static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
 {
 	struct dma_resv *resv = &bo->base._resv;
-	struct dma_resv_list *fobj;
+	struct dma_resv_cursor cursor;
 	struct dma_fence *fence;
-	int i;
 
 	rcu_read_lock();
-	fobj = dma_resv_shared(resv);
-	fence = dma_resv_exclusive(resv);
-	if (fence && !fence->ops->signaled)
-		dma_fence_enable_sw_signaling(fence);
-
-	for (i = 0; fobj && i < fobj->shared_count; ++i) {
-		fence = rcu_dereference(fobj->shared[i]);
-
+	dma_resv_for_each_shared(resv, &cursor, fence) {
 		if (!fence->ops->signaled)
 			dma_fence_enable_sw_signaling(fence);
 	}
+	fence = dma_resv_exclusive(resv);
+	if (fence && !fence->ops->signaled)
+		dma_fence_enable_sw_signaling(fence);
 	rcu_read_unlock();
 }
 
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index 74b217b82f39..bb6911baac3d 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -45,20 +45,9 @@
 #include <linux/seqlock.h>
 #include <linux/rcupdate.h>
 
-extern struct ww_class reservation_ww_class;
+struct dma_resv_list;
 
-/**
- * struct dma_resv_list - a list of shared fences
- * @rcu: for internal use
- * @shared_count: table of shared fences
- * @shared_max: for growing shared fence table
- * @shared: shared fence table
- */
-struct dma_resv_list {
-	struct rcu_head rcu;
-	u32 shared_count, shared_max;
-	struct dma_fence __rcu *shared[];
-};
+extern struct ww_class reservation_ww_class;
 
 /**
  * struct dma_resv - a reservation object manages fences for a buffer
@@ -75,9 +64,23 @@ struct dma_resv {
 	struct dma_resv_list __rcu *fence;
 };
 
+struct dma_resv_cursor {
+	struct dma_resv_list *fences;
+	unsigned int i;
+};
+
 #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
 #define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base)
 
+struct dma_fence *dma_resv_first_shared(struct dma_resv *obj,
+					struct dma_resv_cursor *cursor);
+struct dma_fence *dma_resv_next_shared(struct dma_resv *obj,
+				       struct dma_resv_cursor *cursor);
+
+#define dma_resv_for_each_shared(obj, cursor, fence)		\
+	for (fence = dma_resv_first_shared(obj, cursor); fence;	\
+	     fence = dma_resv_next_shared(obj, cursor))
+
 #ifdef CONFIG_DEBUG_MUTEXES
 void dma_resv_reset_shared_max(struct dma_resv *obj);
 #else
@@ -253,17 +256,6 @@ dma_resv_get_excl_rcu(struct dma_resv *obj)
 	return fence;
 }
 
-/**
- * dma_resv_shared - get the reservation object's shared fence list
- * @obj: the reservation object
- *
- * Returns the shared fence list. The obj->lock or rcu read side must be held.
- */
-static inline struct dma_resv_list *dma_resv_shared(struct dma_resv *obj)
-{
-	return rcu_dereference_check(obj->fence, dma_resv_held(obj));
-}
-
 void dma_resv_init(struct dma_resv *obj);
 void dma_resv_fini(struct dma_resv *obj);
 int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences);
-- 
2.25.1



More information about the dri-devel mailing list