diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
index 0f98384b86d4..f5dc17aa5efb 100644
--- a/drivers/dma-buf/reservation.c
+++ b/drivers/dma-buf/reservation.c
@@ -316,6 +316,7 @@ EXPORT_SYMBOL(reservation_object_copy_fences);
  * reservation_object_get_fences_rcu - Get an object's shared and exclusive
  * fences without update side lock held
  * @obj: the reservation object
+ * @writes_only: if true then only write operations are returned
  * @pfence_excl: the returned exclusive fence (or NULL)
  * @pshared_count: the number of shared fences returned
  * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
@@ -326,6 +327,7 @@ EXPORT_SYMBOL(reservation_object_copy_fences);
  * shared fences as well. Returns either zero or -ENOMEM.
  */
 int reservation_object_get_fences_rcu(struct reservation_object *obj,
+				      bool writes_only,
 				      struct dma_fence **pfence_excl,
 				      unsigned *pshared_count,
 				      struct dma_fence ***pshared)
@@ -358,6 +360,7 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 
 		if (sz) {
 			struct dma_fence **nshared;
+			unsigned int j;
 
 			nshared = krealloc(shared, sz,
 					   GFP_NOWAIT | __GFP_NOWARN);
@@ -374,13 +377,20 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 			}
 			shared = nshared;
 			shared_count = fobj ? fobj->shared_count : 0;
-			for (i = 0; i < shared_count; ++i) {
-				void *e = rcu_dereference(fobj->shared[i]);
+			for (i = 0, j = 0; j < shared_count; ++j) {
+				void *e = rcu_dereference(fobj->shared[j]);
+
+				if (writes_only &&
+				    !reservation_object_shared_is_write(e))
+					continue;
 
 				shared[i] = reservation_object_shared_fence(e);
 				if (!dma_fence_get_rcu(shared[i]))
-					break;
+					goto drop_references;
+
+				i++;
 			}
+			shared_count = i;
 
 			if (!pfence_excl && fence_excl) {
 				shared[i] = fence_excl;
@@ -390,7 +400,8 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 			}
 		}
 
-		if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
+		if (read_seqcount_retry(&obj->seq, seq)) {
+drop_references:
 			while (i--)
 				dma_fence_put(shared[i]);
 			dma_fence_put(fence_excl);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 7d6a36bca9dd..a6d2ba4b4d2d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -200,7 +200,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
 		goto unpin;
 	}
 
-	r = reservation_object_get_fences_rcu(new_abo->tbo.resv, &work->excl,
+	r = reservation_object_get_fences_rcu(new_abo->tbo.resv, false,
+					      &work->excl,
 					      &work->shared_count,
 					      &work->shared);
 	if (unlikely(r != 0)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 3a072a7a39f0..82de4eb38dff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -112,7 +112,8 @@ void amdgpu_pasid_free_delayed(struct reservation_object *resv,
 	unsigned count;
 	int r;
 
-	r = reservation_object_get_fences_rcu(resv, NULL, &count, &fences);
+	r = reservation_object_get_fences_rcu(resv, false, NULL,
+					      &count, &fences);
 	if (r)
 		goto fallback;
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 015613b4f98b..e1bb6f13de41 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -1841,7 +1841,7 @@ static void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 	unsigned i, shared_count;
 	int r;
 
-	r = reservation_object_get_fences_rcu(resv, &excl,
+	r = reservation_object_get_fences_rcu(resv, false, &excl,
 					      &shared_count, &shared);
 	if (r) {
 		/* Not enough memory to grab the fence list, as last resort
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index 5f4a872a88dd..fda8be5be574 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -188,7 +188,8 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit)
 			continue;
 
 		if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
-			ret = reservation_object_get_fences_rcu(robj, &bo->excl,
+			ret = reservation_object_get_fences_rcu(robj, false,
+								&bo->excl,
 								&bo->nr_shared,
 								&bo->shared);
 			if (ret)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0415420e1cfd..85013933e827 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -517,7 +517,7 @@ i915_gem_object_wait_reservation(struct reservation_object *resv,
 		unsigned int count, i;
 		int ret;
 
-		ret = reservation_object_get_fences_rcu(resv,
+		ret = reservation_object_get_fences_rcu(resv, false,
 							&excl, &count, &shared);
 		if (ret)
 			return ret;
@@ -619,7 +619,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
 		unsigned int count, i;
 		int ret;
 
-		ret = reservation_object_get_fences_rcu(obj->resv,
+		ret = reservation_object_get_fences_rcu(obj->resv, false,
 							&excl, &count, &shared);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index f187250e60c6..8b5d87353f54 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -981,7 +981,7 @@ i915_request_await_object(struct i915_request *to,
 		struct dma_fence **shared;
 		unsigned int count, i;
 
-		ret = reservation_object_get_fences_rcu(obj->resv,
+		ret = reservation_object_get_fences_rcu(obj->resv, false,
 							&excl, &count, &shared);
 		if (ret)
 			return ret;
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 1de5173e53a2..1da2c5a99e47 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -499,7 +499,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
 		struct dma_fence **shared;
 		unsigned int count, i;
 
-		ret = reservation_object_get_fences_rcu(resv,
+		ret = reservation_object_get_fences_rcu(resv, false,
 							&excl, &count, &shared);
 		if (ret)
 			return ret;
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index d73bf025df4b..c6defd955aa3 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -296,6 +296,7 @@ void reservation_object_add_excl_fence(struct reservation_object *obj,
 				       struct dma_fence *fence);
 
 int reservation_object_get_fences_rcu(struct reservation_object *obj,
+				      bool writes_only,
 				      struct dma_fence **pfence_excl,
 				      unsigned *pshared_count,
 				      struct dma_fence ***pshared);
