From: Dmitry Osipenko dmitry.osipenko@collabora.com
mainline inclusion from mainline-v6.2-rc3 commit 69555549cfa42e10f2fdd2699ed4e34d9d4f392b category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB3ULB
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
The drm_sched_entity_kill() is invoked twice by drm_sched_entity_destroy() while userspace process is exiting or being killed. First time it's invoked when sched entity is flushed and second time when entity is released. This causes a lockup within wait_for_completion(entity_idle) due to how completion API works.
Calling wait_for_completion() more times than complete() was invoked is a error condition that causes lockup because completion internally uses counter for complete/wait calls. The complete_all() must be used instead in such cases.
This patch fixes lockup of Panfrost driver that is reproducible by killing any application in a middle of 3d drawing operation.
Fixes: 2fdb8a8f07c2 ("drm/scheduler: rework entity flush, kill and fini") Signed-off-by: Dmitry Osipenko dmitry.osipenko@collabora.com Reviewed-by: Christian König christian.koenig@amd.com Link: https://patchwork.freedesktop.org/patch/msgid/20221123001303.533968-1-dmitry... Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/gpu/drm/scheduler/sched_entity.c | 2 +- drivers/gpu/drm/scheduler/sched_main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 6cedce084762..be0d5bfb5df1 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -74,7 +74,7 @@ int drm_sched_entity_init(struct drm_sched_entity *entity, init_completion(&entity->entity_idle);
/* We start in an idle state. */ - complete(&entity->entity_idle); + complete_all(&entity->entity_idle);
spin_lock_init(&entity->rq_lock); spsc_queue_init(&entity->job_queue); diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index c93f75325b6c..936e87ad3feb 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -896,7 +896,7 @@ static int drm_sched_main(void *param) sched_job = drm_sched_entity_pop_job(entity);
if (!sched_job) { - complete(&entity->entity_idle); + complete_all(&entity->entity_idle); continue; }
@@ -907,7 +907,7 @@ static int drm_sched_main(void *param)
trace_drm_run_job(sched_job, entity); fence = sched->ops->run_job(sched_job); - complete(&entity->entity_idle); + complete_all(&entity->entity_idle); drm_sched_fence_scheduled(s_fence);
if (!IS_ERR_OR_NULL(fence)) {