Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/gem/i915_gem_object.h | 39 +++++++++++++++++++- drivers/gpu/drm/i915/gem/i915_gem_shrinker.c | 10 ++++- drivers/gpu/drm/i915/i915_gem.c | 29 ++++++++++++++- drivers/gpu/drm/i915/i915_gem.h | 5 ++- 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index f6ccd05010df..3cafe8985034 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -126,12 +126,43 @@ static inline void assert_object_held_shared(struct drm_i915_gem_object *obj) assert_object_held(obj); } +static inline int +i915_gem_object_lock_to_evict(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww) +{ + int ret; + + if (ww->intr) + ret = dma_resv_lock_interruptible(obj->base.resv, &ww->ctx); + else + ret = dma_resv_lock(obj->base.resv, &ww->ctx); + + if (!ret) { + list_add_tail(&obj->obj_link, &ww->eviction_list); + i915_gem_object_get(obj); + } + + if (ret == -EALREADY && + obj == list_first_entry(&ww->eviction_list, struct drm_i915_gem_object, obj_link)) + ret = 0; + + ww->evicting = true; + + if (ret == -EDEADLK) + ww->contended = i915_gem_object_get(obj); + + return ret; +} + static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, bool intr) { int ret; + if (ww && GEM_WARN_ON(ww->evicting)) + ww->evicting = false; + if (intr) ret = dma_resv_lock_interruptible(obj->base.resv, ww ? &ww->ctx : NULL); else @@ -139,8 +170,14 @@ static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj, if (!ret && ww) list_add_tail(&obj->obj_link, &ww->obj_list); - if (ret == -EALREADY) + if (ret == -EALREADY) { ret = 0; + if (obj == list_first_entry(&ww->eviction_list, struct drm_i915_gem_object, obj_link)) { + i915_gem_object_put(obj); + list_del(&obj->obj_link); + list_add_tail(&obj->obj_link, &ww->obj_list); + } + } if (ret == -EDEADLK) ww->contended = obj; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c index e42192834c88..075cdd7718c4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c @@ -99,6 +99,7 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, unsigned long *nr_scanned, unsigned int shrink) { + struct drm_i915_gem_object *obj; const struct { struct list_head *list; unsigned int bit; @@ -163,7 +164,6 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, */ for (phase = phases; phase->list; phase++) { struct list_head still_in_list; - struct drm_i915_gem_object *obj; unsigned long flags; if ((shrink & phase->bit) == 0) @@ -208,7 +208,11 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, if (!i915_gem_object_trylock(obj)) goto skip; } else { - err = i915_gem_object_lock(obj, ww); + err = i915_gem_object_lock_to_evict(obj, ww); + if (err == -EALREADY) { + err = 0; + goto skip; + } if (err) goto skip; } @@ -234,6 +238,8 @@ i915_gem_shrink(struct i915_gem_ww_ctx *ww, if (err) return err; } + if (ww) + i915_gem_ww_ctx_unlock_evictions(ww); if (shrink & I915_SHRINK_BOUND) intel_runtime_pm_put(&i915->runtime_pm, wakeref); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5a497576614c..4f6fcdae1457 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1370,10 +1370,25 @@ void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr) { ww_acquire_init(&ww->ctx, &reservation_ww_class); INIT_LIST_HEAD(&ww->obj_list); + INIT_LIST_HEAD(&ww->eviction_list); ww->intr = intr; + ww->evicting = false; ww->contended = NULL; } +void i915_gem_ww_ctx_unlock_evictions(struct i915_gem_ww_ctx *ww) +{ + struct drm_i915_gem_object *obj; + + while ((obj = list_first_entry_or_null(&ww->eviction_list, struct drm_i915_gem_object, obj_link))) { + list_del(&obj->obj_link); + i915_gem_object_unlock(obj); + i915_gem_object_put(obj); + } + + ww->evicting = false; +} + static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww) { struct drm_i915_gem_object *obj; @@ -1382,6 +1397,12 @@ static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww) list_del(&obj->obj_link); i915_gem_object_unlock(obj); } + + while ((obj = list_first_entry_or_null(&ww->eviction_list, struct drm_i915_gem_object, obj_link))) { + list_del(&obj->obj_link); + i915_gem_object_unlock(obj); + i915_gem_object_put(obj); + } } void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj) @@ -1411,9 +1432,15 @@ int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww) dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx); if (!ret) - list_add_tail(&ww->contended->obj_link, &ww->obj_list); + list_add_tail(&ww->contended->obj_link, + ww->evicting ? &ww->eviction_list : + &ww->obj_list); + else if (ret && ww->evicting) { + i915_gem_object_put(ww->contended); + } ww->contended = NULL; + ww->evicting = false; return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index a4cad3f154ca..52b19ebffab1 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -119,7 +119,8 @@ static inline bool __tasklet_is_scheduled(struct tasklet_struct *t) struct i915_gem_ww_ctx { struct ww_acquire_ctx ctx; struct list_head obj_list; - bool intr; + struct list_head eviction_list; + bool intr, evicting; struct drm_i915_gem_object *contended; }; @@ -128,4 +129,6 @@ void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx); int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx); void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj); +void i915_gem_ww_ctx_unlock_evictions(struct i915_gem_ww_ctx *ww); + #endif /* __I915_GEM_H__ */ -- 2.28.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx