After schedule() returns 0, we must do one last check of COND to
determine the reason for the wakeup with 0 jiffies remaining before
reporting the timeout -- otherwise we may lose the signal due to
scheduler delays.

References: https://bugs.freedesktop.org/show_bug.cgi?id=106690
Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursu...@intel.com>
---
 drivers/gpu/drm/drm_syncobj.c | 41 +++++++++++++----------------------
 1 file changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index e254f97fed7d..5bcb3ef9b256 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -672,7 +672,6 @@ static signed long drm_syncobj_array_wait_timeout(struct 
drm_syncobj **syncobjs,
 {
        struct syncobj_wait_entry *entries;
        struct dma_fence *fence;
-       signed long ret;
        uint32_t signaled_count, i;
 
        entries = kcalloc(count, sizeof(*entries), GFP_KERNEL);
@@ -692,7 +691,7 @@ static signed long drm_syncobj_array_wait_timeout(struct 
drm_syncobj **syncobjs,
                        if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
                                continue;
                        } else {
-                               ret = -EINVAL;
+                               timeout = -EINVAL;
                                goto cleanup_entries;
                        }
                }
@@ -704,12 +703,6 @@ static signed long drm_syncobj_array_wait_timeout(struct 
drm_syncobj **syncobjs,
                }
        }
 
-       /* Initialize ret to the max of timeout and 1.  That way, the
-        * default return value indicates a successful wait and not a
-        * timeout.
-        */
-       ret = max_t(signed long, timeout, 1);
-
        if (signaled_count == count ||
            (signaled_count > 0 &&
             !(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL)))
@@ -760,18 +753,17 @@ static signed long drm_syncobj_array_wait_timeout(struct 
drm_syncobj **syncobjs,
                        goto done_waiting;
 
                if (timeout == 0) {
-                       /* If we are doing a 0 timeout wait and we got
-                        * here, then we just timed out.
-                        */
-                       ret = 0;
+                       timeout = -ETIME;
                        goto done_waiting;
                }
 
-               ret = schedule_timeout(ret);
+               if (signal_pending(current)) {
+                       timeout = -ERESTARTSYS;
+                       goto done_waiting;
+               }
 
-               if (ret > 0 && signal_pending(current))
-                       ret = -ERESTARTSYS;
-       } while (ret > 0);
+               timeout = schedule_timeout(timeout);
+       } while (1);
 
 done_waiting:
        __set_current_state(TASK_RUNNING);
@@ -788,7 +780,7 @@ static signed long drm_syncobj_array_wait_timeout(struct 
drm_syncobj **syncobjs,
        }
        kfree(entries);
 
-       return ret;
+       return timeout;
 }
 
 /**
@@ -829,19 +821,16 @@ static int drm_syncobj_array_wait(struct drm_device *dev,
                                  struct drm_syncobj **syncobjs)
 {
        signed long timeout = drm_timeout_abs_to_jiffies(wait->timeout_nsec);
-       signed long ret = 0;
        uint32_t first = ~0;
 
-       ret = drm_syncobj_array_wait_timeout(syncobjs,
-                                            wait->count_handles,
-                                            wait->flags,
-                                            timeout, &first);
-       if (ret < 0)
-               return ret;
+       timeout = drm_syncobj_array_wait_timeout(syncobjs,
+                                                wait->count_handles,
+                                                wait->flags,
+                                                timeout, &first);
+       if (timeout < 0)
+               return timeout;
 
        wait->first_signaled = first;
-       if (ret == 0)
-               return -ETIME;
        return 0;
 }
 
-- 
2.19.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to