[PATCH 2/2] dma-buf: cleanup shared fence removal

Christian König ckoenig.leichtzumerken at gmail.com
Thu Jun 27 10:18:13 UTC 2019


While freeing up memory it is easier to remove a fence from a reservation
object instead of signaling it and installing a new one in all other objects.

Clean this up by adding the removal function to the core reservation object
code instead of messing with the internal in amdgpu.

No functional change.

Signed-off-by: Christian König <christian.koenig at amd.com>
---
 drivers/dma-buf/reservation.c                 | 62 +++++++++++++++++++
 .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 45 +-------------
 include/linux/reservation.h                   |  3 +-
 3 files changed, 65 insertions(+), 45 deletions(-)

diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
index ef710effedfa..e43a316a005d 100644
--- a/drivers/dma-buf/reservation.c
+++ b/drivers/dma-buf/reservation.c
@@ -231,6 +231,68 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
 }
 EXPORT_SYMBOL(reservation_object_add_shared_fence);
 
+/**
+ * reservation_object_remove_shared_fence - remove shared fences
+ * @obj: the reservation object
+ * @context: the context of the fences to remove
+ *
+ * Remove shared fences based on their fence context.
+ */
+int reservation_object_remove_shared_fence(struct reservation_object *obj,
+					   uint64_t context)
+{
+	struct reservation_object_list *old, *new;
+	unsigned int i, j, k;
+
+	reservation_object_assert_held(obj);
+
+	old = reservation_object_get_list(obj);
+	if (!old)
+		return 0;
+
+	new = kmalloc(offsetof(typeof(*new), shared[old->shared_max]),
+		      GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+
+	/* Go through all the shared fences in the resevation object and sort
+	 * the interesting ones to the end of the new list.
+	 */
+	for (i = 0, j = old->shared_count, k = 0; i < old->shared_count; ++i) {
+		struct dma_fence *f;
+
+		f = rcu_dereference_protected(old->shared[i],
+					      reservation_object_held(obj));
+
+		if (f->context == context)
+			RCU_INIT_POINTER(new->shared[--j], f);
+		else
+			RCU_INIT_POINTER(new->shared[k++], f);
+	}
+	new->shared_max = old->shared_max;
+	new->shared_count = k;
+
+	/* Install the new fence list, seqcount provides the barriers */
+	preempt_disable();
+	write_seqcount_begin(&obj->seq);
+	RCU_INIT_POINTER(obj->fence, new);
+	write_seqcount_end(&obj->seq);
+	preempt_enable();
+
+	/* Drop the references to the removed fences */
+	for (i = j, k = 0; i < old->shared_count; ++i) {
+		struct dma_fence *f;
+
+		f = rcu_dereference_protected(new->shared[i],
+					      reservation_object_held(obj));
+		dma_fence_put(f);
+	}
+	kfree_rcu(old, rcu);
+
+	return 0;
+}
+EXPORT_SYMBOL(reservation_object_remove_shared_fence);
+
 /**
  * reservation_object_add_excl_fence - Add an exclusive fence.
  * @obj: the reservation object
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 10abae398e51..9b25ad3d003e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -224,50 +224,7 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
 	if (!ef)
 		return -EINVAL;
 
-	old = reservation_object_get_list(resv);
-	if (!old)
-		return 0;
-
-	new = kmalloc(offsetof(typeof(*new), shared[old->shared_max]),
-		      GFP_KERNEL);
-	if (!new)
-		return -ENOMEM;
-
-	/* Go through all the shared fences in the resevation object and sort
-	 * the interesting ones to the end of the list.
-	 */
-	for (i = 0, j = old->shared_count, k = 0; i < old->shared_count; ++i) {
-		struct dma_fence *f;
-
-		f = rcu_dereference_protected(old->shared[i],
-					      reservation_object_held(resv));
-
-		if (f->context == ef->base.context)
-			RCU_INIT_POINTER(new->shared[--j], f);
-		else
-			RCU_INIT_POINTER(new->shared[k++], f);
-	}
-	new->shared_max = old->shared_max;
-	new->shared_count = k;
-
-	/* Install the new fence list, seqcount provides the barriers */
-	preempt_disable();
-	write_seqcount_begin(&resv->seq);
-	RCU_INIT_POINTER(resv->fence, new);
-	write_seqcount_end(&resv->seq);
-	preempt_enable();
-
-	/* Drop the references to the removed fences or move them to ef_list */
-	for (i = j, k = 0; i < old->shared_count; ++i) {
-		struct dma_fence *f;
-
-		f = rcu_dereference_protected(new->shared[i],
-					      reservation_object_held(resv));
-		dma_fence_put(f);
-	}
-	kfree_rcu(old, rcu);
-
-	return 0;
+	return reservation_object_remove_shared_fence(resv, ef->base.context);
 }
 
 static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain,
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index f47e8196d039..1c833a56b678 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -229,7 +229,8 @@ int reservation_object_reserve_shared(struct reservation_object *obj,
 				      unsigned int num_fences);
 void reservation_object_add_shared_fence(struct reservation_object *obj,
 					 struct dma_fence *fence);
-
+int reservation_object_remove_shared_fence(struct reservation_object *obj,
+					   uint64_t context);
 void reservation_object_add_excl_fence(struct reservation_object *obj,
 				       struct dma_fence *fence);
 
-- 
2.17.1



More information about the dri-devel mailing list