diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_context.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 108 |
1 files changed, 30 insertions, 78 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 1a87d04e7937..58a2a44f88bd 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -93,69 +93,28 @@ #define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1 -/* Initial size (as log2) to preallocate the handle->object hashtable */ -#define VMA_HT_BITS 2u /* 4 x 2 pointers, 64 bytes minimum */ - -static void resize_vma_ht(struct work_struct *work) +static void lut_close(struct i915_gem_context *ctx) { - struct i915_gem_context_vma_lut *lut = - container_of(work, typeof(*lut), resize); - unsigned int bits, new_bits, size, i; - struct hlist_head *new_ht; - - GEM_BUG_ON(!(lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS)); - - bits = 1 + ilog2(4*lut->ht_count/3 + 1); - new_bits = min_t(unsigned int, - max(bits, VMA_HT_BITS), - sizeof(unsigned int) * BITS_PER_BYTE - 1); - if (new_bits == lut->ht_bits) - goto out; - - new_ht = kzalloc(sizeof(*new_ht)<<new_bits, GFP_KERNEL | __GFP_NOWARN); - if (!new_ht) - new_ht = vzalloc(sizeof(*new_ht)<<new_bits); - if (!new_ht) - /* Pretend resize succeeded and stop calling us for a bit! */ - goto out; + struct i915_lut_handle *lut, *ln; + struct radix_tree_iter iter; + void __rcu **slot; - size = BIT(lut->ht_bits); - for (i = 0; i < size; i++) { - struct i915_vma *vma; - struct hlist_node *tmp; - - hlist_for_each_entry_safe(vma, tmp, &lut->ht[i], ctx_node) - hlist_add_head(&vma->ctx_node, - &new_ht[hash_32(vma->ctx_handle, - new_bits)]); + list_for_each_entry_safe(lut, ln, &ctx->handles_list, ctx_link) { + list_del(&lut->obj_link); + kmem_cache_free(ctx->i915->luts, lut); } - kvfree(lut->ht); - lut->ht = new_ht; - lut->ht_bits = new_bits; -out: - smp_store_release(&lut->ht_size, BIT(bits)); - GEM_BUG_ON(lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS); -} -static void vma_lut_free(struct i915_gem_context *ctx) -{ - struct i915_gem_context_vma_lut *lut = &ctx->vma_lut; - unsigned int i, size; + radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) { + struct i915_vma *vma = rcu_dereference_raw(*slot); + struct drm_i915_gem_object *obj = vma->obj; - if (lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS) - cancel_work_sync(&lut->resize); + radix_tree_iter_delete(&ctx->handles_vma, &iter, slot); - size = BIT(lut->ht_bits); - for (i = 0; i < size; i++) { - struct i915_vma *vma; + if (!i915_vma_is_ggtt(vma)) + i915_vma_close(vma); - hlist_for_each_entry(vma, &lut->ht[i], ctx_node) { - vma->obj->vma_hashed = NULL; - vma->ctx = NULL; - i915_vma_put(vma); - } + __i915_gem_object_release_unless_active(obj); } - kvfree(lut->ht); } static void i915_gem_context_free(struct i915_gem_context *ctx) @@ -165,7 +124,6 @@ static void i915_gem_context_free(struct i915_gem_context *ctx) lockdep_assert_held(&ctx->i915->drm.struct_mutex); GEM_BUG_ON(!i915_gem_context_is_closed(ctx)); - vma_lut_free(ctx); i915_ppgtt_put(ctx->ppgtt); for (i = 0; i < I915_NUM_ENGINES; i++) { @@ -239,8 +197,11 @@ void i915_gem_context_release(struct kref *ref) static void context_close(struct i915_gem_context *ctx) { i915_gem_context_set_closed(ctx); + + lut_close(ctx); if (ctx->ppgtt) i915_ppgtt_close(&ctx->ppgtt->base); + ctx->file_priv = ERR_PTR(-EBADF); i915_gem_context_put(ctx); } @@ -313,16 +274,8 @@ __create_hw_context(struct drm_i915_private *dev_priv, ctx->i915 = dev_priv; ctx->priority = I915_PRIORITY_NORMAL; - ctx->vma_lut.ht_bits = VMA_HT_BITS; - ctx->vma_lut.ht_size = BIT(VMA_HT_BITS); - BUILD_BUG_ON(BIT(VMA_HT_BITS) == I915_CTX_RESIZE_IN_PROGRESS); - ctx->vma_lut.ht = kcalloc(ctx->vma_lut.ht_size, - sizeof(*ctx->vma_lut.ht), - GFP_KERNEL); - if (!ctx->vma_lut.ht) - goto err_out; - - INIT_WORK(&ctx->vma_lut.resize, resize_vma_ht); + INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); + INIT_LIST_HEAD(&ctx->handles_list); /* Default context will never have a file_priv */ ret = DEFAULT_CONTEXT_HANDLE; @@ -372,8 +325,6 @@ err_pid: put_pid(ctx->pid); idr_remove(&file_priv->context_idr, ctx->user_handle); err_lut: - kvfree(ctx->vma_lut.ht); -err_out: context_close(ctx); return ERR_PTR(ret); } @@ -741,19 +692,19 @@ static inline bool skip_rcs_switch(struct i915_hw_ppgtt *ppgtt, } static bool -needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt, - struct intel_engine_cs *engine, - struct i915_gem_context *to) +needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt, struct intel_engine_cs *engine) { + struct i915_gem_context *from = engine->legacy_active_context; + if (!ppgtt) return false; /* Always load the ppgtt on first use */ - if (!engine->legacy_active_context) + if (!from) return true; /* Same context without new entries, skip */ - if (engine->legacy_active_context == to && + if ((!from->ppgtt || from->ppgtt == ppgtt) && !(intel_engine_flag(engine) & ppgtt->pd_dirty_rings)) return false; @@ -797,7 +748,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req) if (skip_rcs_switch(ppgtt, engine, to)) return 0; - if (needs_pd_load_pre(ppgtt, engine, to)) { + if (needs_pd_load_pre(ppgtt, engine)) { /* Older GENs and non render rings still want the load first, * "PP_DCLV followed by PP_DIR_BASE register through Load * Register Immediate commands in Ring Buffer before submitting @@ -894,7 +845,7 @@ int i915_switch_context(struct drm_i915_gem_request *req) struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt; - if (needs_pd_load_pre(ppgtt, engine, to)) { + if (needs_pd_load_pre(ppgtt, engine)) { int ret; trace_switch_mm(engine, to); @@ -905,6 +856,7 @@ int i915_switch_context(struct drm_i915_gem_request *req) ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); } + engine->legacy_active_context = to; return 0; } @@ -977,7 +929,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) static bool client_is_banned(struct drm_i915_file_private *file_priv) { - return file_priv->context_bans > I915_MAX_CLIENT_CONTEXT_BANS; + return atomic_read(&file_priv->context_bans) > I915_MAX_CLIENT_CONTEXT_BANS; } int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, @@ -1179,8 +1131,8 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, else args->reset_count = 0; - args->batch_active = READ_ONCE(ctx->guilty_count); - args->batch_pending = READ_ONCE(ctx->active_count); + args->batch_active = atomic_read(&ctx->guilty_count); + args->batch_pending = atomic_read(&ctx->active_count); ret = 0; out: |