[PATCH] drm/etnaviv: take GPU lock later in the submit process
Christian Gmeiner
christian.gmeiner at gmail.com
Mon Aug 15 10:46:55 UTC 2016
2016-08-08 13:00 GMT+02:00 Lucas Stach <l.stach at pengutronix.de>:
> 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 at pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner at gmail.com>
> ---
> drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 10 +++++-----
> 1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> index 87ef34150d46..b382cf505262 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
> @@ -1333,8 +1333,6 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
> if (ret < 0)
> return ret;
>
> - mutex_lock(&gpu->lock);
> -
> /*
> * TODO
> *
> @@ -1348,16 +1346,18 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
> if (unlikely(event == ~0U)) {
> DRM_ERROR("no free event\n");
> ret = -EBUSY;
> - goto out_unlock;
> + goto out_pm_put;
> }
>
> fence = etnaviv_gpu_fence_alloc(gpu);
> if (!fence) {
> event_free(gpu, event);
> ret = -ENOMEM;
> - goto out_unlock;
> + goto out_pm_put;
> }
>
> + mutex_lock(&gpu->lock);
> +
> gpu->event[event].fence = fence;
> submit->fence = fence->seqno;
> gpu->active_fence = submit->fence;
> @@ -1395,9 +1395,9 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
> hangcheck_timer_reset(gpu);
> ret = 0;
>
> -out_unlock:
> mutex_unlock(&gpu->lock);
>
> +out_pm_put:
> etnaviv_gpu_pm_put(gpu);
>
> return ret;
> --
> 2.8.1
>
More information about the dri-devel
mailing list