[Intel-gfx] [PATCH 3/3] drm/i915: Replace execbuf vma ht with an idr
Tvrtko Ursulin
tvrtko.ursulin at linux.intel.com
Tue Jun 20 11:26:44 UTC 2017
On 16/06/2017 17:02, Chris Wilson wrote:
> This was the competing idea long ago, but it was only with the rewrite
> of the idr as an radixtree and using the radixtree directly ourselves,
> and the realisation that we can store the vma directly in the radixtree
> and only need a list for the reverse mapping, that made the patch
> performant enough to displace using a hashtable. Though the vma ht is
> fast and doesn't require and extra allocation (as we can embed the node
> inside the vma), it does require a thread for resizing and serialization.
> That is hairy enough to investigate alternative and favour them if
> equivalent in performance. One advantage of allocating an indirection
> entry is that we can support a single shared bo between many clients,
> something that was done on a first-come first-serve basis for shared GGTT
> vma previously. To offset the extra allocations, we create yet another
> kmem_cache for them.
>
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> ---
> drivers/gpu/drm/i915/i915_debugfs.c | 6 --
> drivers/gpu/drm/i915/i915_drv.h | 1 +
> drivers/gpu/drm/i915/i915_gem.c | 32 ++++++++--
> drivers/gpu/drm/i915/i915_gem_context.c | 86 +++++----------------------
> drivers/gpu/drm/i915/i915_gem_context.h | 30 ++--------
> drivers/gpu/drm/i915/i915_gem_execbuffer.c | 70 +++++++---------------
> drivers/gpu/drm/i915/i915_gem_object.h | 10 +++-
> drivers/gpu/drm/i915/i915_vma.c | 22 -------
> drivers/gpu/drm/i915/i915_vma.h | 4 --
> drivers/gpu/drm/i915/selftests/mock_context.c | 15 ++---
> lib/radix-tree.c | 1 +
> 11 files changed, 81 insertions(+), 196 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 4577b0af6886..a6ba2100bb88 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1998,12 +1998,6 @@ static int i915_context_status(struct seq_file *m, void *unused)
> seq_putc(m, '\n');
> }
>
> - seq_printf(m,
> - "\tvma hashtable size=%u (actual %lu), count=%u\n",
> - ctx->vma_lut.ht_size,
> - BIT(ctx->vma_lut.ht_bits),
> - ctx->vma_lut.ht_count);
> -
> seq_putc(m, '\n');
> }
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index cd15697c1ca4..de8dd0c06ce6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2083,6 +2083,7 @@ struct drm_i915_private {
>
> struct kmem_cache *objects;
> struct kmem_cache *vmas;
> + struct kmem_cache *luts;
> struct kmem_cache *requests;
> struct kmem_cache *dependencies;
> struct kmem_cache *priorities;
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 7dcac3bfb771..3388c65b54a3 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -3252,19 +3252,33 @@ i915_gem_idle_work_handler(struct work_struct *work)
>
> void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file)
> {
> + struct drm_i915_private *i915 = to_i915(gem->dev);
> struct drm_i915_gem_object *obj = to_intel_bo(gem);
> struct drm_i915_file_private *fpriv = file->driver_priv;
> struct i915_vma *vma, *vn;
> + struct i915_lut_handle *lut, *ln;
>
> mutex_lock(&obj->base.dev->struct_mutex);
> +
> + list_for_each_entry_safe(lut, ln, &obj->lut_list, obj_link) {
> + struct i915_gem_context *ctx = lut->ctx;
> +
> + if (ctx->file_priv != fpriv)
> + continue;
> +
> + radix_tree_delete(&ctx->handles_vma, lut->handle);
> + i915_gem_object_put(obj);
> +
> + list_del(&lut->obj_link);
> + list_del(&lut->ctx_link);
> +
> + kmem_cache_free(i915->luts, lut);
> + }
> +
> list_for_each_entry_safe(vma, vn, &obj->vma_list, obj_link)
> if (vma->vm->file == fpriv)
> i915_vma_close(vma);
>
> - vma = obj->vma_hashed;
> - if (vma && vma->ctx->file_priv == fpriv)
> - i915_vma_unlink_ctx(vma);
> -
> if (i915_gem_object_is_active(obj) &&
> !i915_gem_object_has_active_reference(obj)) {
> i915_gem_object_set_active_reference(obj);
> @@ -4259,6 +4273,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
> INIT_LIST_HEAD(&obj->global_link);
> INIT_LIST_HEAD(&obj->userfault_link);
> INIT_LIST_HEAD(&obj->vma_list);
> + INIT_LIST_HEAD(&obj->lut_list);
> INIT_LIST_HEAD(&obj->batch_pool_link);
>
> obj->ops = ops;
> @@ -4897,12 +4912,16 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
> if (!dev_priv->vmas)
> goto err_objects;
>
> + dev_priv->luts = KMEM_CACHE(i915_lut_handle, 0);
> + if (!dev_priv->luts)
> + goto err_vmas;
> +
> dev_priv->requests = KMEM_CACHE(drm_i915_gem_request,
> SLAB_HWCACHE_ALIGN |
> SLAB_RECLAIM_ACCOUNT |
> SLAB_TYPESAFE_BY_RCU);
> if (!dev_priv->requests)
> - goto err_vmas;
> + goto err_luts;
>
> dev_priv->dependencies = KMEM_CACHE(i915_dependency,
> SLAB_HWCACHE_ALIGN |
> @@ -4949,6 +4968,8 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
> kmem_cache_destroy(dev_priv->dependencies);
> err_requests:
> kmem_cache_destroy(dev_priv->requests);
> +err_luts:
> + kmem_cache_destroy(dev_priv->luts);
> err_vmas:
> kmem_cache_destroy(dev_priv->vmas);
> err_objects:
> @@ -4971,6 +4992,7 @@ void i915_gem_load_cleanup(struct drm_i915_private *dev_priv)
> kmem_cache_destroy(dev_priv->priorities);
> kmem_cache_destroy(dev_priv->dependencies);
> kmem_cache_destroy(dev_priv->requests);
> + kmem_cache_destroy(dev_priv->luts);
> kmem_cache_destroy(dev_priv->vmas);
> kmem_cache_destroy(dev_priv->objects);
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index 39ed58a21fc1..dc182a8dd4e8 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -93,69 +93,21 @@
>
> #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);
I assume you deliberately did not bother unlinking from the ctx list
since all that is getting zapped anyway?
> + 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;
> -
> - if (lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS)
> - cancel_work_sync(&lut->resize);
> -
> - size = BIT(lut->ht_bits);
> - for (i = 0; i < size; i++) {
> - struct i915_vma *vma;
> -
> - hlist_for_each_entry(vma, &lut->ht[i], ctx_node) {
> - vma->obj->vma_hashed = NULL;
> - vma->ctx = NULL;
> - i915_vma_put(vma);
> - }
> + radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) {
> + i915_vma_put(rcu_dereference_raw(*slot));
> + radix_tree_iter_delete(&ctx->handles_vma, &iter, slot);
> }
> - kvfree(lut->ht);
> }
>
> void i915_gem_context_free(struct kref *ctx_ref)
> @@ -167,7 +119,6 @@ void i915_gem_context_free(struct kref *ctx_ref)
> trace_i915_context_free(ctx);
> 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++) {
> @@ -195,8 +146,11 @@ void i915_gem_context_free(struct kref *ctx_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);
> }
> @@ -269,16 +223,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;
> @@ -328,8 +274,6 @@ __create_hw_context(struct drm_i915_private *dev_priv,
> 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);
> }
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h
> index 82c99ba92ad3..cd0c5d8e0db7 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.h
> +++ b/drivers/gpu/drm/i915/i915_gem_context.h
> @@ -27,6 +27,7 @@
>
> #include <linux/bitops.h>
> #include <linux/list.h>
> +#include <linux/radix-tree.h>
>
> struct pid;
>
> @@ -143,32 +144,6 @@ struct i915_gem_context {
> /** ggtt_offset_bias: placement restriction for context objects */
> u32 ggtt_offset_bias;
>
> - struct i915_gem_context_vma_lut {
> - /** ht_size: last request size to allocate the hashtable for. */
> - unsigned int ht_size;
> -#define I915_CTX_RESIZE_IN_PROGRESS BIT(0)
> - /** ht_bits: real log2(size) of hashtable. */
> - unsigned int ht_bits;
> - /** ht_count: current number of entries inside the hashtable */
> - unsigned int ht_count;
> -
> - /** ht: the array of buckets comprising the simple hashtable */
> - struct hlist_head *ht;
> -
> - /**
> - * resize: After an execbuf completes, we check the load factor
> - * of the hashtable. If the hashtable is too full, or too empty,
> - * we schedule a task to resize the hashtable. During the
> - * resize, the entries are moved between different buckets and
> - * so we cannot simultaneously read the hashtable as it is
> - * being resized (unlike rhashtable). Therefore we treat the
> - * active work as a strong barrier, pausing a subsequent
> - * execbuf to wait for the resize worker to complete, if
> - * required.
> - */
> - struct work_struct resize;
> - } vma_lut;
> -
> /** engine: per-engine logical HW state */
> struct intel_context {
> struct i915_vma *state;
> @@ -199,6 +174,9 @@ struct i915_gem_context {
>
> /** remap_slice: Bitmask of cache lines that need remapping */
> u8 remap_slice;
> +
> + struct radix_tree_root handles_vma;
> + struct list_head handles_list;
Add kernel doc for the two please.
> };
>
> static inline bool i915_gem_context_is_closed(const struct i915_gem_context *ctx)
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index 18d6581bc6c5..adcea065985c 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -637,19 +637,6 @@ static int eb_reserve(struct i915_execbuffer *eb)
> } while (1);
> }
>
> -static inline struct hlist_head *
> -ht_head(const struct i915_gem_context_vma_lut *lut, u32 handle)
> -{
> - return &lut->ht[hash_32(handle, lut->ht_bits)];
> -}
> -
> -static inline bool
> -ht_needs_resize(const struct i915_gem_context_vma_lut *lut)
> -{
> - return (4*lut->ht_count > 3*lut->ht_size ||
> - 4*lut->ht_count + 1 < lut->ht_size);
> -}
> -
> static unsigned int eb_batch_index(const struct i915_execbuffer *eb)
> {
> if (eb->args->flags & I915_EXEC_BATCH_FIRST)
> @@ -684,31 +671,22 @@ static int eb_select_context(struct i915_execbuffer *eb)
>
> static int eb_lookup_vmas(struct i915_execbuffer *eb, unsigned int flags)
> {
> - struct i915_gem_context_vma_lut *lut = &eb->ctx->vma_lut;
> - struct drm_i915_gem_object *uninitialized_var(obj);
> + struct drm_i915_gem_object *obj;
> + struct radix_tree_root *handles_vma = &eb->ctx->handles_vma;
> unsigned int i;
> int err;
>
> INIT_LIST_HEAD(&eb->relocs);
> INIT_LIST_HEAD(&eb->unbound);
>
> - if (unlikely(lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS))
> - flush_work(&lut->resize);
> - GEM_BUG_ON(lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS);
> -
> for (i = 0; i < eb->buffer_count; i++) {
> u32 handle = eb->exec[i].handle;
> - struct hlist_head *hl = ht_head(lut, handle);
> struct i915_vma *vma;
> + struct i915_lut_handle *lut;
>
> - hlist_for_each_entry(vma, hl, ctx_node) {
> - GEM_BUG_ON(vma->ctx != eb->ctx);
> -
> - if (vma->ctx_handle != handle)
> - continue;
> -
> + vma = radix_tree_lookup(handles_vma, handle);
> + if (likely(vma))
> goto add_vma;
> - }
>
> obj = i915_gem_object_lookup(eb->file, handle);
> if (unlikely(!obj)) {
> @@ -716,43 +694,36 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb, unsigned int flags)
> goto err_vma;
> }
>
> - flags |= __EXEC_OBJECT_HAS_REF;
> -
> vma = i915_vma_instance(obj, eb->vm, NULL);
> if (unlikely(IS_ERR(vma))) {
> err = PTR_ERR(vma);
> goto err_obj;
> }
>
> - /* First come, first served */
> - if (!vma->ctx) {
> - vma->ctx = eb->ctx;
> - vma->ctx_handle = handle;
> - hlist_add_head(&vma->ctx_node, hl);
> - lut->ht_count++;
> - lut->ht_size |= I915_CTX_RESIZE_IN_PROGRESS;
> - if (i915_vma_is_ggtt(vma)) {
> - GEM_BUG_ON(obj->vma_hashed);
> - obj->vma_hashed = vma;
> - }
> + lut = kmem_cache_alloc(eb->i915->luts, GFP_KERNEL);
> + if (unlikely(!lut)) {
> + err = -ENOMEM;
> + goto err_obj;
> + }
>
> - /* transfer ref to ctx */
> - flags &= ~__EXEC_OBJECT_HAS_REF;
> + /* transfer ref to ctx */
> + err = radix_tree_insert(handles_vma, handle, vma);
> + if (unlikely(err)) {
> + kfree(lut);
> + goto err_obj;
> }
>
> + list_add(&lut->obj_link, &obj->lut_list);
> + list_add(&lut->ctx_link, &eb->ctx->handles_list);
> + lut->ctx = eb->ctx;
> + lut->handle = handle;
> +
> add_vma:
> err = eb_add_vma(eb, i, vma, flags);
> if (unlikely(err))
> goto err_vma;
> }
>
> - if (lut->ht_size & I915_CTX_RESIZE_IN_PROGRESS) {
> - if (ht_needs_resize(lut))
> - queue_work(system_highpri_wq, &lut->resize);
> - else
> - lut->ht_size &= ~I915_CTX_RESIZE_IN_PROGRESS;
> - }
> -
> /* take note of the batch buffer before we might reorder the lists */
> i = eb_batch_index(eb);
> eb->batch = eb->vma[i];
> @@ -778,7 +749,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb, unsigned int flags)
> i915_gem_object_put(obj);
> err_vma:
> eb->vma[i] = NULL;
> - lut->ht_size &= ~I915_CTX_RESIZE_IN_PROGRESS;
> return err;
> }
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h
> index 5b19a4916a4d..8188d3cf5e11 100644
> --- a/drivers/gpu/drm/i915/i915_gem_object.h
> +++ b/drivers/gpu/drm/i915/i915_gem_object.h
> @@ -35,6 +35,13 @@
>
> #include "i915_selftest.h"
>
> +struct i915_lut_handle {
> + struct list_head obj_link;
> + struct list_head ctx_link;
> + struct i915_gem_context *ctx;
> + u32 handle;
> +};
> +
> struct drm_i915_gem_object_ops {
> unsigned int flags;
> #define I915_GEM_OBJECT_HAS_STRUCT_PAGE BIT(0)
> @@ -86,7 +93,8 @@ struct drm_i915_gem_object {
> * They are also added to @vma_list for easy iteration.
> */
> struct rb_root vma_tree;
> - struct i915_vma *vma_hashed;
> +
> + struct list_head lut_list;
And some kernel doc here please.
>
> /** Stolen memory for this object, instead of being backed by shmem. */
> struct drm_mm_node *stolen;
> diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
> index 532c709febbd..93329a809764 100644
> --- a/drivers/gpu/drm/i915/i915_vma.c
> +++ b/drivers/gpu/drm/i915/i915_vma.c
> @@ -591,33 +591,11 @@ static void i915_vma_destroy(struct i915_vma *vma)
> kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
> }
>
> -void i915_vma_unlink_ctx(struct i915_vma *vma)
> -{
> - struct i915_gem_context *ctx = vma->ctx;
> -
> - if (ctx->vma_lut.ht_size & I915_CTX_RESIZE_IN_PROGRESS) {
> - cancel_work_sync(&ctx->vma_lut.resize);
> - ctx->vma_lut.ht_size &= ~I915_CTX_RESIZE_IN_PROGRESS;
> - }
> -
> - __hlist_del(&vma->ctx_node);
> - ctx->vma_lut.ht_count--;
> -
> - if (i915_vma_is_ggtt(vma))
> - vma->obj->vma_hashed = NULL;
> - vma->ctx = NULL;
> -
> - i915_vma_put(vma);
> -}
> -
> void i915_vma_close(struct i915_vma *vma)
> {
> GEM_BUG_ON(i915_vma_is_closed(vma));
> vma->flags |= I915_VMA_CLOSED;
>
> - if (vma->ctx)
> - i915_vma_unlink_ctx(vma);
> -
> list_del(&vma->obj_link);
> rb_erase(&vma->obj_node, &vma->obj->vma_tree);
>
> diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
> index 5f1356e93c6c..6d35cf7ddcfb 100644
> --- a/drivers/gpu/drm/i915/i915_vma.h
> +++ b/drivers/gpu/drm/i915/i915_vma.h
> @@ -115,10 +115,6 @@ struct i915_vma {
> unsigned int *exec_flags;
> struct hlist_node exec_node;
> u32 exec_handle;
> -
> - struct i915_gem_context *ctx;
> - struct hlist_node ctx_node;
> - u32 ctx_handle;
> };
>
> struct i915_vma *
> diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c
> index f8b9cc212b02..3ee31ef84607 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_context.c
> +++ b/drivers/gpu/drm/i915/selftests/mock_context.c
> @@ -40,18 +40,13 @@ mock_context(struct drm_i915_private *i915,
> INIT_LIST_HEAD(&ctx->link);
> ctx->i915 = i915;
>
> - ctx->vma_lut.ht_bits = VMA_HT_BITS;
> - ctx->vma_lut.ht_size = BIT(VMA_HT_BITS);
> - ctx->vma_lut.ht = kcalloc(ctx->vma_lut.ht_size,
> - sizeof(*ctx->vma_lut.ht),
> - GFP_KERNEL);
> - if (!ctx->vma_lut.ht)
> - goto err_free;
> + INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
> + INIT_LIST_HEAD(&ctx->handles_list);
>
> ret = ida_simple_get(&i915->context_hw_ida,
> 0, MAX_CONTEXT_HW_ID, GFP_KERNEL);
> if (ret < 0)
> - goto err_vma_ht;
> + goto err_handles;
> ctx->hw_id = ret;
>
> if (name) {
> @@ -66,9 +61,7 @@ mock_context(struct drm_i915_private *i915,
>
> return ctx;
>
> -err_vma_ht:
> - kvfree(ctx->vma_lut.ht);
> -err_free:
> +err_handles:
> kfree(ctx);
> return NULL;
>
> diff --git a/lib/radix-tree.c b/lib/radix-tree.c
> index 898e87998417..3527eb364964 100644
> --- a/lib/radix-tree.c
> +++ b/lib/radix-tree.c
> @@ -2022,6 +2022,7 @@ void radix_tree_iter_delete(struct radix_tree_root *root,
> if (__radix_tree_delete(root, iter->node, slot))
> iter->index = iter->next_index;
> }
> +EXPORT_SYMBOL(radix_tree_iter_delete);
>
> /**
> * radix_tree_delete_item - delete an item from a radix tree
>
Very nice! Much shorter and more elegant (and so readable) than the
previous state of affairs.
With the kerneldoc added:
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
Regards,
Tvrtko
More information about the Intel-gfx
mailing list