mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 06:41:39 -04:00
drm/amdgpu: drop userq fence driver refs out of fence process()
amdgpu_userq_wait_ioctl() takes extra references on waited-on fence
drivers and stores them in waitq->fence_drv_xa. When a new userq fence is
created, those references are transferred into userq_fence->fence_drv_array
so they can be released when the fence completes.
However, those inherited references are currently only dropped from
amdgpu_userq_fence_driver_process(). If a fence never reaches that path,
such as it is already signaled when created, so we need to explicitly release
those fences in that case.
v2: use a list(list_cut_before) for managing the signal userq driver fences.(Christian)
Link: https://patchwork.freedesktop.org/patch/718078/?series=164763&rev=2
v3: Doesn't cache the userq first unsignaled fence and use the cut before list
head directly.(Christian)
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Prike Liang <Prike.Liang@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
b250a43bf5
commit
dd88d42d9c
@@ -145,13 +145,22 @@ amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq)
|
||||
amdgpu_userq_fence_driver_put(userq->fence_drv);
|
||||
}
|
||||
|
||||
static void
|
||||
amdgpu_userq_fence_put_fence_drv_array(struct amdgpu_userq_fence *userq_fence)
|
||||
{
|
||||
unsigned long i;
|
||||
for (i = 0; i < userq_fence->fence_drv_array_count; i++)
|
||||
amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]);
|
||||
userq_fence->fence_drv_array_count = 0;
|
||||
}
|
||||
|
||||
void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_drv)
|
||||
{
|
||||
struct amdgpu_userq_fence *userq_fence, *tmp;
|
||||
LIST_HEAD(to_be_signaled);
|
||||
struct dma_fence *fence;
|
||||
unsigned long flags;
|
||||
u64 rptr;
|
||||
int i;
|
||||
|
||||
if (!fence_drv)
|
||||
return;
|
||||
@@ -159,21 +168,26 @@ void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_d
|
||||
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
|
||||
rptr = amdgpu_userq_fence_read(fence_drv);
|
||||
|
||||
list_for_each_entry_safe(userq_fence, tmp, &fence_drv->fences, link) {
|
||||
fence = &userq_fence->base;
|
||||
|
||||
if (rptr < fence->seqno)
|
||||
list_for_each_entry(userq_fence, &fence_drv->fences, link) {
|
||||
if (rptr < userq_fence->base.seqno)
|
||||
break;
|
||||
}
|
||||
|
||||
list_cut_before(&to_be_signaled, &fence_drv->fences,
|
||||
&userq_fence->link);
|
||||
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(userq_fence, tmp, &to_be_signaled, link) {
|
||||
fence = &userq_fence->base;
|
||||
list_del_init(&userq_fence->link);
|
||||
dma_fence_signal(fence);
|
||||
|
||||
for (i = 0; i < userq_fence->fence_drv_array_count; i++)
|
||||
amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]);
|
||||
|
||||
list_del(&userq_fence->link);
|
||||
/* Drop fence_drv_array outside fence_list_lock
|
||||
* to avoid the recursion lock.
|
||||
*/
|
||||
amdgpu_userq_fence_put_fence_drv_array(userq_fence);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
void amdgpu_userq_fence_driver_destroy(struct kref *ref)
|
||||
@@ -228,6 +242,7 @@ static int amdgpu_userq_fence_create(struct amdgpu_usermode_queue *userq,
|
||||
struct amdgpu_userq_fence_driver *fence_drv;
|
||||
struct dma_fence *fence;
|
||||
unsigned long flags;
|
||||
bool signaled = false;
|
||||
|
||||
fence_drv = userq->fence_drv;
|
||||
if (!fence_drv)
|
||||
@@ -274,13 +289,17 @@ static int amdgpu_userq_fence_create(struct amdgpu_usermode_queue *userq,
|
||||
|
||||
/* Check if hardware has already processed the job */
|
||||
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
|
||||
if (!dma_fence_is_signaled(fence))
|
||||
if (!dma_fence_is_signaled(fence)) {
|
||||
list_add_tail(&userq_fence->link, &fence_drv->fences);
|
||||
else
|
||||
} else {
|
||||
signaled = true;
|
||||
dma_fence_put(fence);
|
||||
|
||||
}
|
||||
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
|
||||
|
||||
if (signaled)
|
||||
amdgpu_userq_fence_put_fence_drv_array(userq_fence);
|
||||
|
||||
*f = fence;
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user