[Intel-gfx] [PATCH v3 62/63] drm/i915: Idea to implement eviction locking
Maarten Lankhorst
maarten.lankhorst at linux.intel.com
Thu Oct 15 11:26:26 UTC 2020
Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
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
More information about the Intel-gfx
mailing list