From e45d7b7f47a4849a5d3d55a2cf5802a72924d37b Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 27 Oct 2016 11:10:31 +0800 Subject: [PATCH] drm/i915/gvt: fix nested sleeping issue We cannot use blocking method mutex_lock inside a wait loop. Here we invoke pick_next_workload() which needs acquire a mutex in our "condition" experssion. Then we go into a another of the going-to-sleep sequence and changing the task state. This is a dangerous. Let's rewrite the wait sequence to avoid nested sleeping. v2: fix do...while loop exit condition (zhenyu) v3: rebase to gvt-staging branch Signed-off-by: Du, Changbin Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/scheduler.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index e96eaeebeb0a..f7e320b9b17a 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -402,19 +402,24 @@ static int workload_thread(void *priv) struct intel_vgpu_workload *workload = NULL; int ret; bool need_force_wake = IS_SKYLAKE(gvt->dev_priv); + DEFINE_WAIT_FUNC(wait, woken_wake_function); kfree(p); gvt_dbg_core("workload thread for ring %d started\n", ring_id); while (!kthread_should_stop()) { - ret = wait_event_interruptible(scheduler->waitq[ring_id], - kthread_should_stop() || - (workload = pick_next_workload(gvt, ring_id))); + add_wait_queue(&scheduler->waitq[ring_id], &wait); + do { + workload = pick_next_workload(gvt, ring_id); + if (workload) + break; + wait_woken(&wait, TASK_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT); + } while (!kthread_should_stop()); + remove_wait_queue(&scheduler->waitq[ring_id], &wait); - WARN_ON_ONCE(ret); - - if (kthread_should_stop()) + if (!workload) break; mutex_lock(&scheduler_mutex);