Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6f8d26e authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/amdgpu: fix amdgpu_amdkfd_remove_eviction_fence v3



Fix quite a number of bugs here. Unfortunately only compile tested.

v2: fix copy&paste error
v3: fix 80 chars issue in comment

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c4aed876
Loading
Loading
Loading
Loading
+46 −57
Original line number Original line Diff line number Diff line
@@ -206,11 +206,9 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
					struct amdgpu_amdkfd_fence ***ef_list,
					struct amdgpu_amdkfd_fence ***ef_list,
					unsigned int *ef_count)
					unsigned int *ef_count)
{
{
	struct reservation_object_list *fobj;
	struct reservation_object *resv = bo->tbo.resv;
	struct reservation_object *resv;
	struct reservation_object_list *old, *new;
	unsigned int i = 0, j = 0, k = 0, shared_count;
	unsigned int i, j, k;
	unsigned int count = 0;
	struct amdgpu_amdkfd_fence **fence_list;


	if (!ef && !ef_list)
	if (!ef && !ef_list)
		return -EINVAL;
		return -EINVAL;
@@ -220,76 +218,67 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
		*ef_count = 0;
		*ef_count = 0;
	}
	}


	resv = bo->tbo.resv;
	old = reservation_object_get_list(resv);
	fobj = reservation_object_get_list(resv);
	if (!old)

	if (!fobj)
		return 0;
		return 0;


	preempt_disable();
	new = kmalloc(offsetof(typeof(*new), shared[old->shared_max]),
	write_seqcount_begin(&resv->seq);
		      GFP_KERNEL);
	if (!new)
		return -ENOMEM;


	/* Go through all the shared fences in the resevation object. If
	/* Go through all the shared fences in the resevation object and sort
	 * ef is specified and it exists in the list, remove it and reduce the
	 * the interesting ones to the end of the list.
	 * count. If ef is not specified, then get the count of eviction fences
	 * present.
	 */
	 */
	shared_count = fobj->shared_count;
	for (i = 0, j = old->shared_count, k = 0; i < old->shared_count; ++i) {
	for (i = 0; i < shared_count; ++i) {
		struct dma_fence *f;
		struct dma_fence *f;


		f = rcu_dereference_protected(fobj->shared[i],
		f = rcu_dereference_protected(old->shared[i],
					      reservation_object_held(resv));
					      reservation_object_held(resv));


		if (ef) {
		if ((ef && f->context == ef->base.context) ||
			if (f->context == ef->base.context) {
		    (!ef && to_amdgpu_amdkfd_fence(f)))
				dma_fence_put(f);
			RCU_INIT_POINTER(new->shared[--j], f);
				fobj->shared_count--;
		else
			} else {
			RCU_INIT_POINTER(new->shared[k++], f);
				RCU_INIT_POINTER(fobj->shared[j++], f);
			}
		} else if (to_amdgpu_amdkfd_fence(f))
			count++;
	}
	}
	write_seqcount_end(&resv->seq);
	new->shared_max = old->shared_max;
	preempt_enable();
	new->shared_count = k;


	if (ef || !count)
	if (!ef) {
		return 0;
		unsigned int count = old->shared_count - j;


	/* Alloc memory for count number of eviction fence pointers. Fill the
		/* Alloc memory for count number of eviction fence pointers.
	 * ef_list array and ef_count
		 * Fill the ef_list array and ef_count
		 */
		 */
	fence_list = kcalloc(count, sizeof(struct amdgpu_amdkfd_fence *),
		*ef_list = kcalloc(count, sizeof(**ef_list), GFP_KERNEL);
			     GFP_KERNEL);
		*ef_count = count;
	if (!fence_list)

		if (!*ef_list) {
			kfree(new);
			return -ENOMEM;
			return -ENOMEM;
		}
	}


	/* Install the new fence list, seqcount provides the barriers */
	preempt_disable();
	preempt_disable();
	write_seqcount_begin(&resv->seq);
	write_seqcount_begin(&resv->seq);
	RCU_INIT_POINTER(resv->fence, new);
	write_seqcount_end(&resv->seq);
	preempt_enable();


	j = 0;
	/* Drop the references to the removed fences or move them to ef_list */
	for (i = 0; i < shared_count; ++i) {
	for (i = j, k = 0; i < old->shared_count; ++i) {
		struct dma_fence *f;
		struct dma_fence *f;
		struct amdgpu_amdkfd_fence *efence;


		f = rcu_dereference_protected(fobj->shared[i],
		f = rcu_dereference_protected(new->shared[i],
					      reservation_object_held(resv));
					      reservation_object_held(resv));

		if (!ef)
		efence = to_amdgpu_amdkfd_fence(f);
			(*ef_list)[k++] = to_amdgpu_amdkfd_fence(f);
		if (efence) {
		else
			fence_list[k++] = efence;
			dma_fence_put(f);
			fobj->shared_count--;
		} else {
			RCU_INIT_POINTER(fobj->shared[j++], f);
		}
	}
	}

	kfree_rcu(old, rcu);
	write_seqcount_end(&resv->seq);
	preempt_enable();

	*ef_list = fence_list;
	*ef_count = k;


	return 0;
	return 0;
}
}