diff options
-rw-r--r-- | drivers/gpu/drm/i915/gem/i915_gem_object.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/gem/i915_gem_object.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_ww.c | 19 |
4 files changed, 64 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index fd34b1a115c4..101d4f60157b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -89,6 +89,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, mutex_init(&obj->mm.get_page.lock); INIT_RADIX_TREE(&obj->mm.get_dma_page.radix, GFP_KERNEL | __GFP_NOWARN); mutex_init(&obj->mm.get_dma_page.lock); + kref_init(&i915_gem_to_ttm(obj)->kref); } /** @@ -319,6 +320,29 @@ void __i915_gem_free_object(struct drm_i915_gem_object *obj) __i915_gem_object_fini(obj); } +static void __i915_gem_free_object_free_destroy(struct kref *kref) +{ + struct drm_i915_gem_object *obj = container_of(kref, struct drm_i915_gem_object, __do_not_access.kref); + + __i915_gem_free_object(obj); + + /* But keep the pointer alive for RCU-protected lookups */ + call_rcu(&obj->rcu, __i915_gem_free_object_rcu); +} + +void i915_gem_object_free_get(struct drm_i915_gem_object *obj) +{ + kref_get(&i915_gem_to_ttm(obj)->kref); +} + +void i915_gem_object_free_put(struct drm_i915_gem_object *obj) +{ + if (obj->ops->delayed_free) + ttm_bo_put(i915_gem_to_ttm(obj)); + else + kref_put(&i915_gem_to_ttm(obj)->kref, __i915_gem_free_object_free_destroy); +} + static void __i915_gem_free_objects(struct drm_i915_private *i915, struct llist_node *freed) { @@ -340,10 +364,8 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, __i915_gem_object_pages_fini(obj); i915_gem_object_unlock(obj); - __i915_gem_free_object(obj); - /* But keep the pointer alive for RCU-protected lookups */ - call_rcu(&obj->rcu, __i915_gem_free_object_rcu); + i915_gem_object_free_put(obj); cond_resched(); } } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 08db9af75a62..1b7ee6cd65bf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -123,6 +123,9 @@ i915_gem_object_get_rcu(struct drm_i915_gem_object *obj) return obj; } +void i915_gem_object_free_get(struct drm_i915_gem_object *obj); +void i915_gem_object_free_put(struct drm_i915_gem_object *obj); + static inline struct drm_i915_gem_object * i915_gem_object_lookup(struct drm_file *file, u32 handle) { diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index ec1423e60516..d66f60493522 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -422,18 +422,32 @@ retry: if (dma_resv_locking_ctx(vma->obj->base.resv) != &ww->ctx && !i915_gem_object_trylock_to_evict(vma->obj, ww)) { struct drm_i915_gem_object *obj; + bool dead = false; if (i915_vma_is_pinned(vma)) continue; obj = i915_gem_object_get_rcu(vma->obj); - if (!obj) - /* Object's dead, can't drop vm->mutex safely */ - continue; + if (!obj) { + obj = vma->obj; + i915_gem_object_free_get(obj); + dead = true; + } mutex_unlock(&vm->mutex); ret = i915_gem_object_lock_to_evict(obj, ww); - i915_gem_object_put(obj); + + + if (dead) { + if (!ret) { + __i915_gem_object_pages_fini(obj); + list_del(&obj->obj_link); + i915_gem_object_unlock(obj); + } + i915_gem_object_free_put(obj); + } else { + i915_gem_object_put(obj); + } if (ret) { i915_gem_ww_ctx_unlock_evictions(ww); diff --git a/drivers/gpu/drm/i915/i915_gem_ww.c b/drivers/gpu/drm/i915/i915_gem_ww.c index 5e7c14cb43d0..b4eef420807d 100644 --- a/drivers/gpu/drm/i915/i915_gem_ww.c +++ b/drivers/gpu/drm/i915/i915_gem_ww.c @@ -5,6 +5,7 @@ #include <linux/dma-resv.h> #include "i915_gem_ww.h" #include "gem/i915_gem_object.h" +#include "gem/i915_gem_ttm.h" void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr) { @@ -72,6 +73,19 @@ int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww) else dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx); + if (ww->contended_evict && !kref_read(&i915_gem_to_ttm(ww->contended)->kref)) { + /* dead object, reap it */ + if (!ret) { + __i915_gem_object_pages_fini(ww->contended); + i915_gem_object_unlock(ww->contended); + } + + i915_gem_object_free_put(ww->contended); + ww->contended_evict = false; + ww->contended = NULL; + return ret; + } + if (!ret) { list_add_tail(&ww->contended->obj_link, !ww->contended_evict ? &ww->obj_list : &ww->eviction_list); @@ -112,7 +126,10 @@ static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj, ret = 0; if (ret == -EDEADLK) { - i915_gem_object_get(obj); + if (!evict) + i915_gem_object_get(obj); + else if (!i915_gem_object_get_rcu(obj)) + i915_gem_object_free_get(obj); ww->contended = obj; ww->contended_evict = evict; } |