All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Christian König" <ckoenig.leichtzumerken@gmail.com>
To: dri-devel@lists.freedesktop.org, chris@chris-wilson.co.uk,
	daniel.vetter@ffwll.ch, sumit.semwal@linaro.org,
	linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org
Subject: [PATCH 09/10] dma-buf/resv: replace exclusive fence with new fences container
Date: Wed, 21 Aug 2019 14:31:46 +0200	[thread overview]
Message-ID: <20190821123147.110736-10-christian.koenig@amd.com> (raw)
In-Reply-To: <20190821123147.110736-1-christian.koenig@amd.com>

Replace the exclusive fence implementation with the new writers container
and change all users accordingly.

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-buf.c                    |  20 ++--
 drivers/dma-buf/dma-resv.c                   | 106 +++++++------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c     |   2 +-
 drivers/gpu/drm/drm_gem.c                    |   7 +-
 drivers/gpu/drm/drm_gem_framebuffer_helper.c |   2 +-
 drivers/gpu/drm/etnaviv/etnaviv_gem.c        |   6 +-
 drivers/gpu/drm/i915/gem/i915_gem_busy.c     |  16 ++-
 drivers/gpu/drm/nouveau/nouveau_bo.c         |   3 +-
 drivers/gpu/drm/nouveau/nouveau_fence.c      |   2 +-
 drivers/gpu/drm/radeon/radeon_display.c      |   4 +-
 drivers/gpu/drm/radeon/radeon_sync.c         |   2 +-
 drivers/gpu/drm/radeon/radeon_uvd.c          |   3 +-
 drivers/gpu/drm/ttm/ttm_bo.c                 |   2 +-
 include/linux/dma-resv.h                     |  33 +-----
 15 files changed, 78 insertions(+), 132 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 220cfa9ca82b..33fb3608e8ba 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -195,7 +195,7 @@ 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, *readers;
+	struct dma_fence *writers, *readers;
 	struct dma_buf *dmabuf;
 	struct dma_resv *resv;
 	__poll_t events;
@@ -213,10 +213,10 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 		return 0;
 
 	rcu_read_lock();
-	fence_excl = dma_fence_get_rcu_safe(&resv->fence_excl);
+	writers = dma_resv_fences_get_rcu(&resv->writers);
 	readers = dma_resv_fences_get_rcu(&resv->readers);
 
-	if (fence_excl && (!(events & EPOLLOUT) || !readers)) {
+	if (writers && (!(events & EPOLLOUT) || !readers)) {
 		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
 		__poll_t pevents = EPOLLIN;
 
@@ -232,16 +232,16 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 		spin_unlock_irq(&dmabuf->poll.lock);
 
 		if (events & pevents) {
-			if (!dma_fence_add_callback(fence_excl, &dcb->cb,
+			if (!dma_fence_add_callback(writers, &dcb->cb,
 						    dma_buf_poll_cb)) {
 				events &= ~pevents;
-				dma_fence_put(fence_excl);
+				dma_fence_put(writers);
 			} else {
 				/*
 				 * No callback queued, wake up any additional
 				 * waiters.
 				 */
-				dma_fence_put(fence_excl);
+				dma_fence_put(writers);
 				dma_buf_poll_cb(NULL, &dcb->cb);
 			}
 		}
@@ -1122,7 +1122,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 	struct dma_buf_attachment *attach_obj;
 	struct dma_fence_array_cursor cursor;
 	struct dma_resv *robj;
-	struct dma_fence *fence, *readers;
+	struct dma_fence *fence, *writers, *readers;
 	int count = 0, attach_count;
 	size_t size = 0;
 
@@ -1154,10 +1154,10 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 
 		robj = buf_obj->resv;
 		rcu_read_lock();
-		fence = dma_resv_get_excl(robj);
+		writers = dma_resv_fences_get_rcu(&robj->writers);
 		readers = dma_resv_fences_get_rcu(&robj->readers);
-		if (fence)
-			seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n",
+		dma_fence_array_for_each(fence, cursor, writers)
+			seq_printf(s, "\tWriters fence: %s %s %ssignalled\n",
 				   fence->ops->get_driver_name(fence),
 				   fence->ops->get_timeline_name(fence),
 				   dma_fence_is_signaled(fence) ? "" : "un");
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 8723af0a7a4d..8ef7dbc7fd8e 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -39,22 +39,16 @@
 /**
  * DOC: Reservation Object Overview
  *
- * The reservation object provides a mechanism to manage readers and
- * exclusive fences associated with a buffer.  A reservation object
- * can have attached one exclusive fence (normally associated with
- * write operations) or N read fences.  The RCU mechanism is used to
- * protect read access to fences from locked write-side updates.
+ * The reservation object provides a mechanism to manage readers and writers
+ * associated with a buffer. A reservation object can have attached any number
+ * of read and writer operation in the form of dma_fence objects. The RCU
+ * mechanism is used to protect read access to fences from locked write-side
+ * updates.
  */
 
 DEFINE_WD_CLASS(reservation_ww_class);
 EXPORT_SYMBOL(reservation_ww_class);
 
-struct lock_class_key reservation_seqcount_class;
-EXPORT_SYMBOL(reservation_seqcount_class);
-
-const char reservation_seqcount_string[] = "reservation_seqcount";
-EXPORT_SYMBOL(reservation_seqcount_string);
-
 static void dma_resv_fences_init(struct dma_resv_fences *fences)
 {
 	RCU_INIT_POINTER(fences->fence, NULL);
@@ -284,9 +278,7 @@ void dma_resv_init(struct dma_resv *obj)
 {
 	ww_mutex_init(&obj->lock, &reservation_ww_class);
 
-	__seqcount_init(&obj->seq, reservation_seqcount_string,
-			&reservation_seqcount_class);
-	RCU_INIT_POINTER(obj->fence_excl, NULL);
+	dma_resv_fences_init(&obj->writers);
 	dma_resv_fences_init(&obj->readers);
 }
 EXPORT_SYMBOL(dma_resv_init);
@@ -301,7 +293,7 @@ void dma_resv_fini(struct dma_resv *obj)
 	 * This object should be dead and all references must have
 	 * been released to it, so no need to be protected with rcu.
 	 */
-	dma_fence_put(rcu_dereference_protected(obj->fence_excl, true));
+	dma_resv_fences_fini(&obj->writers);
 	dma_resv_fences_fini(&obj->readers);
 	ww_mutex_destroy(&obj->lock);
 }
@@ -312,25 +304,14 @@ EXPORT_SYMBOL(dma_resv_fini);
  * @obj: the reservation object
  * @fence: the shared fence to add
  *
- * Add a fence to the exclusive slot.  The obj->lock must be held.
+ * Add a fence to the exclusive slots.  The obj->lock must be held.
  */
 void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
 {
-	struct dma_fence *old_fence = dma_resv_get_excl(obj);
-
 	dma_resv_assert_held(obj);
 
-	dma_fence_get(fence);
-
-	preempt_disable();
-	write_seqcount_begin(&obj->seq);
-	/* write_seqcount_begin provides the necessary memory barrier */
-	RCU_INIT_POINTER(obj->fence_excl, fence);
+	dma_resv_fences_set(obj, &obj->writers, fence);
 	dma_resv_fences_set(obj, &obj->readers, fence);
-	write_seqcount_end(&obj->seq);
-	preempt_enable();
-
-	dma_fence_put(old_fence);
 }
 EXPORT_SYMBOL(dma_resv_add_excl_fence);
 
@@ -346,11 +327,9 @@ void dma_resv_prune_fences(struct dma_resv *obj)
 
 	dma_resv_assert_held(obj);
 
-	fence = dma_resv_get_excl(obj);
-	if (dma_fence_is_signaled(fence)) {
-		RCU_INIT_POINTER(obj->fence_excl, NULL);
-		dma_fence_put(fence);
-	}
+	fence = dma_resv_fences_deref(obj, &obj->writers);
+	if (dma_fence_is_signaled(fence))
+		dma_resv_fences_set(obj, &obj->writers, NULL);
 
 	fence = dma_resv_fences_deref(obj, &obj->readers);
 	if (dma_fence_is_signaled(fence))
@@ -367,36 +346,27 @@ EXPORT_SYMBOL(dma_resv_prune_fences);
 */
 int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
 {
-	struct dma_fence *old, *excl, *readers;
+	struct dma_fence *writers, *readers;
 
 	dma_resv_assert_held(dst);
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&src->fence_excl);
+	writers = dma_resv_fences_get_rcu(&src->writers);
 	readers = dma_resv_fences_get_rcu(&src->readers);
 	rcu_read_unlock();
 
-	old = dma_resv_get_excl(dst);
-
-	preempt_disable();
-	write_seqcount_begin(&dst->seq);
-	/* write_seqcount_begin provides the necessary memory barrier */
-	RCU_INIT_POINTER(dst->fence_excl, excl);
+	dma_resv_fences_set(dst, &dst->writers, writers);
 	dma_resv_fences_set(dst, &dst->readers, readers);
-	write_seqcount_end(&dst->seq);
-	preempt_enable();
-
-	dma_fence_put(old);
 
 	return 0;
 }
 EXPORT_SYMBOL(dma_resv_copy_fences);
 
 /**
- * dma_resv_get_fences_rcu - Get an object's readers and exclusive
+ * dma_resv_get_fences_rcu - Get an object's readers and writers
  * fences without update side lock held
  * @obj: the reservation object
- * @pfence_excl: the returned exclusive fence (or NULL)
+ * @pfence_excl: the returned writers (or NULL)
  * @pshared_count: the number of shared fences returned
  * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
  * the required size, and must be freed by caller)
@@ -404,30 +374,32 @@ EXPORT_SYMBOL(dma_resv_copy_fences);
  * Retrieve all fences from the reservation object. If the pointer for the
  * exclusive fence is not specified the fence is put into the array of the
  * shared fences as well. Returns either zero or -ENOMEM.
+ *
+ * TODO: Deprecated and shouldn't be used any more.
  */
 int dma_resv_get_fences_rcu(struct dma_resv *obj,
 			    struct dma_fence **pfence_excl,
 			    unsigned *pshared_count,
 			    struct dma_fence ***pshared)
 {
-	struct dma_fence *excl, *readers;
+	struct dma_fence *writers, *readers;
 	struct dma_fence **shared;
 	unsigned int shared_count;
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&obj->fence_excl);
+	writers = dma_resv_fences_get_rcu(&obj->writers);
 	readers = dma_resv_fences_get_rcu(&obj->readers);
 	rcu_read_unlock();
 
 	shared_count = readers ? 1 : 0;
-	if (excl && !pfence_excl)
+	if (writers && !pfence_excl)
 		++shared_count;
 
 	if (shared_count) {
 		shared = kmalloc_array(shared_count, sizeof(*shared),
 				       GFP_KERNEL);
 		if (!shared) {
-			dma_fence_put(excl);
+			dma_fence_put(writers);
 			dma_fence_put(readers);
 			return -ENOMEM;
 		}
@@ -435,8 +407,8 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
 		shared_count = 0;
 		if (readers)
 			shared[shared_count++] = readers;
-		if (excl && !pfence_excl)
-			shared[shared_count++] = excl;
+		if (writers && !pfence_excl)
+			shared[shared_count++] = writers;
 
 		*pshared = shared;
 		*pshared_count = shared_count;
@@ -446,7 +418,7 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
 	}
 
 	if (pfence_excl)
-		*pfence_excl = excl;
+		*pfence_excl = writers;
 
 	return 0;
 }
@@ -454,9 +426,9 @@ EXPORT_SYMBOL_GPL(dma_resv_get_fences_rcu);
 
 /**
  * dma_resv_wait_timeout_rcu - Wait on reservation's objects
- * readers and/or exclusive fences.
+ * readers and/or writers.
  * @obj: the reservation object
- * @wait_all: if true, wait on all fences, else wait on just exclusive fence
+ * @wait_all: if true, wait on all fences, else wait on just writers
  * @intr: if true, do interruptible wait
  * @timeout: timeout value in jiffies or zero to return immediately
  *
@@ -468,11 +440,11 @@ long dma_resv_wait_timeout_rcu(struct dma_resv *obj,
 			       bool wait_all, bool intr,
 			       unsigned long timeout)
 {
-	struct dma_fence *excl, *readers;
+	struct dma_fence *writers, *readers;
 	long ret = timeout ? timeout : 1;
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&obj->fence_excl);
+	writers = dma_resv_fences_get_rcu(&obj->writers);
 	readers = dma_resv_fences_get_rcu(&obj->readers);
 	rcu_read_unlock();
 
@@ -482,11 +454,11 @@ long dma_resv_wait_timeout_rcu(struct dma_resv *obj,
 			goto out;
 	}
 
-	if (excl)
-		ret = dma_fence_wait_timeout(excl, intr, ret);
+	if (writers)
+		ret = dma_fence_wait_timeout(writers, intr, ret);
 
 out:
-	dma_fence_put(excl);
+	dma_fence_put(writers);
 	dma_fence_put(readers);
 	return ret;
 }
@@ -496,7 +468,7 @@ EXPORT_SYMBOL_GPL(dma_resv_wait_timeout_rcu);
  * dma_resv_test_signaled_rcu - Test if a reservation object's
  * fences have been signaled.
  * @obj: the reservation object
- * @test_all: if true, test all fences, otherwise only test the exclusive
+ * @test_all: if true, test all fences, otherwise only test the writers
  * fence
  *
  * RETURNS
@@ -504,21 +476,21 @@ EXPORT_SYMBOL_GPL(dma_resv_wait_timeout_rcu);
  */
 bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all)
 {
-	struct dma_fence *excl, *readers;
+	struct dma_fence *writers, *readers;
 	bool ret = true;
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&obj->fence_excl);
+	writers = dma_resv_fences_get_rcu(&obj->writers);
 	readers = dma_resv_fences_get_rcu(&obj->readers);
 	rcu_read_unlock();
 
-	if (excl)
-		ret = dma_fence_is_signaled(excl);
+	if (writers)
+		ret = dma_fence_is_signaled(writers);
 
 	if (test_all && readers)
 		ret &= dma_fence_is_signaled(readers);
 
-	dma_fence_put(excl);
+	dma_fence_put(writers);
 	dma_fence_put(readers);
 
 	return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 3e4685565f82..fde3aa1ad76d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -141,7 +141,7 @@ __dma_resv_make_exclusive(struct dma_resv *obj)
 {
 	struct dma_fence *readers = dma_fence_get_rcu(obj->readers.fence);
 
-	dma_resv_add_excl_fence(obj, readers);
+	dma_resv_fences_set(obj, &obj->writers, readers);
 	dma_fence_put(readers);
 
 	return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index f8bc5baf0a44..7ba84897d52d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -204,7 +204,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
 		return -EINVAL;
 
 	/* always sync to the exclusive fence */
-	f = dma_resv_get_excl(resv);
+	f = dma_resv_fences_deref(resv, &resv->writers);
 	r = amdgpu_sync_fence(adev, sync, f, false);
 	if (r)
 		return r;
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 6854f5867d51..213410f8af6e 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1412,14 +1412,13 @@ int drm_gem_fence_array_add_implicit(struct xarray *fence_array,
 	unsigned int i, fence_count;
 
 	if (!write) {
-		struct dma_fence *fence =
-			dma_resv_get_excl_rcu(obj->resv);
+		struct dma_fence *fence;
 
+		fence = dma_resv_fences_deref(obj->resv, &obj->resv->writers);
 		return drm_gem_fence_array_add(fence_array, fence);
 	}
 
-	ret = dma_resv_get_fences_rcu(obj->resv, NULL,
-						&fence_count, &fences);
+	ret = dma_resv_get_fences_rcu(obj->resv, NULL, &fence_count, &fences);
 	if (ret || !fence_count)
 		return ret;
 
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index b9bcd310ca2d..72af3547d2e3 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -294,7 +294,7 @@ int drm_gem_fb_prepare_fb(struct drm_plane *plane,
 		return 0;
 
 	obj = drm_gem_fb_get_obj(state->fb, 0);
-	fence = dma_resv_get_excl_rcu(obj->resv);
+	fence = dma_resv_fences_get_rcu(&obj->resv->writers);
 	drm_atomic_set_fence_for_plane(state, fence);
 
 	return 0;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 15f36ccd6e53..df6452f90576 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -460,9 +460,9 @@ 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);
+	struct dma_fence *fence, *writers, *readers;
 	struct dma_fence_array_cursor cursor;
 	struct dma_resv *robj = obj->resv;
-	struct dma_fence *fence, *readers;
 	unsigned long off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
@@ -474,8 +474,8 @@ static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 	readers = dma_resv_fences_deref(robj, &robj->readers);
 	dma_fence_array_for_each(fence, cursor, readers)
 		etnaviv_gem_describe_fence(fence, "Shared", m);
-	fence = rcu_dereference(robj->fence_excl);
-	if (fence)
+	writers = dma_resv_fences_deref(robj, &robj->writers);
+	dma_fence_array_for_each(fence, cursor, readers)
 		etnaviv_gem_describe_fence(fence, "Exclusive", m);
 	rcu_read_unlock();
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
index 0f18ba97b228..36fe5881667a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -84,9 +84,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_i915_gem_busy *args = data;
 	struct dma_fence_array_cursor cursor;
-	struct dma_fence *fence, *readers;
+	struct dma_fence *fence, *writers, *readers;
 	struct drm_i915_gem_object *obj;
-	unsigned int seq;
 	int err;
 
 	err = -ENOENT;
@@ -112,21 +111,18 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 	 * to report the overall busyness. This is what the wait-ioctl does.
 	 *
 	 */
-retry:
-	seq = raw_read_seqcount(&obj->base.resv->seq);
+	writers = dma_resv_fences_get_rcu(&obj->base.resv->writers);
+	readers = dma_resv_fences_get_rcu(&obj->base.resv->readers);
 
 	/* Translate the exclusive fence to the READ *and* WRITE engine */
-	args->busy =
-		busy_check_writer(rcu_dereference(obj->base.resv->fence_excl));
+	args->busy = busy_check_writer(writers);
 
 	/* Translate shared fences to READ set of engines */
-	readers = dma_resv_fences_get_rcu(&obj->base.resv->readers);
 	dma_fence_array_for_each(fence, cursor, readers)
 		args->busy |= busy_check_reader(fence);
-	dma_fence_put(readers);
 
-	if (args->busy && read_seqcount_retry(&obj->base.resv->seq, seq))
-		goto retry;
+	dma_fence_put(writers);
+	dma_fence_put(readers);
 
 	err = 0;
 out:
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 6b3fad03b342..f865eadae965 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1324,8 +1324,9 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
 {
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
 	struct drm_device *dev = drm->dev;
-	struct dma_fence *fence = dma_resv_get_excl(bo->base.resv);
+	struct dma_fence *fence;
 
+	fence = dma_resv_fences_deref(bo->base.resv, &bo->base.resv->writers);
 	nv10_bo_put_tile_region(dev, *old_tile, fence);
 	*old_tile = new_tile;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 350cd2a9ea51..a97878fbbc96 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -348,7 +348,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 			return ret;
 	}
 
-	fence = dma_resv_get_excl(resv);
+	fence = dma_resv_fences_deref(resv, &resv->writers);
 	if (fence) {
 		struct nouveau_channel *prev = NULL;
 		bool must_wait = true;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index e81b01f8db90..6ef589081c6b 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -533,7 +533,9 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
 		DRM_ERROR("failed to pin new rbo buffer before flip\n");
 		goto cleanup;
 	}
-	work->fence = dma_fence_get(dma_resv_get_excl(new_rbo->tbo.base.resv));
+	work->fence = dma_resv_fences_deref(new_rbo->tbo.base.resv,
+					    &new_rbo->tbo.base.resv->writers);
+	dma_fence_get(work->fence);
 	radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
 	radeon_bo_unreserve(new_rbo);
 
diff --git a/drivers/gpu/drm/radeon/radeon_sync.c b/drivers/gpu/drm/radeon/radeon_sync.c
index 971dd6c01e60..bf595428dabf 100644
--- a/drivers/gpu/drm/radeon/radeon_sync.c
+++ b/drivers/gpu/drm/radeon/radeon_sync.c
@@ -97,7 +97,7 @@ int radeon_sync_resv(struct radeon_device *rdev,
 	int r = 0;
 
 	/* always sync to the exclusive fence */
-	f = dma_resv_get_excl(resv);
+	f = dma_resv_fences_deref(resv, &resv->writers);
 	fence = f ? to_radeon_fence(f) : NULL;
 	if (fence && fence->rdev == rdev)
 		radeon_sync_fence(sync, fence);
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 1ad5c3b86b64..72bfcddbce2b 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -465,6 +465,7 @@ static int radeon_uvd_validate_codec(struct radeon_cs_parser *p,
 static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 			     unsigned offset, unsigned buf_sizes[])
 {
+	struct dma_resv *resv = bo->tbo.base.resv;
 	int32_t *msg, msg_type, handle;
 	unsigned img_size = 0;
 	struct dma_fence *f;
@@ -477,7 +478,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 		return -EINVAL;
 	}
 
-	f = dma_resv_get_excl(bo->tbo.base.resv);
+	f = dma_resv_fences_deref(resv, &resv->writers);
 	if (f) {
 		r = radeon_fence_wait((struct radeon_fence *)f, false);
 		if (r) {
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 19eeefbbb65a..53d4035778d0 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -455,7 +455,7 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
 {
 	struct dma_fence *fence;
 
-	fence = dma_resv_get_excl(&bo->base._resv);
+	fence = dma_resv_fences_deref(&bo->base._resv, &bo->base._resv.writers);
 	if (fence && !fence->ops->signaled)
 		dma_fence_enable_sw_signaling(fence);
 
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index b23e16975f39..72c3c4f99711 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -48,8 +48,6 @@
 struct dma_resv;
 
 extern struct ww_class reservation_ww_class;
-extern struct lock_class_key reservation_seqcount_class;
-extern const char reservation_seqcount_string[];
 
 /**
  * struct dma_resv_fences - fences inside a reservation object
@@ -76,15 +74,14 @@ void dma_resv_fences_commit(struct dma_resv *obj,
  * struct dma_resv - a reservation object manages fences for a buffer
  * @lock: update side lock
  * @seq: sequence count for managing RCU read-side synchronization
- * @fence_excl: the exclusive fence, if there is one currently
+ * @writers: array of write operations for implicit sync
  * @readers: array of read operations for implicit sync
  */
 struct dma_resv {
 	struct ww_mutex lock;
-	seqcount_t seq;
 
-	struct dma_fence __rcu *fence_excl;
-	struct dma_resv_fences	readers;
+	struct dma_resv_fences writers;
+	struct dma_resv_fences readers;
 };
 
 #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
@@ -243,25 +240,6 @@ static inline void dma_resv_unlock(struct dma_resv *obj)
 	ww_mutex_unlock(&obj->lock);
 }
 
-/**
- * dma_resv_get_excl - get the reservation object's
- * exclusive fence, with update-side lock held
- * @obj: the reservation object
- *
- * Returns the exclusive fence (if any).  Does NOT take a
- * reference. Writers must hold obj->lock, readers may only
- * hold a RCU read side lock.
- *
- * RETURNS
- * The exclusive fence or NULL
- */
-static inline struct dma_fence *
-dma_resv_get_excl(struct dma_resv *obj)
-{
-	return rcu_dereference_protected(obj->fence_excl,
-					 dma_resv_held(obj));
-}
-
 /**
  * dma_resv_get_excl_rcu - get the reservation object's
  * exclusive fence, without lock held.
@@ -278,11 +256,8 @@ dma_resv_get_excl_rcu(struct dma_resv *obj)
 {
 	struct dma_fence *fence;
 
-	if (!rcu_access_pointer(obj->fence_excl))
-		return NULL;
-
 	rcu_read_lock();
-	fence = dma_fence_get_rcu_safe(&obj->fence_excl);
+	fence = dma_resv_fences_get_rcu(&obj->writers);
 	rcu_read_unlock();
 
 	return fence;
-- 
2.17.1


WARNING: multiple messages have this Message-ID (diff)
From: "Christian König" <ckoenig.leichtzumerken@gmail.com>
To: dri-devel@lists.freedesktop.org, chris@chris-wilson.co.uk,
	daniel.vetter@ffwll.ch, sumit.semwal@linaro.org,
	linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org
Subject: [PATCH 09/10] dma-buf/resv: replace exclusive fence with new fences container
Date: Wed, 21 Aug 2019 14:31:46 +0200	[thread overview]
Message-ID: <20190821123147.110736-10-christian.koenig@amd.com> (raw)
In-Reply-To: <20190821123147.110736-1-christian.koenig@amd.com>

Replace the exclusive fence implementation with the new writers container
and change all users accordingly.

Signed-off-by: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-buf.c                    |  20 ++--
 drivers/dma-buf/dma-resv.c                   | 106 +++++++------------
 drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c     |   2 +-
 drivers/gpu/drm/drm_gem.c                    |   7 +-
 drivers/gpu/drm/drm_gem_framebuffer_helper.c |   2 +-
 drivers/gpu/drm/etnaviv/etnaviv_gem.c        |   6 +-
 drivers/gpu/drm/i915/gem/i915_gem_busy.c     |  16 ++-
 drivers/gpu/drm/nouveau/nouveau_bo.c         |   3 +-
 drivers/gpu/drm/nouveau/nouveau_fence.c      |   2 +-
 drivers/gpu/drm/radeon/radeon_display.c      |   4 +-
 drivers/gpu/drm/radeon/radeon_sync.c         |   2 +-
 drivers/gpu/drm/radeon/radeon_uvd.c          |   3 +-
 drivers/gpu/drm/ttm/ttm_bo.c                 |   2 +-
 include/linux/dma-resv.h                     |  33 +-----
 15 files changed, 78 insertions(+), 132 deletions(-)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 220cfa9ca82b..33fb3608e8ba 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -195,7 +195,7 @@ 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, *readers;
+	struct dma_fence *writers, *readers;
 	struct dma_buf *dmabuf;
 	struct dma_resv *resv;
 	__poll_t events;
@@ -213,10 +213,10 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 		return 0;
 
 	rcu_read_lock();
-	fence_excl = dma_fence_get_rcu_safe(&resv->fence_excl);
+	writers = dma_resv_fences_get_rcu(&resv->writers);
 	readers = dma_resv_fences_get_rcu(&resv->readers);
 
-	if (fence_excl && (!(events & EPOLLOUT) || !readers)) {
+	if (writers && (!(events & EPOLLOUT) || !readers)) {
 		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
 		__poll_t pevents = EPOLLIN;
 
@@ -232,16 +232,16 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 		spin_unlock_irq(&dmabuf->poll.lock);
 
 		if (events & pevents) {
-			if (!dma_fence_add_callback(fence_excl, &dcb->cb,
+			if (!dma_fence_add_callback(writers, &dcb->cb,
 						    dma_buf_poll_cb)) {
 				events &= ~pevents;
-				dma_fence_put(fence_excl);
+				dma_fence_put(writers);
 			} else {
 				/*
 				 * No callback queued, wake up any additional
 				 * waiters.
 				 */
-				dma_fence_put(fence_excl);
+				dma_fence_put(writers);
 				dma_buf_poll_cb(NULL, &dcb->cb);
 			}
 		}
@@ -1122,7 +1122,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 	struct dma_buf_attachment *attach_obj;
 	struct dma_fence_array_cursor cursor;
 	struct dma_resv *robj;
-	struct dma_fence *fence, *readers;
+	struct dma_fence *fence, *writers, *readers;
 	int count = 0, attach_count;
 	size_t size = 0;
 
@@ -1154,10 +1154,10 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 
 		robj = buf_obj->resv;
 		rcu_read_lock();
-		fence = dma_resv_get_excl(robj);
+		writers = dma_resv_fences_get_rcu(&robj->writers);
 		readers = dma_resv_fences_get_rcu(&robj->readers);
-		if (fence)
-			seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n",
+		dma_fence_array_for_each(fence, cursor, writers)
+			seq_printf(s, "\tWriters fence: %s %s %ssignalled\n",
 				   fence->ops->get_driver_name(fence),
 				   fence->ops->get_timeline_name(fence),
 				   dma_fence_is_signaled(fence) ? "" : "un");
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index 8723af0a7a4d..8ef7dbc7fd8e 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -39,22 +39,16 @@
 /**
  * DOC: Reservation Object Overview
  *
- * The reservation object provides a mechanism to manage readers and
- * exclusive fences associated with a buffer.  A reservation object
- * can have attached one exclusive fence (normally associated with
- * write operations) or N read fences.  The RCU mechanism is used to
- * protect read access to fences from locked write-side updates.
+ * The reservation object provides a mechanism to manage readers and writers
+ * associated with a buffer. A reservation object can have attached any number
+ * of read and writer operation in the form of dma_fence objects. The RCU
+ * mechanism is used to protect read access to fences from locked write-side
+ * updates.
  */
 
 DEFINE_WD_CLASS(reservation_ww_class);
 EXPORT_SYMBOL(reservation_ww_class);
 
-struct lock_class_key reservation_seqcount_class;
-EXPORT_SYMBOL(reservation_seqcount_class);
-
-const char reservation_seqcount_string[] = "reservation_seqcount";
-EXPORT_SYMBOL(reservation_seqcount_string);
-
 static void dma_resv_fences_init(struct dma_resv_fences *fences)
 {
 	RCU_INIT_POINTER(fences->fence, NULL);
@@ -284,9 +278,7 @@ void dma_resv_init(struct dma_resv *obj)
 {
 	ww_mutex_init(&obj->lock, &reservation_ww_class);
 
-	__seqcount_init(&obj->seq, reservation_seqcount_string,
-			&reservation_seqcount_class);
-	RCU_INIT_POINTER(obj->fence_excl, NULL);
+	dma_resv_fences_init(&obj->writers);
 	dma_resv_fences_init(&obj->readers);
 }
 EXPORT_SYMBOL(dma_resv_init);
@@ -301,7 +293,7 @@ void dma_resv_fini(struct dma_resv *obj)
 	 * This object should be dead and all references must have
 	 * been released to it, so no need to be protected with rcu.
 	 */
-	dma_fence_put(rcu_dereference_protected(obj->fence_excl, true));
+	dma_resv_fences_fini(&obj->writers);
 	dma_resv_fences_fini(&obj->readers);
 	ww_mutex_destroy(&obj->lock);
 }
@@ -312,25 +304,14 @@ EXPORT_SYMBOL(dma_resv_fini);
  * @obj: the reservation object
  * @fence: the shared fence to add
  *
- * Add a fence to the exclusive slot.  The obj->lock must be held.
+ * Add a fence to the exclusive slots.  The obj->lock must be held.
  */
 void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
 {
-	struct dma_fence *old_fence = dma_resv_get_excl(obj);
-
 	dma_resv_assert_held(obj);
 
-	dma_fence_get(fence);
-
-	preempt_disable();
-	write_seqcount_begin(&obj->seq);
-	/* write_seqcount_begin provides the necessary memory barrier */
-	RCU_INIT_POINTER(obj->fence_excl, fence);
+	dma_resv_fences_set(obj, &obj->writers, fence);
 	dma_resv_fences_set(obj, &obj->readers, fence);
-	write_seqcount_end(&obj->seq);
-	preempt_enable();
-
-	dma_fence_put(old_fence);
 }
 EXPORT_SYMBOL(dma_resv_add_excl_fence);
 
@@ -346,11 +327,9 @@ void dma_resv_prune_fences(struct dma_resv *obj)
 
 	dma_resv_assert_held(obj);
 
-	fence = dma_resv_get_excl(obj);
-	if (dma_fence_is_signaled(fence)) {
-		RCU_INIT_POINTER(obj->fence_excl, NULL);
-		dma_fence_put(fence);
-	}
+	fence = dma_resv_fences_deref(obj, &obj->writers);
+	if (dma_fence_is_signaled(fence))
+		dma_resv_fences_set(obj, &obj->writers, NULL);
 
 	fence = dma_resv_fences_deref(obj, &obj->readers);
 	if (dma_fence_is_signaled(fence))
@@ -367,36 +346,27 @@ EXPORT_SYMBOL(dma_resv_prune_fences);
 */
 int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
 {
-	struct dma_fence *old, *excl, *readers;
+	struct dma_fence *writers, *readers;
 
 	dma_resv_assert_held(dst);
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&src->fence_excl);
+	writers = dma_resv_fences_get_rcu(&src->writers);
 	readers = dma_resv_fences_get_rcu(&src->readers);
 	rcu_read_unlock();
 
-	old = dma_resv_get_excl(dst);
-
-	preempt_disable();
-	write_seqcount_begin(&dst->seq);
-	/* write_seqcount_begin provides the necessary memory barrier */
-	RCU_INIT_POINTER(dst->fence_excl, excl);
+	dma_resv_fences_set(dst, &dst->writers, writers);
 	dma_resv_fences_set(dst, &dst->readers, readers);
-	write_seqcount_end(&dst->seq);
-	preempt_enable();
-
-	dma_fence_put(old);
 
 	return 0;
 }
 EXPORT_SYMBOL(dma_resv_copy_fences);
 
 /**
- * dma_resv_get_fences_rcu - Get an object's readers and exclusive
+ * dma_resv_get_fences_rcu - Get an object's readers and writers
  * fences without update side lock held
  * @obj: the reservation object
- * @pfence_excl: the returned exclusive fence (or NULL)
+ * @pfence_excl: the returned writers (or NULL)
  * @pshared_count: the number of shared fences returned
  * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
  * the required size, and must be freed by caller)
@@ -404,30 +374,32 @@ EXPORT_SYMBOL(dma_resv_copy_fences);
  * Retrieve all fences from the reservation object. If the pointer for the
  * exclusive fence is not specified the fence is put into the array of the
  * shared fences as well. Returns either zero or -ENOMEM.
+ *
+ * TODO: Deprecated and shouldn't be used any more.
  */
 int dma_resv_get_fences_rcu(struct dma_resv *obj,
 			    struct dma_fence **pfence_excl,
 			    unsigned *pshared_count,
 			    struct dma_fence ***pshared)
 {
-	struct dma_fence *excl, *readers;
+	struct dma_fence *writers, *readers;
 	struct dma_fence **shared;
 	unsigned int shared_count;
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&obj->fence_excl);
+	writers = dma_resv_fences_get_rcu(&obj->writers);
 	readers = dma_resv_fences_get_rcu(&obj->readers);
 	rcu_read_unlock();
 
 	shared_count = readers ? 1 : 0;
-	if (excl && !pfence_excl)
+	if (writers && !pfence_excl)
 		++shared_count;
 
 	if (shared_count) {
 		shared = kmalloc_array(shared_count, sizeof(*shared),
 				       GFP_KERNEL);
 		if (!shared) {
-			dma_fence_put(excl);
+			dma_fence_put(writers);
 			dma_fence_put(readers);
 			return -ENOMEM;
 		}
@@ -435,8 +407,8 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
 		shared_count = 0;
 		if (readers)
 			shared[shared_count++] = readers;
-		if (excl && !pfence_excl)
-			shared[shared_count++] = excl;
+		if (writers && !pfence_excl)
+			shared[shared_count++] = writers;
 
 		*pshared = shared;
 		*pshared_count = shared_count;
@@ -446,7 +418,7 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
 	}
 
 	if (pfence_excl)
-		*pfence_excl = excl;
+		*pfence_excl = writers;
 
 	return 0;
 }
@@ -454,9 +426,9 @@ EXPORT_SYMBOL_GPL(dma_resv_get_fences_rcu);
 
 /**
  * dma_resv_wait_timeout_rcu - Wait on reservation's objects
- * readers and/or exclusive fences.
+ * readers and/or writers.
  * @obj: the reservation object
- * @wait_all: if true, wait on all fences, else wait on just exclusive fence
+ * @wait_all: if true, wait on all fences, else wait on just writers
  * @intr: if true, do interruptible wait
  * @timeout: timeout value in jiffies or zero to return immediately
  *
@@ -468,11 +440,11 @@ long dma_resv_wait_timeout_rcu(struct dma_resv *obj,
 			       bool wait_all, bool intr,
 			       unsigned long timeout)
 {
-	struct dma_fence *excl, *readers;
+	struct dma_fence *writers, *readers;
 	long ret = timeout ? timeout : 1;
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&obj->fence_excl);
+	writers = dma_resv_fences_get_rcu(&obj->writers);
 	readers = dma_resv_fences_get_rcu(&obj->readers);
 	rcu_read_unlock();
 
@@ -482,11 +454,11 @@ long dma_resv_wait_timeout_rcu(struct dma_resv *obj,
 			goto out;
 	}
 
-	if (excl)
-		ret = dma_fence_wait_timeout(excl, intr, ret);
+	if (writers)
+		ret = dma_fence_wait_timeout(writers, intr, ret);
 
 out:
-	dma_fence_put(excl);
+	dma_fence_put(writers);
 	dma_fence_put(readers);
 	return ret;
 }
@@ -496,7 +468,7 @@ EXPORT_SYMBOL_GPL(dma_resv_wait_timeout_rcu);
  * dma_resv_test_signaled_rcu - Test if a reservation object's
  * fences have been signaled.
  * @obj: the reservation object
- * @test_all: if true, test all fences, otherwise only test the exclusive
+ * @test_all: if true, test all fences, otherwise only test the writers
  * fence
  *
  * RETURNS
@@ -504,21 +476,21 @@ EXPORT_SYMBOL_GPL(dma_resv_wait_timeout_rcu);
  */
 bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all)
 {
-	struct dma_fence *excl, *readers;
+	struct dma_fence *writers, *readers;
 	bool ret = true;
 
 	rcu_read_lock();
-	excl = dma_fence_get_rcu_safe(&obj->fence_excl);
+	writers = dma_resv_fences_get_rcu(&obj->writers);
 	readers = dma_resv_fences_get_rcu(&obj->readers);
 	rcu_read_unlock();
 
-	if (excl)
-		ret = dma_fence_is_signaled(excl);
+	if (writers)
+		ret = dma_fence_is_signaled(writers);
 
 	if (test_all && readers)
 		ret &= dma_fence_is_signaled(readers);
 
-	dma_fence_put(excl);
+	dma_fence_put(writers);
 	dma_fence_put(readers);
 
 	return ret;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 3e4685565f82..fde3aa1ad76d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -141,7 +141,7 @@ __dma_resv_make_exclusive(struct dma_resv *obj)
 {
 	struct dma_fence *readers = dma_fence_get_rcu(obj->readers.fence);
 
-	dma_resv_add_excl_fence(obj, readers);
+	dma_resv_fences_set(obj, &obj->writers, readers);
 	dma_fence_put(readers);
 
 	return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index f8bc5baf0a44..7ba84897d52d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -204,7 +204,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
 		return -EINVAL;
 
 	/* always sync to the exclusive fence */
-	f = dma_resv_get_excl(resv);
+	f = dma_resv_fences_deref(resv, &resv->writers);
 	r = amdgpu_sync_fence(adev, sync, f, false);
 	if (r)
 		return r;
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 6854f5867d51..213410f8af6e 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1412,14 +1412,13 @@ int drm_gem_fence_array_add_implicit(struct xarray *fence_array,
 	unsigned int i, fence_count;
 
 	if (!write) {
-		struct dma_fence *fence =
-			dma_resv_get_excl_rcu(obj->resv);
+		struct dma_fence *fence;
 
+		fence = dma_resv_fences_deref(obj->resv, &obj->resv->writers);
 		return drm_gem_fence_array_add(fence_array, fence);
 	}
 
-	ret = dma_resv_get_fences_rcu(obj->resv, NULL,
-						&fence_count, &fences);
+	ret = dma_resv_get_fences_rcu(obj->resv, NULL, &fence_count, &fences);
 	if (ret || !fence_count)
 		return ret;
 
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index b9bcd310ca2d..72af3547d2e3 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -294,7 +294,7 @@ int drm_gem_fb_prepare_fb(struct drm_plane *plane,
 		return 0;
 
 	obj = drm_gem_fb_get_obj(state->fb, 0);
-	fence = dma_resv_get_excl_rcu(obj->resv);
+	fence = dma_resv_fences_get_rcu(&obj->resv->writers);
 	drm_atomic_set_fence_for_plane(state, fence);
 
 	return 0;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index 15f36ccd6e53..df6452f90576 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -460,9 +460,9 @@ 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);
+	struct dma_fence *fence, *writers, *readers;
 	struct dma_fence_array_cursor cursor;
 	struct dma_resv *robj = obj->resv;
-	struct dma_fence *fence, *readers;
 	unsigned long off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
@@ -474,8 +474,8 @@ static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 	readers = dma_resv_fences_deref(robj, &robj->readers);
 	dma_fence_array_for_each(fence, cursor, readers)
 		etnaviv_gem_describe_fence(fence, "Shared", m);
-	fence = rcu_dereference(robj->fence_excl);
-	if (fence)
+	writers = dma_resv_fences_deref(robj, &robj->writers);
+	dma_fence_array_for_each(fence, cursor, readers)
 		etnaviv_gem_describe_fence(fence, "Exclusive", m);
 	rcu_read_unlock();
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
index 0f18ba97b228..36fe5881667a 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -84,9 +84,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_i915_gem_busy *args = data;
 	struct dma_fence_array_cursor cursor;
-	struct dma_fence *fence, *readers;
+	struct dma_fence *fence, *writers, *readers;
 	struct drm_i915_gem_object *obj;
-	unsigned int seq;
 	int err;
 
 	err = -ENOENT;
@@ -112,21 +111,18 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 	 * to report the overall busyness. This is what the wait-ioctl does.
 	 *
 	 */
-retry:
-	seq = raw_read_seqcount(&obj->base.resv->seq);
+	writers = dma_resv_fences_get_rcu(&obj->base.resv->writers);
+	readers = dma_resv_fences_get_rcu(&obj->base.resv->readers);
 
 	/* Translate the exclusive fence to the READ *and* WRITE engine */
-	args->busy =
-		busy_check_writer(rcu_dereference(obj->base.resv->fence_excl));
+	args->busy = busy_check_writer(writers);
 
 	/* Translate shared fences to READ set of engines */
-	readers = dma_resv_fences_get_rcu(&obj->base.resv->readers);
 	dma_fence_array_for_each(fence, cursor, readers)
 		args->busy |= busy_check_reader(fence);
-	dma_fence_put(readers);
 
-	if (args->busy && read_seqcount_retry(&obj->base.resv->seq, seq))
-		goto retry;
+	dma_fence_put(writers);
+	dma_fence_put(readers);
 
 	err = 0;
 out:
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 6b3fad03b342..f865eadae965 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1324,8 +1324,9 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
 {
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
 	struct drm_device *dev = drm->dev;
-	struct dma_fence *fence = dma_resv_get_excl(bo->base.resv);
+	struct dma_fence *fence;
 
+	fence = dma_resv_fences_deref(bo->base.resv, &bo->base.resv->writers);
 	nv10_bo_put_tile_region(dev, *old_tile, fence);
 	*old_tile = new_tile;
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 350cd2a9ea51..a97878fbbc96 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -348,7 +348,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e
 			return ret;
 	}
 
-	fence = dma_resv_get_excl(resv);
+	fence = dma_resv_fences_deref(resv, &resv->writers);
 	if (fence) {
 		struct nouveau_channel *prev = NULL;
 		bool must_wait = true;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index e81b01f8db90..6ef589081c6b 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -533,7 +533,9 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
 		DRM_ERROR("failed to pin new rbo buffer before flip\n");
 		goto cleanup;
 	}
-	work->fence = dma_fence_get(dma_resv_get_excl(new_rbo->tbo.base.resv));
+	work->fence = dma_resv_fences_deref(new_rbo->tbo.base.resv,
+					    &new_rbo->tbo.base.resv->writers);
+	dma_fence_get(work->fence);
 	radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
 	radeon_bo_unreserve(new_rbo);
 
diff --git a/drivers/gpu/drm/radeon/radeon_sync.c b/drivers/gpu/drm/radeon/radeon_sync.c
index 971dd6c01e60..bf595428dabf 100644
--- a/drivers/gpu/drm/radeon/radeon_sync.c
+++ b/drivers/gpu/drm/radeon/radeon_sync.c
@@ -97,7 +97,7 @@ int radeon_sync_resv(struct radeon_device *rdev,
 	int r = 0;
 
 	/* always sync to the exclusive fence */
-	f = dma_resv_get_excl(resv);
+	f = dma_resv_fences_deref(resv, &resv->writers);
 	fence = f ? to_radeon_fence(f) : NULL;
 	if (fence && fence->rdev == rdev)
 		radeon_sync_fence(sync, fence);
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 1ad5c3b86b64..72bfcddbce2b 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -465,6 +465,7 @@ static int radeon_uvd_validate_codec(struct radeon_cs_parser *p,
 static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 			     unsigned offset, unsigned buf_sizes[])
 {
+	struct dma_resv *resv = bo->tbo.base.resv;
 	int32_t *msg, msg_type, handle;
 	unsigned img_size = 0;
 	struct dma_fence *f;
@@ -477,7 +478,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 		return -EINVAL;
 	}
 
-	f = dma_resv_get_excl(bo->tbo.base.resv);
+	f = dma_resv_fences_deref(resv, &resv->writers);
 	if (f) {
 		r = radeon_fence_wait((struct radeon_fence *)f, false);
 		if (r) {
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 19eeefbbb65a..53d4035778d0 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -455,7 +455,7 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
 {
 	struct dma_fence *fence;
 
-	fence = dma_resv_get_excl(&bo->base._resv);
+	fence = dma_resv_fences_deref(&bo->base._resv, &bo->base._resv.writers);
 	if (fence && !fence->ops->signaled)
 		dma_fence_enable_sw_signaling(fence);
 
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index b23e16975f39..72c3c4f99711 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -48,8 +48,6 @@
 struct dma_resv;
 
 extern struct ww_class reservation_ww_class;
-extern struct lock_class_key reservation_seqcount_class;
-extern const char reservation_seqcount_string[];
 
 /**
  * struct dma_resv_fences - fences inside a reservation object
@@ -76,15 +74,14 @@ void dma_resv_fences_commit(struct dma_resv *obj,
  * struct dma_resv - a reservation object manages fences for a buffer
  * @lock: update side lock
  * @seq: sequence count for managing RCU read-side synchronization
- * @fence_excl: the exclusive fence, if there is one currently
+ * @writers: array of write operations for implicit sync
  * @readers: array of read operations for implicit sync
  */
 struct dma_resv {
 	struct ww_mutex lock;
-	seqcount_t seq;
 
-	struct dma_fence __rcu *fence_excl;
-	struct dma_resv_fences	readers;
+	struct dma_resv_fences writers;
+	struct dma_resv_fences readers;
 };
 
 #define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base)
@@ -243,25 +240,6 @@ static inline void dma_resv_unlock(struct dma_resv *obj)
 	ww_mutex_unlock(&obj->lock);
 }
 
-/**
- * dma_resv_get_excl - get the reservation object's
- * exclusive fence, with update-side lock held
- * @obj: the reservation object
- *
- * Returns the exclusive fence (if any).  Does NOT take a
- * reference. Writers must hold obj->lock, readers may only
- * hold a RCU read side lock.
- *
- * RETURNS
- * The exclusive fence or NULL
- */
-static inline struct dma_fence *
-dma_resv_get_excl(struct dma_resv *obj)
-{
-	return rcu_dereference_protected(obj->fence_excl,
-					 dma_resv_held(obj));
-}
-
 /**
  * dma_resv_get_excl_rcu - get the reservation object's
  * exclusive fence, without lock held.
@@ -278,11 +256,8 @@ dma_resv_get_excl_rcu(struct dma_resv *obj)
 {
 	struct dma_fence *fence;
 
-	if (!rcu_access_pointer(obj->fence_excl))
-		return NULL;
-
 	rcu_read_lock();
-	fence = dma_fence_get_rcu_safe(&obj->fence_excl);
+	fence = dma_resv_fences_get_rcu(&obj->writers);
 	rcu_read_unlock();
 
 	return fence;
-- 
2.17.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2019-08-21 12:32 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-21 12:31 [RFC] replacing dma_resv API Christian König
2019-08-21 12:31 ` Christian König
2019-08-21 12:31 ` [PATCH 01/10] dma-buf: make to_dma_fence_array NULL safe Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 12:31 ` [PATCH 02/10] dma-buf: add dma_fence_array_alloc/free Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 12:31 ` [PATCH 03/10] dma-buf: add dma_fence_array_recycle Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 16:24   ` Chris Wilson
2019-08-21 16:24     ` Chris Wilson
2019-08-22  8:38     ` Christian König
2019-08-22  8:38       ` Christian König
2019-08-21 12:31 ` [PATCH 04/10] dma-buf: add dma_fence_array_for_each Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 12:31 ` [PATCH 05/10] dma-buf/resv: add dma_resv_prune_fences Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 14:55   ` Chris Wilson
2019-08-21 14:55     ` Chris Wilson
2019-08-21 14:56     ` Chris Wilson
2019-08-21 14:56       ` Chris Wilson
2019-08-21 12:31 ` [PATCH 06/10] dma-buf/resv: stop pruning shared fences when exclusive is added Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 12:31 ` [PATCH 07/10] dma-buf/resv: add new fences container implementation Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 16:04   ` Daniel Vetter
2019-08-21 16:04     ` Daniel Vetter
2019-08-22  8:23     ` Christian König
2019-08-22  8:23       ` Christian König
2019-08-22 13:02       ` Daniel Vetter
2019-08-22 13:02         ` Daniel Vetter
2019-08-22 13:53         ` Koenig, Christian
2019-08-22 13:53           ` Koenig, Christian
2019-08-21 12:31 ` [PATCH 08/10] dma-buf/resv: replace shared fence with new fences container Christian König
2019-08-21 12:31   ` Christian König
2019-08-21 15:24   ` Chris Wilson
2019-08-21 15:24     ` Chris Wilson
2019-08-21 17:35     ` Chris Wilson
2019-08-21 17:35       ` Chris Wilson
2019-08-22  8:37       ` Christian König
2019-08-22  8:37         ` Christian König
2019-08-22  9:16         ` Christian König
2019-08-22  9:16           ` Christian König
2019-08-21 16:21   ` Chris Wilson
2019-08-21 16:21     ` Chris Wilson
2019-08-24 13:22   ` Chris Wilson
2019-08-24 13:22     ` Chris Wilson
2019-08-21 12:31 ` Christian König [this message]
2019-08-21 12:31   ` [PATCH 09/10] dma-buf/resv: replace exclusive " Christian König
2019-08-21 12:31 ` [PATCH 10/10] dma-buf/resv: add other operations Christian König
2019-08-21 12:31   ` Christian König
2019-08-22 12:28   ` Ville Syrjälä
2019-08-22 12:28     ` Ville Syrjälä
2019-08-21 16:13 ` [RFC] replacing dma_resv API Daniel Vetter
2019-08-21 16:13   ` Daniel Vetter
2019-08-21 20:05   ` Daniel Vetter
2019-08-21 20:05     ` Daniel Vetter
2019-08-22  9:27     ` Christian König
2019-08-22  9:27       ` Christian König
2019-08-21 20:11 ` Chris Wilson
2019-08-21 20:11   ` Chris Wilson
2019-08-21 20:22   ` Daniel Vetter
2019-08-21 20:22     ` Daniel Vetter
2019-08-22  9:14     ` Christian König
2019-08-22  9:14       ` Christian König
2019-08-22 10:00       ` Daniel Vetter
2019-08-22 10:00         ` Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190821123147.110736-10-christian.koenig@amd.com \
    --to=ckoenig.leichtzumerken@gmail.com \
    --cc=chris@chris-wilson.co.uk \
    --cc=daniel.vetter@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linaro-mm-sig@lists.linaro.org \
    --cc=linux-media@vger.kernel.org \
    --cc=sumit.semwal@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.