* synchronize between the two.
  * This requirement is inherited from the Vulkan fence API.
  *
+ * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE is set, the ioctl will also set
+ * a fence deadline hint on the backing fences before waiting, to provide the
+ * fence signaler with an appropriate sense of urgency.  The deadline is
+ * specified as an absolute &CLOCK_MONOTONIC value in units of ns.
+ *
  * Similarly, &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT takes an array of syncobj
  * handles as well as an array of u64 points and does a host-side wait on all
  * of syncobj fences at the given points simultaneously.
                                                  uint32_t count,
                                                  uint32_t flags,
                                                  signed long timeout,
-                                                 uint32_t *idx)
+                                                 uint32_t *idx,
+                                                 ktime_t *deadline)
 {
        struct syncobj_wait_entry *entries;
        struct dma_fence *fence;
                        drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]);
        }
 
+       if (deadline) {
+               for (i = 0; i < count; ++i) {
+                       fence = entries[i].fence;
+                       if (!fence)
+                               continue;
+                       dma_fence_set_deadline(fence, *deadline);
+               }
+       }
+
        do {
                set_current_state(TASK_INTERRUPTIBLE);
 
                                  struct drm_file *file_private,
                                  struct drm_syncobj_wait *wait,
                                  struct drm_syncobj_timeline_wait *timeline_wait,
-                                 struct drm_syncobj **syncobjs, bool timeline)
+                                 struct drm_syncobj **syncobjs, bool timeline,
+                                 ktime_t *deadline)
 {
        signed long timeout = 0;
        uint32_t first = ~0;
                                                         NULL,
                                                         wait->count_handles,
                                                         wait->flags,
-                                                        timeout, &first);
+                                                        timeout, &first,
+                                                        deadline);
                if (timeout < 0)
                        return timeout;
                wait->first_signaled = first;
                                                         u64_to_user_ptr(timeline_wait->points),
                                                         timeline_wait->count_handles,
                                                         timeline_wait->flags,
-                                                        timeout, &first);
+                                                        timeout, &first,
+                                                        deadline);
                if (timeout < 0)
                        return timeout;
                timeline_wait->first_signaled = first;
 {
        struct drm_syncobj_wait *args = data;
        struct drm_syncobj **syncobjs;
+       unsigned int possible_flags;
+       ktime_t t, *tp = NULL;
        int ret = 0;
 
        if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ))
                return -EOPNOTSUPP;
 
-       if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
-                           DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT))
+       possible_flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
+                        DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+                        DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE;
+
+       if (args->flags & ~possible_flags)
                return -EINVAL;
 
        if (args->count_handles == 0)
-               return -EINVAL;
+               return 0;
 
        ret = drm_syncobj_array_find(file_private,
                                     u64_to_user_ptr(args->handles),
        if (ret < 0)
                return ret;
 
+       if (args->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE) {
+               t = ns_to_ktime(args->deadline_nsec);
+               tp = &t;
+       }
+
        ret = drm_syncobj_array_wait(dev, file_private,
-                                    args, NULL, syncobjs, false);
+                                    args, NULL, syncobjs, false, tp);
 
        drm_syncobj_array_free(syncobjs, args->count_handles);
 
 {
        struct drm_syncobj_timeline_wait *args = data;
        struct drm_syncobj **syncobjs;
+       unsigned int possible_flags;
+       ktime_t t, *tp = NULL;
        int ret = 0;
 
        if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE))
                return -EOPNOTSUPP;
 
-       if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
-                           DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
-                           DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE))
+       possible_flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |
+                        DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+                        DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE |
+                        DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE;
+
+       if (args->flags & ~possible_flags)
                return -EINVAL;
 
        if (args->count_handles == 0)
-               return -EINVAL;
+               return 0;
 
        ret = drm_syncobj_array_find(file_private,
                                     u64_to_user_ptr(args->handles),
        if (ret < 0)
                return ret;
 
+       if (args->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE) {
+               t = ns_to_ktime(args->deadline_nsec);
+               tp = &t;
+       }
+
        ret = drm_syncobj_array_wait(dev, file_private,
-                                    NULL, args, syncobjs, true);
+                                    NULL, args, syncobjs, true, tp);
 
        drm_syncobj_array_free(syncobjs, args->count_handles);
 
 
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE (1 << 3) /* set fence deadline to deadline_nsec */
 struct drm_syncobj_wait {
        __u64 handles;
        /* absolute timeout */
        __u32 flags;
        __u32 first_signaled; /* only valid when not waiting all */
        __u32 pad;
+       /**
+        * @deadline_nsec - fence deadline hint
+        *
+        * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing
+        * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is
+        * set.
+        */
+       __u64 deadline_nsec;
 };
 
 struct drm_syncobj_timeline_wait {
        __u32 flags;
        __u32 first_signaled; /* only valid when not waiting all */
        __u32 pad;
+       /**
+        * @deadline_nsec - fence deadline hint
+        *
+        * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing
+        * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is
+        * set.
+        */
+       __u64 deadline_nsec;
 };
 
 /**