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:
parent
6fb5082a8c
commit
e45d7b7f47
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue