Skip to content

Commit d985349

Browse files
committed
drm/etnaviv: take GPU lock later in the submit process
Both the fence and event alloc are safe to be done without holding the GPU lock, as they either don't need any locking (fences) or are protected by their own lock (events). This solves a bad locking interaction between the submit path and the recover worker. If userspace manages to exhaust all available events while the GPU is hung, the submit will wait for events to become available holding the GPU lock. The recover worker waits for this lock to become available before trying to recover the GPU which frees up the allocated events. Essentially both paths are deadlocked until the submit path times out waiting for available events, failing the submit that could otherwise be handled just fine if the recover worker had the chance to bring the GPU back in a working state. Signed-off-by: Lucas Stach <l.stach@pengutronix.de> Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
1 parent 29b4817 commit d985349

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

drivers/gpu/drm/etnaviv/etnaviv_gpu.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,8 +1333,6 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
13331333
if (ret < 0)
13341334
return ret;
13351335

1336-
mutex_lock(&gpu->lock);
1337-
13381336
/*
13391337
* TODO
13401338
*
@@ -1348,16 +1346,18 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
13481346
if (unlikely(event == ~0U)) {
13491347
DRM_ERROR("no free event\n");
13501348
ret = -EBUSY;
1351-
goto out_unlock;
1349+
goto out_pm_put;
13521350
}
13531351

13541352
fence = etnaviv_gpu_fence_alloc(gpu);
13551353
if (!fence) {
13561354
event_free(gpu, event);
13571355
ret = -ENOMEM;
1358-
goto out_unlock;
1356+
goto out_pm_put;
13591357
}
13601358

1359+
mutex_lock(&gpu->lock);
1360+
13611361
gpu->event[event].fence = fence;
13621362
submit->fence = fence->seqno;
13631363
gpu->active_fence = submit->fence;
@@ -1395,9 +1395,9 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
13951395
hangcheck_timer_reset(gpu);
13961396
ret = 0;
13971397

1398-
out_unlock:
13991398
mutex_unlock(&gpu->lock);
14001399

1400+
out_pm_put:
14011401
etnaviv_gpu_pm_put(gpu);
14021402

14031403
return ret;

0 commit comments

Comments
 (0)