diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 4df039ef2ce3..e161d383b526 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
| @@ -33,21 +33,20 @@ | |||
| 33 | #include "intel_drv.h" | 33 | #include "intel_drv.h" |
| 34 | #include "i915_trace.h" | 34 | #include "i915_trace.h" |
| 35 | 35 | ||
| 36 | static bool ggtt_is_idle(struct drm_i915_private *dev_priv) | 36 | static bool ggtt_is_idle(struct drm_i915_private *i915) |
| 37 | { | 37 | { |
| 38 | struct i915_ggtt *ggtt = &dev_priv->ggtt; | 38 | struct intel_engine_cs *engine; |
| 39 | struct intel_engine_cs *engine; | 39 | enum intel_engine_id id; |
| 40 | enum intel_engine_id id; | ||
| 41 | 40 | ||
| 42 | for_each_engine(engine, dev_priv, id) { | 41 | if (i915->gt.active_requests) |
| 43 | struct intel_timeline *tl; | 42 | return false; |
| 44 | 43 | ||
| 45 | tl = &ggtt->base.timeline.engine[engine->id]; | 44 | for_each_engine(engine, i915, id) { |
| 46 | if (i915_gem_active_isset(&tl->last_request)) | 45 | if (engine->last_retired_context != i915->kernel_context) |
| 47 | return false; | 46 | return false; |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | return true; | 49 | return true; |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | static int ggtt_flush(struct drm_i915_private *i915) | 52 | static int ggtt_flush(struct drm_i915_private *i915) |
| @@ -157,7 +156,8 @@ i915_gem_evict_something(struct i915_address_space *vm, | |||
| 157 | min_size, alignment, cache_level, | 156 | min_size, alignment, cache_level, |
| 158 | start, end, mode); | 157 | start, end, mode); |
| 159 | 158 | ||
| 160 | /* Retire before we search the active list. Although we have | 159 | /* |
| 160 | * Retire before we search the active list. Although we have | ||
| 161 | * reasonable accuracy in our retirement lists, we may have | 161 | * reasonable accuracy in our retirement lists, we may have |
| 162 | * a stray pin (preventing eviction) that can only be resolved by | 162 | * a stray pin (preventing eviction) that can only be resolved by |
| 163 | * retiring. | 163 | * retiring. |
| @@ -182,7 +182,8 @@ search_again: | |||
| 182 | BUG_ON(ret); | 182 | BUG_ON(ret); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | /* Can we unpin some objects such as idle hw contents, | 185 | /* |
| 186 | * Can we unpin some objects such as idle hw contents, | ||
| 186 | * or pending flips? But since only the GGTT has global entries | 187 | * or pending flips? But since only the GGTT has global entries |
| 187 | * such as scanouts, rinbuffers and contexts, we can skip the | 188 | * such as scanouts, rinbuffers and contexts, we can skip the |
| 188 | * purge when inspecting per-process local address spaces. | 189 | * purge when inspecting per-process local address spaces. |
| @@ -190,19 +191,33 @@ search_again: | |||
| 190 | if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK) | 191 | if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK) |
| 191 | return -ENOSPC; | 192 | return -ENOSPC; |
| 192 | 193 | ||
| 193 | if (ggtt_is_idle(dev_priv)) { | 194 | /* |
| 194 | /* If we still have pending pageflip completions, drop | 195 | * Not everything in the GGTT is tracked via VMA using |
| 195 | * back to userspace to give our workqueues time to | 196 | * i915_vma_move_to_active(), otherwise we could evict as required |
| 196 | * acquire our locks and unpin the old scanouts. | 197 | * with minimal stalling. Instead we are forced to idle the GPU and |
| 197 | */ | 198 | * explicitly retire outstanding requests which will then remove |
| 198 | return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC; | 199 | * the pinning for active objects such as contexts and ring, |
| 199 | } | 200 | * enabling us to evict them on the next iteration. |
| 201 | * | ||
| 202 | * To ensure that all user contexts are evictable, we perform | ||
| 203 | * a switch to the perma-pinned kernel context. This all also gives | ||
| 204 | * us a termination condition, when the last retired context is | ||
| 205 | * the kernel's there is no more we can evict. | ||
| 206 | */ | ||
| 207 | if (!ggtt_is_idle(dev_priv)) { | ||
| 208 | ret = ggtt_flush(dev_priv); | ||
| 209 | if (ret) | ||
| 210 | return ret; | ||
| 200 | 211 | ||
| 201 | ret = ggtt_flush(dev_priv); | 212 | goto search_again; |
| 202 | if (ret) | 213 | } |
| 203 | return ret; | ||
| 204 | 214 | ||
| 205 | goto search_again; | 215 | /* |
| 216 | * If we still have pending pageflip completions, drop | ||
| 217 | * back to userspace to give our workqueues time to | ||
| 218 | * acquire our locks and unpin the old scanouts. | ||
| 219 | */ | ||
| 220 | return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC; | ||
| 206 | 221 | ||
| 207 | found: | 222 | found: |
| 208 | /* drm_mm doesn't allow any other other operations while | 223 | /* drm_mm doesn't allow any other other operations while |
