Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915/display: Apply interactive priority to explicit flip fences

Currently, if a modeset/pageflip needs to wait for render completion to
an object, we boost the priority of that rendering above all other work.
We can apply the same interactive priority boosting to explicit fences
that we can unwrap into a native i915_request (i.e. sync_file).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210119204454.10343-1-chris@chris-wilson.co.uk

+42 -23
+6 -10
drivers/gpu/drm/i915/display/intel_display.c
··· 15631 15631 intel_unpin_fb_vma(vma, old_plane_state->flags); 15632 15632 } 15633 15633 15634 - static void fb_obj_bump_render_priority(struct drm_i915_gem_object *obj) 15635 - { 15636 - struct i915_sched_attr attr = { 15637 - .priority = I915_USER_PRIORITY(I915_PRIORITY_DISPLAY), 15638 - }; 15639 - 15640 - i915_gem_object_wait_priority(obj, 0, &attr); 15641 - } 15642 - 15643 15634 /** 15644 15635 * intel_prepare_plane_fb - Prepare fb for usage on plane 15645 15636 * @_plane: drm plane to prepare for ··· 15647 15656 intel_prepare_plane_fb(struct drm_plane *_plane, 15648 15657 struct drm_plane_state *_new_plane_state) 15649 15658 { 15659 + struct i915_sched_attr attr = { 15660 + .priority = I915_USER_PRIORITY(I915_PRIORITY_DISPLAY), 15661 + }; 15650 15662 struct intel_plane *plane = to_intel_plane(_plane); 15651 15663 struct intel_plane_state *new_plane_state = 15652 15664 to_intel_plane_state(_new_plane_state); ··· 15689 15695 } 15690 15696 15691 15697 if (new_plane_state->uapi.fence) { /* explicit fencing */ 15698 + i915_gem_fence_wait_priority(new_plane_state->uapi.fence, 15699 + &attr); 15692 15700 ret = i915_sw_fence_await_dma_fence(&state->commit_ready, 15693 15701 new_plane_state->uapi.fence, 15694 15702 i915_fence_timeout(dev_priv), ··· 15712 15716 if (ret) 15713 15717 return ret; 15714 15718 15715 - fb_obj_bump_render_priority(obj); 15719 + i915_gem_object_wait_priority(obj, 0, &attr); 15716 15720 i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB); 15717 15721 15718 15722 if (!new_plane_state->uapi.fence) { /* implicit fencing */
+3
drivers/gpu/drm/i915/gem/i915_gem_object.h
··· 500 500 obj->cache_dirty = true; 501 501 } 502 502 503 + void i915_gem_fence_wait_priority(struct dma_fence *fence, 504 + const struct i915_sched_attr *attr); 505 + 503 506 int i915_gem_object_wait(struct drm_i915_gem_object *obj, 504 507 unsigned int flags, 505 508 long timeout);
+33 -13
drivers/gpu/drm/i915/gem/i915_gem_wait.c
··· 5 5 */ 6 6 7 7 #include <linux/dma-fence-array.h> 8 + #include <linux/dma-fence-chain.h> 8 9 #include <linux/jiffies.h> 9 10 10 11 #include "gt/intel_engine.h" ··· 45 44 unsigned int count, i; 46 45 int ret; 47 46 48 - ret = dma_resv_get_fences_rcu(resv, 49 - &excl, &count, &shared); 47 + ret = dma_resv_get_fences_rcu(resv, &excl, &count, &shared); 50 48 if (ret) 51 49 return ret; 52 50 ··· 91 91 return timeout; 92 92 } 93 93 94 - static void __fence_set_priority(struct dma_fence *fence, 95 - const struct i915_sched_attr *attr) 94 + static void fence_set_priority(struct dma_fence *fence, 95 + const struct i915_sched_attr *attr) 96 96 { 97 97 struct i915_request *rq; 98 98 struct intel_engine_cs *engine; ··· 103 103 rq = to_request(fence); 104 104 engine = rq->engine; 105 105 106 - local_bh_disable(); 107 106 rcu_read_lock(); /* RCU serialisation for set-wedged protection */ 108 107 if (engine->schedule) 109 108 engine->schedule(rq, attr); 110 109 rcu_read_unlock(); 111 - local_bh_enable(); /* kick the tasklets if queues were reprioritised */ 112 110 } 113 111 114 - static void fence_set_priority(struct dma_fence *fence, 115 - const struct i915_sched_attr *attr) 112 + static inline bool __dma_fence_is_chain(const struct dma_fence *fence) 116 113 { 114 + return fence->ops == &dma_fence_chain_ops; 115 + } 116 + 117 + void i915_gem_fence_wait_priority(struct dma_fence *fence, 118 + const struct i915_sched_attr *attr) 119 + { 120 + if (dma_fence_is_signaled(fence)) 121 + return; 122 + 123 + local_bh_disable(); 124 + 117 125 /* Recurse once into a fence-array */ 118 126 if (dma_fence_is_array(fence)) { 119 127 struct dma_fence_array *array = to_dma_fence_array(fence); 120 128 int i; 121 129 122 130 for (i = 0; i < array->num_fences; i++) 123 - __fence_set_priority(array->fences[i], attr); 131 + fence_set_priority(array->fences[i], attr); 132 + } else if (__dma_fence_is_chain(fence)) { 133 + struct dma_fence *iter; 134 + 135 + /* The chain is ordered; if we boost the last, we boost all */ 136 + dma_fence_chain_for_each(iter, fence) { 137 + fence_set_priority(to_dma_fence_chain(iter)->fence, 138 + attr); 139 + break; 140 + } 141 + dma_fence_put(iter); 124 142 } else { 125 - __fence_set_priority(fence, attr); 143 + fence_set_priority(fence, attr); 126 144 } 145 + 146 + local_bh_enable(); /* kick the tasklets if queues were reprioritised */ 127 147 } 128 148 129 149 int ··· 159 139 int ret; 160 140 161 141 ret = dma_resv_get_fences_rcu(obj->base.resv, 162 - &excl, &count, &shared); 142 + &excl, &count, &shared); 163 143 if (ret) 164 144 return ret; 165 145 166 146 for (i = 0; i < count; i++) { 167 - fence_set_priority(shared[i], attr); 147 + i915_gem_fence_wait_priority(shared[i], attr); 168 148 dma_fence_put(shared[i]); 169 149 } 170 150 ··· 174 154 } 175 155 176 156 if (excl) { 177 - fence_set_priority(excl, attr); 157 + i915_gem_fence_wait_priority(excl, attr); 178 158 dma_fence_put(excl); 179 159 } 180 160 return 0;