drm/i915/scheduler: Boost priorities for flips
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 14 Nov 2016 20:41:05 +0000 (20:41 +0000)
committerChris Wilson <chris@chris-wilson.co.uk>
Mon, 14 Nov 2016 21:01:22 +0000 (21:01 +0000)
Boost the priority of any rendering required to show the next pageflip
as we want to avoid missing the vblank by being delayed by invisible
workload. We prioritise avoiding jank and jitter in the GUI over
starving background tasks.

v2: Descend dma_fence_array when boosting priorities.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20161114204105.29171-10-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_display.c

index 0e7e33b73d096af4dec29c693168493c2b415b50..6bc13bde337e0e82de1274c5e575454b333cae26 100644 (file)
@@ -3091,6 +3091,11 @@ int i915_gem_object_wait(struct drm_i915_gem_object *obj,
                         unsigned int flags,
                         long timeout,
                         struct intel_rps_client *rps);
+int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
+                                 unsigned int flags,
+                                 int priority);
+#define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX
+
 int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
                                  bool write);
index 7a43f2a73552e8845480e705da1f9d98d81d1c49..3fb5e66e4d65d5c2ffce77b23f00e7a642b27c18 100644 (file)
@@ -34,6 +34,7 @@
 #include "intel_drv.h"
 #include "intel_frontbuffer.h"
 #include "intel_mocs.h"
+#include <linux/dma-fence-array.h>
 #include <linux/reservation.h>
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
@@ -434,6 +435,70 @@ i915_gem_object_wait_reservation(struct reservation_object *resv,
        return timeout;
 }
 
+static void __fence_set_priority(struct dma_fence *fence, int prio)
+{
+       struct drm_i915_gem_request *rq;
+       struct intel_engine_cs *engine;
+
+       if (!dma_fence_is_i915(fence))
+               return;
+
+       rq = to_request(fence);
+       engine = rq->engine;
+       if (!engine->schedule)
+               return;
+
+       engine->schedule(rq, prio);
+}
+
+static void fence_set_priority(struct dma_fence *fence, int prio)
+{
+       /* Recurse once into a fence-array */
+       if (dma_fence_is_array(fence)) {
+               struct dma_fence_array *array = to_dma_fence_array(fence);
+               int i;
+
+               for (i = 0; i < array->num_fences; i++)
+                       __fence_set_priority(array->fences[i], prio);
+       } else {
+               __fence_set_priority(fence, prio);
+       }
+}
+
+int
+i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
+                             unsigned int flags,
+                             int prio)
+{
+       struct dma_fence *excl;
+
+       if (flags & I915_WAIT_ALL) {
+               struct dma_fence **shared;
+               unsigned int count, i;
+               int ret;
+
+               ret = reservation_object_get_fences_rcu(obj->resv,
+                                                       &excl, &count, &shared);
+               if (ret)
+                       return ret;
+
+               for (i = 0; i < count; i++) {
+                       fence_set_priority(shared[i], prio);
+                       dma_fence_put(shared[i]);
+               }
+
+               kfree(shared);
+       } else {
+               excl = reservation_object_get_excl_rcu(obj->resv);
+       }
+
+       if (excl) {
+               fence_set_priority(excl, prio);
+               dma_fence_put(excl);
+       }
+       return 0;
+}
+
 /**
  * Waits for rendering to the object to be completed
  * @obj: i915 gem object
index 5603c1fccd38b347562947d8797842e69d8963cc..4b6986cb6ff5f79cd3721077bbcc86e42db72a97 100644 (file)
@@ -14799,6 +14799,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                                                      GFP_KERNEL);
                if (ret < 0)
                        return ret;
+
+               i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
        }
 
        if (plane->type == DRM_PLANE_TYPE_CURSOR &&