--- a/sys/dev/drm/include/linux/wait.h +++ b/sys/dev/drm/include/linux/wait.h @@ -122,13 +122,13 @@ void finish_wait(wait_queue_head_t *q, wait_queue_entry_t *wait); prepare_to_wait(&wq, &tmp_wq, state); \ \ while (1) { \ __wait_event_prefix(&wq, flags); \ \ + tsleep_interlock(current, flags); \ if (condition) \ break; \ \ - tsleep_interlock(current, flags); \ - \ if ((timeout_jiffies) != 0) { \ ret = tsleep(current, PINTERLOCKED|flags, "lwe", timeout_jiffies); \ } else { \ --- a/sys/dev/drm/include/linux/sched.h +++ b/sys/dev/drm/include/linux/sched.h @@ -240,8 +240,11 @@ wake_up_process(struct task_struct *tsk) spin_lock(&tsk->kt_spin); ostate = tsk->state; tsk->state = TASK_RUNNING; spin_unlock(&tsk->kt_spin); - if (ostate != TASK_RUNNING) + if (ostate != TASK_RUNNING) { wakeup(tsk); + return 1; + } - return 1; /* Always indicate the process was woken up */ + return 0; /* was already running: nothing was woken */ } static inline int --- a/sys/dev/drm/linux_wait.c +++ b/sys/dev/drm/linux_wait.c @@ -37,11 +37,12 @@ int autoremove_wake_function(wait_queue_entry_t *wait, unsigned mode, int sync, void *key) { int ret = default_wake_function(wait, mode, sync, key); - /* Was the process woken up ? */ + /* Only unlink the entry if a wakeup was actually delivered; + * wake_up_process() returning 0 means the target was already + * RUNNING and no wakeup() was issued. */ if (ret) list_del_init(&wait->entry); return ret; }