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

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
...@@ -206,11 +206,9 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, ...@@ -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, ...@@ -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)
return 0;
/* Alloc memory for count number of eviction fence pointers. Fill the
* ef_list array and ef_count
*/
fence_list = kcalloc(count, sizeof(struct amdgpu_amdkfd_fence *),
GFP_KERNEL);
if (!fence_list)
return -ENOMEM;
preempt_disable(); if (!ef) {
write_seqcount_begin(&resv->seq); unsigned int count = old->shared_count - j;
j = 0; /* Alloc memory for count number of eviction fence pointers.
for (i = 0; i < shared_count; ++i) { * Fill the ef_list array and ef_count
struct dma_fence *f; */
struct amdgpu_amdkfd_fence *efence; *ef_list = kcalloc(count, sizeof(**ef_list), GFP_KERNEL);
*ef_count = count;
f = rcu_dereference_protected(fobj->shared[i],
reservation_object_held(resv));
efence = to_amdgpu_amdkfd_fence(f); if (!*ef_list) {
if (efence) { kfree(new);
fence_list[k++] = efence; return -ENOMEM;
fobj->shared_count--;
} else {
RCU_INIT_POINTER(fobj->shared[j++], f);
} }
} }
/* 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); write_seqcount_end(&resv->seq);
preempt_enable(); preempt_enable();
*ef_list = fence_list; /* Drop the references to the removed fences or move them to ef_list */
*ef_count = k; 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));
if (!ef)
(*ef_list)[k++] = to_amdgpu_amdkfd_fence(f);
else
dma_fence_put(f);
}
kfree_rcu(old, rcu);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment