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 <changbin.du@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
This commit is contained in:
Du, Changbin 2016-10-27 11:10:31 +08:00 committed by Zhenyu Wang
parent 6fb5082a8c
commit e45d7b7f47
1 changed files with 11 additions and 6 deletions

View File

@ -402,19 +402,24 @@ static int workload_thread(void *priv)
struct intel_vgpu_workload *workload = NULL; struct intel_vgpu_workload *workload = NULL;
int ret; int ret;
bool need_force_wake = IS_SKYLAKE(gvt->dev_priv); bool need_force_wake = IS_SKYLAKE(gvt->dev_priv);
DEFINE_WAIT_FUNC(wait, woken_wake_function);
kfree(p); kfree(p);
gvt_dbg_core("workload thread for ring %d started\n", ring_id); gvt_dbg_core("workload thread for ring %d started\n", ring_id);
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
ret = wait_event_interruptible(scheduler->waitq[ring_id], add_wait_queue(&scheduler->waitq[ring_id], &wait);
kthread_should_stop() || do {
(workload = pick_next_workload(gvt, ring_id))); 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 (!workload)
if (kthread_should_stop())
break; break;
mutex_lock(&scheduler_mutex); mutex_lock(&scheduler_mutex);