[PATCH 09/11] dma-buf: add shared fence usage flags

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


Add usage flags for shared fences and improve the documentation.

This allows driver to better specify what shared fences
are doing with the resource.

Signed-off-by: Christian König <christian.koenig at amd.com>
---
 drivers/dma-buf/dma-resv.c                    | 132 +++++++++++++-----
 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  |   2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_object.c    |   2 +-
 drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c  |   4 +-
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c    |   3 +-
 drivers/gpu/drm/i915/i915_vma.c               |   2 +-
 drivers/gpu/drm/msm/msm_gpu.c                 |   3 +-
 drivers/gpu/drm/nouveau/nouveau_bo.c          |   2 +-
 drivers/gpu/drm/qxl/qxl_release.c             |   3 +-
 drivers/gpu/drm/radeon/radeon_object.c        |   2 +-
 drivers/gpu/drm/ttm/ttm_bo.c                  |   2 +-
 drivers/gpu/drm/ttm/ttm_execbuf_util.c        |   3 +-
 drivers/gpu/drm/vc4/vc4_gem.c                 |   3 +-
 drivers/gpu/drm/vgem/vgem_fence.c             |   2 +-
 include/linux/dma-resv.h                      |  21 ++-
 15 files changed, 135 insertions(+), 51 deletions(-)

diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c
index ef7e0464e08d..bf72c162fd70 100644
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -49,17 +49,35 @@
 struct dma_resv_list {
 	struct rcu_head rcu;
 	u32 shared_count, shared_max;
-	struct dma_fence __rcu *shared[];
+	unsigned long shared[];
 };
 
 /**
  * DOC: Reservation Object Overview
  *
- * The reservation object provides a mechanism to manage shared and
- * exclusive fences associated with a buffer.  A reservation object
- * can have attached one exclusive fence (normally associated with
- * write operations) or N shared fences (read operations).  The RCU
- * mechanism is used to protect read access to fences from locked
+ * The reservation object provides a mechanism to manage shared and exclusive
+ * fences associated with a buffer. A reservation object can have attached one
+ * exclusive fence or multiple shared fences. Using the exclusive fence
+ * effectively serializes all accesses to the resource while using the shared
+ * fence slots allows for concurrent access.
+ *
+ * Because of this newly added DMA operations which want to use a resource
+ * always needs to wait for the existing exclusive fence before they start,
+ * no matter if they are added as shared or exclusive one.
+ *
+ * To aid drivers in determining if they need to wait for a shared resource
+ * usage flags should be given with each shared fence added to the resource.
+ *
+ * @DMA_RESV_USAGE_NONE is used for special cases where no waiting is desired.
+ * @DMA_RESV_USAGE_READ is used to note that the resource is read by this
+ * operation and writers should wait for it.
+ * @DMA_RESV_USAGE_WRITE is used to note that the resource is written by this
+ * operation and readers should wait for it.
+ * @DMA_RESV_USAGE_RW is used to note that the resource is both read and
+ * written.
+ *
+ * When drivers access the fences contained inside the dma_resv object the RCU
+ * mechanism can be used to protect read access to fences from locked
  * write-side updates.
  */
 
@@ -100,8 +118,12 @@ static void dma_resv_list_free(struct dma_resv_list *list)
 	if (!list)
 		return;
 
-	for (i = 0; i < list->shared_count; ++i)
-		dma_fence_put(rcu_dereference_protected(list->shared[i], true));
+	for (i = 0; i < list->shared_count; ++i) {
+		struct dma_fence __rcu *fence;
+
+		fence = (void __rcu *)(list->shared[i] & ~DMA_RESV_USAGE_RW);
+		dma_fence_put(rcu_dereference_protected(fence, true));
+	}
 
 	kfree_rcu(list, rcu);
 }
@@ -111,15 +133,44 @@ static void dma_resv_list_free(struct dma_resv_list *list)
  * @obj: the reservation object
  * @list: list to get the fence from
  * @idx: index into the fence array
+ * @val: optional original value
  *
  * Return the fence at the specified index double checking that either the rcu
  * read side or the dma_resv object is held.
  */
-static struct dma_fence *dma_resv_list_fence(struct dma_resv *obj,
-					     struct dma_resv_list *list,
-					     unsigned int idx)
+static inline struct dma_fence *dma_resv_list_fence(struct dma_resv *obj,
+						    struct dma_resv_list *list,
+						    unsigned int idx,
+						    unsigned long *val)
 {
-	return rcu_dereference_check(list->shared[idx], dma_resv_held(obj));
+	struct dma_fence __rcu *fence;
+	unsigned long tmp = READ_ONCE(list->shared[idx]);
+
+	if (val)
+		*val = tmp;
+
+	fence = (void __rcu *)(tmp & ~DMA_RESV_USAGE_RW);
+	return rcu_dereference_check(fence, dma_resv_held(obj));
+}
+
+/**
+ * dma_resv_list_assign - assign fence and usage
+ * @list: list to assign the fence to
+ * @idx: index where to assign the fence
+ * @f: the fence to assign
+ * @usage: the usage to use
+ *
+ * Assign the fence and usage to the slot at position idx.
+ */
+static void dma_resv_list_assign(struct dma_resv_list *list,
+				 unsigned int idx,
+				 struct dma_fence *f,
+				 uint32_t usage)
+{
+	struct dma_fence __rcu *fence;
+
+	rcu_assign_pointer(fence, f);
+	WRITE_ONCE(list->shared[idx], ((unsigned long __force)fence) | usage);
 }
 
 /**
@@ -200,10 +251,17 @@ EXPORT_SYMBOL(dma_resv_first_shared);
 struct dma_fence *dma_resv_next_shared(struct dma_resv *obj,
 				       struct dma_resv_cursor *cursor)
 {
+	struct dma_fence *fence;
+	unsigned long val;
+	int idx;
+
 	if (cursor->i >= cursor->fences->shared_count)
 		return NULL;
 
-	return dma_resv_list_fence(obj, cursor->fences, cursor->i++);
+	idx = cursor->i++;
+	fence = dma_resv_list_fence(obj, cursor->fences, idx, &val);
+	cursor->usage = val & DMA_RESV_USAGE_RW;
+	return fence;
 }
 EXPORT_SYMBOL(dma_resv_next_shared);
 
@@ -246,13 +304,14 @@ int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences)
 	 * the new.
 	 */
 	for (i = 0, j = 0, k = max; i < (old ? old->shared_count : 0); ++i) {
-		struct dma_fence *fence;
+		struct dma_fence * fence;
+		unsigned long val;
 
-		fence = dma_resv_list_fence(obj, old, i);
+		fence = dma_resv_list_fence(obj, old, i, &val);
 		if (dma_fence_is_signaled(fence))
-			RCU_INIT_POINTER(new->shared[--k], fence);
+			new->shared[--k] = val;
 		else
-			RCU_INIT_POINTER(new->shared[j++], fence);
+			new->shared[j++] = val;
 	}
 	new->shared_count = j;
 
@@ -271,7 +330,7 @@ int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences)
 
 	/* Drop the references to the signaled fences */
 	for (i = k; i < max; ++i)
-		dma_fence_put(dma_resv_list_fence(obj, new, i));
+		dma_fence_put(dma_resv_list_fence(obj, new, i, NULL));
 	kfree_rcu(old, rcu);
 
 	return 0;
@@ -298,14 +357,16 @@ void dma_resv_reset_shared_max(struct dma_resv *obj)
 #endif
 
 /**
- * dma_resv_add_shared_fence - Add a fence to a shared slot
+ * dma_resv_add_shared - Add a fence to a shared slot
  * @obj: the reservation object
  * @fence: the shared fence to add
+ * @usage: how the fence is using the resource
  *
  * Add a fence to a shared slot, obj->lock must be held, and
  * dma_resv_reserve_shared() has been called.
  */
-void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
+void dma_resv_add_shared(struct dma_resv *obj, struct dma_fence *fence,
+			 enum dma_resv_usage usage)
 {
 	struct dma_resv_list *fobj;
 	struct dma_fence *old;
@@ -321,8 +382,7 @@ void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
 	write_seqcount_begin(&obj->seq);
 
 	for (i = 0; i < count; ++i) {
-
-		old = dma_resv_list_fence(obj, fobj, i);
+		old = dma_resv_list_fence(obj, fobj, i, NULL);
 		if (old->context == fence->context ||
 		    dma_fence_is_signaled(old))
 			goto replace;
@@ -333,20 +393,21 @@ void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
 	count++;
 
 replace:
-	RCU_INIT_POINTER(fobj->shared[i], fence);
+	dma_resv_list_assign(fobj, i, fence, usage);
 	/* pointer update must be visible before we extend the shared_count */
 	smp_store_mb(fobj->shared_count, count);
 
 	write_seqcount_end(&obj->seq);
 	dma_fence_put(old);
 }
-EXPORT_SYMBOL(dma_resv_add_shared_fence);
+EXPORT_SYMBOL(dma_resv_add_shared);
 
 /**
  * dma_resv_replace_shared - replace shared fences
  * @obj: the reservation object
  * @context: the context of the fences to replace
  * @fence: the new fence to use instead
+ * @usage: how the fence is using the resource
  *
  * Replace fences with a specified context with a new fence. Only valid if the
  * operation represented by the original fences is completed or has no longer
@@ -354,7 +415,7 @@ EXPORT_SYMBOL(dma_resv_add_shared_fence);
  * completes. Takes the reference to the new fence.
  */
 void dma_resv_replace_shared(struct dma_resv *obj, uint64_t context,
-			     struct dma_fence *fence)
+			     struct dma_fence *fence, enum dma_resv_usage usage)
 {
 	struct dma_resv_list *list;
 	unsigned int i;
@@ -367,12 +428,13 @@ void dma_resv_replace_shared(struct dma_resv *obj, uint64_t context,
 
 	write_seqcount_begin(&obj->seq);
 	for (i = 0; i < list->shared_count; ++i) {
-		struct dma_fence *old = dma_resv_list_fence(obj, list, i);
+		struct dma_fence *old;
 
+		old = dma_resv_list_fence(obj, list, i, NULL);
 		if (old->context != context)
 			continue;
 
-		rcu_assign_pointer(list->shared[i], dma_fence_get(fence));
+		dma_resv_list_assign(list, i, fence, usage);
 		dma_fence_put(old);
 	}
 	write_seqcount_end(&obj->seq);
@@ -411,7 +473,7 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence)
 
 	/* inplace update, no shared fences */
 	while (i--)
-		dma_fence_put(dma_resv_list_fence(obj, old, i));
+		dma_fence_put(dma_resv_list_fence(obj, old, i, NULL));
 
 	dma_fence_put(old_fence);
 }
@@ -454,10 +516,10 @@ int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
 
 		dst_list->shared_count = 0;
 		for (i = 0; i < src_list->shared_count; ++i) {
-			struct dma_fence __rcu **dst;
 			struct dma_fence *fence;
+			unsigned long val;
 
-			fence = dma_resv_list_fence(src, src_list, i);
+			fence = dma_resv_list_fence(src, src_list, i, &val);
 			if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
 				     &fence->flags))
 				continue;
@@ -473,8 +535,7 @@ int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src)
 				continue;
 			}
 
-			dst = &dst_list->shared[dst_list->shared_count++];
-			rcu_assign_pointer(*dst, fence);
+			dst_list->shared[dst_list->shared_count++] = val;
 		}
 	} else {
 		dst_list = NULL;
@@ -566,7 +627,8 @@ int dma_resv_get_fences_rcu(struct dma_resv *obj,
 			shared = nshared;
 			shared_count = fobj ? fobj->shared_count : 0;
 			for (i = 0; i < shared_count; ++i) {
-				shared[i] = dma_resv_list_fence(obj, fobj, i);
+				shared[i] = dma_resv_list_fence(obj, fobj,
+								i, NULL);
 				if (!dma_fence_get_rcu(shared[i]))
 					break;
 			}
@@ -650,7 +712,7 @@ long dma_resv_wait_timeout_rcu(struct dma_resv *obj,
 		for (i = 0; !fence && i < shared_count; ++i) {
 			struct dma_fence *lfence;
 
-			lfence = dma_resv_list_fence(obj, fobj, i);
+			lfence = dma_resv_list_fence(obj, fobj, i, NULL);
 			if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
 				     &lfence->flags))
 				continue;
@@ -736,7 +798,7 @@ bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all)
 		for (i = 0; i < shared_count; ++i) {
 			struct dma_fence *fence;
 
-			fence = dma_resv_list_fence(obj, fobj, i);
+			fence = dma_resv_list_fence(obj, fobj, i, NULL);
 			ret = dma_resv_test_signaled_single(fence);
 			if (ret < 0)
 				goto retry;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 3e5a681a5482..50bdf9bfd030 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -245,7 +245,7 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
 	 * table update and TLB flush here directly.
 	 */
 	dma_resv_replace_shared(bo->tbo.base.resv, ef->base.context,
-				dma_fence_get_stub());
+				dma_fence_get_stub(), DMA_RESV_USAGE_NONE);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 0adffcace326..1190781cefcb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -1422,7 +1422,7 @@ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
 	struct dma_resv *resv = bo->tbo.base.resv;
 
 	if (shared)
-		dma_resv_add_shared_fence(resv, fence);
+		dma_resv_add_shared(resv, fence, DMA_RESV_USAGE_RW);
 	else
 		dma_resv_add_excl_fence(resv, fence);
 }
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index d05c35994579..f0e69c514275 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -214,8 +214,8 @@ static void submit_attach_object_fences(struct etnaviv_gem_submit *submit)
 			dma_resv_add_excl_fence(obj->resv,
 							  submit->out_fence);
 		else
-			dma_resv_add_shared_fence(obj->resv,
-							    submit->out_fence);
+			dma_resv_add_shared(obj->resv, submit->out_fence,
+					    DMA_RESV_USAGE_READ);
 
 		submit_unlock_object(submit, i);
 	}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 5964e67c7d36..16138bc2dbe4 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -2551,7 +2551,8 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb,
 		goto err_commit;
 
 	/* Keep the batch alive and unwritten as we parse */
-	dma_resv_add_shared_fence(pw->batch->resv, &pw->base.dma);
+	dma_resv_add_shared(pw->batch->resv, &pw->base.dma,
+			    DMA_RESV_USAGE_READ);
 
 	/* Force execution to wait for completion of the parser */
 	dma_resv_add_excl_fence(shadow->resv, &pw->base.dma);
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 07490db51cdc..0d177a7687cb 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -1256,7 +1256,7 @@ int i915_vma_move_to_active(struct i915_vma *vma,
 				return err;
 		}
 
-		dma_resv_add_shared_fence(vma->resv, &rq->fence);
+		dma_resv_add_shared(vma->resv, &rq->fence, DMA_RESV_USAGE_READ);
 		obj->write_domain = 0;
 	}
 
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 9dd1c58430ab..82f98a4224f7 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -820,7 +820,8 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
 		if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
 			dma_resv_add_excl_fence(drm_obj->resv, submit->fence);
 		else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
-			dma_resv_add_shared_fence(drm_obj->resv, submit->fence);
+			dma_resv_add_shared(drm_obj->resv, submit->fence,
+					    DMA_RESV_USAGE_READ);
 
 		msm_gem_active_get(drm_obj, gpu);
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index ad30a6a100b9..b2c13c63f93c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1313,7 +1313,7 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool excl
 	if (exclusive)
 		dma_resv_add_excl_fence(resv, &fence->base);
 	else if (fence)
-		dma_resv_add_shared_fence(resv, &fence->base);
+		dma_resv_add_shared(resv, &fence->base, DMA_RESV_USAGE_RW);
 }
 
 static void
diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
index b19f2f00b215..b725e3fbbb49 100644
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -429,7 +429,8 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release)
 	list_for_each_entry(entry, &release->bos, head) {
 		bo = entry->bo;
 
-		dma_resv_add_shared_fence(bo->base.resv, &release->base);
+		dma_resv_add_shared(bo->base.resv, &release->base,
+				    DMA_RESV_USAGE_READ);
 		ttm_bo_move_to_lru_tail_unlocked(bo);
 		dma_resv_unlock(bo->base.resv);
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index cee11c55fd15..b744cd766bb1 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -815,7 +815,7 @@ void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence,
 	struct dma_resv *resv = bo->tbo.base.resv;
 
 	if (shared)
-		dma_resv_add_shared_fence(resv, &fence->base);
+		dma_resv_add_shared(resv, &fence->base, DMA_RESV_USAGE_READ);
 	else
 		dma_resv_add_excl_fence(resv, &fence->base);
 }
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 16b869d9b1d6..c9bbc4630afc 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -700,7 +700,7 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
 		return ret;
 	}
 
-	dma_resv_add_shared_fence(bo->base.resv, fence);
+	dma_resv_add_shared(bo->base.resv, fence, DMA_RESV_USAGE_RW);
 
 	ret = dma_resv_reserve_shared(bo->base.resv, 1);
 	if (unlikely(ret)) {
diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
index 071c48d672c6..8ed1d89cfeeb 100644
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -156,7 +156,8 @@ void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
 		struct ttm_buffer_object *bo = entry->bo;
 
 		if (entry->num_shared)
-			dma_resv_add_shared_fence(bo->base.resv, fence);
+			dma_resv_add_shared(bo->base.resv, fence,
+					    DMA_RESV_USAGE_RW);
 		else
 			dma_resv_add_excl_fence(bo->base.resv, fence);
 		ttm_bo_move_to_lru_tail_unlocked(bo);
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index 445d3bab89e0..2ab59abcea1a 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -543,7 +543,8 @@ vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno)
 		bo = to_vc4_bo(&exec->bo[i]->base);
 		bo->seqno = seqno;
 
-		dma_resv_add_shared_fence(bo->base.base.resv, exec->fence);
+		dma_resv_add_shared(bo->base.base.resv, exec->fence,
+				    DMA_RESV_USAGE_READ);
 	}
 
 	list_for_each_entry(bo, &exec->unref_list, unref_head) {
diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c
index 2902dc6e64fa..cb5e731d07af 100644
--- a/drivers/gpu/drm/vgem/vgem_fence.c
+++ b/drivers/gpu/drm/vgem/vgem_fence.c
@@ -163,7 +163,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev,
 	if (arg->flags & VGEM_FENCE_WRITE)
 		dma_resv_add_excl_fence(resv, fence);
 	else if ((ret = dma_resv_reserve_shared(resv, 1)) == 0)
-		dma_resv_add_shared_fence(resv, fence);
+		dma_resv_add_shared(resv, fence, DMA_RESV_USAGE_READ);
 	dma_resv_unlock(resv);
 
 	/* Record the fence in our idr for later signaling */
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h
index bb6911baac3d..e5afffaec579 100644
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -49,6 +49,20 @@ struct dma_resv_list;
 
 extern struct ww_class reservation_ww_class;
 
+/**
+ * enum dma_resv_usage - how a DMA resource is used for implicit sync
+ * @DMA_RESV_USAGE_NONE: Only for memory management
+ * @DMA_RESV_USAGE_READ: Read only access
+ * @DMA_RESV_USAGE_WRITE: Write only access
+ * @DMA_RESV_USAGE_RW: Both read and write access
+ */
+enum dma_resv_usage {
+	DMA_RESV_USAGE_NONE	= 0,
+	DMA_RESV_USAGE_READ	= 1 << 0,
+	DMA_RESV_USAGE_WRITE	= 1 << 1,
+	DMA_RESV_USAGE_RW	= (DMA_RESV_USAGE_READ | DMA_RESV_USAGE_WRITE)
+};
+
 /**
  * struct dma_resv - a reservation object manages fences for a buffer
  * @lock: update side lock
@@ -66,6 +80,7 @@ struct dma_resv {
 
 struct dma_resv_cursor {
 	struct dma_resv_list *fences;
+	enum dma_resv_usage usage;
 	unsigned int i;
 };
 
@@ -259,9 +274,11 @@ dma_resv_get_excl_rcu(struct dma_resv *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);
-void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence);
+void dma_resv_add_shared(struct dma_resv *obj, struct dma_fence *fence,
+			 enum dma_resv_usage usage);
 void dma_resv_replace_shared(struct dma_resv *obj, uint64_t context,
-			     struct dma_fence *fence);
+			     struct dma_fence *fence,
+			     enum dma_resv_usage usage);
 
 void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence);
 
-- 
2.25.1



More information about the dri-devel mailing list