Commit 93159e12 authored by Chris Wilson's avatar Chris Wilson

drm/i915/gem: Avoid gem_context->mutex for simple vma lookup

As we store the handle lookup inside a radix tree, we do not need the
gem_context->mutex except until we need to insert our lookup into the
common radix tree. This takes a small bit of rearranging to ensure that
the lut we insert into the tree is ready prior to actually inserting it
(as soon as it is exposed via the radixtree, it is visible to any other
submission).

v2: For brownie points, remove the goto spaghetti.
v3: Tighten up the closed-handle checks.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200323092841.22240-8-chris@chris-wilson.co.uk
parent 3447c4c5
...@@ -481,7 +481,7 @@ eb_add_vma(struct i915_execbuffer *eb, ...@@ -481,7 +481,7 @@ eb_add_vma(struct i915_execbuffer *eb,
GEM_BUG_ON(i915_vma_is_closed(vma)); GEM_BUG_ON(i915_vma_is_closed(vma));
ev->vma = i915_vma_get(vma); ev->vma = vma;
ev->exec = entry; ev->exec = entry;
ev->flags = entry->flags; ev->flags = entry->flags;
...@@ -728,77 +728,117 @@ static int eb_select_context(struct i915_execbuffer *eb) ...@@ -728,77 +728,117 @@ static int eb_select_context(struct i915_execbuffer *eb)
return 0; return 0;
} }
static int eb_lookup_vmas(struct i915_execbuffer *eb) static int __eb_add_lut(struct i915_execbuffer *eb,
u32 handle, struct i915_vma *vma)
{ {
struct radix_tree_root *handles_vma = &eb->gem_context->handles_vma; struct i915_gem_context *ctx = eb->gem_context;
struct drm_i915_gem_object *obj; struct i915_lut_handle *lut;
unsigned int i, batch;
int err; int err;
if (unlikely(i915_gem_context_is_closed(eb->gem_context))) lut = i915_lut_handle_alloc();
return -ENOENT; if (unlikely(!lut))
return -ENOMEM;
INIT_LIST_HEAD(&eb->relocs); i915_vma_get(vma);
INIT_LIST_HEAD(&eb->unbound); if (!atomic_fetch_inc(&vma->open_count))
i915_vma_reopen(vma);
lut->handle = handle;
lut->ctx = ctx;
/* Check that the context hasn't been closed in the meantime */
err = -EINTR;
if (!mutex_lock_interruptible(&ctx->mutex)) {
err = -ENOENT;
if (likely(!i915_gem_context_is_closed(ctx)))
err = radix_tree_insert(&ctx->handles_vma, handle, vma);
if (err == 0) { /* And nor has this handle */
struct drm_i915_gem_object *obj = vma->obj;
i915_gem_object_lock(obj);
if (idr_find(&eb->file->object_idr, handle) == obj) {
list_add(&lut->obj_link, &obj->lut_list);
} else {
radix_tree_delete(&ctx->handles_vma, handle);
err = -ENOENT;
}
i915_gem_object_unlock(obj);
}
mutex_unlock(&ctx->mutex);
}
if (unlikely(err))
goto err;
batch = eb_batch_index(eb); return 0;
for (i = 0; i < eb->buffer_count; i++) { err:
u32 handle = eb->exec[i].handle; atomic_dec(&vma->open_count);
struct i915_lut_handle *lut; i915_vma_put(vma);
i915_lut_handle_free(lut);
return err;
}
static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle)
{
do {
struct drm_i915_gem_object *obj;
struct i915_vma *vma; struct i915_vma *vma;
int err;
vma = radix_tree_lookup(handles_vma, handle); rcu_read_lock();
vma = radix_tree_lookup(&eb->gem_context->handles_vma, handle);
if (likely(vma))
vma = i915_vma_tryget(vma);
rcu_read_unlock();
if (likely(vma)) if (likely(vma))
goto add_vma; return vma;
obj = i915_gem_object_lookup(eb->file, handle); obj = i915_gem_object_lookup(eb->file, handle);
if (unlikely(!obj)) { if (unlikely(!obj))
err = -ENOENT; return ERR_PTR(-ENOENT);
goto err_vma;
}
vma = i915_vma_instance(obj, eb->context->vm, NULL); vma = i915_vma_instance(obj, eb->context->vm, NULL);
if (IS_ERR(vma)) { if (IS_ERR(vma)) {
err = PTR_ERR(vma); i915_gem_object_put(obj);
goto err_obj; return vma;
} }
lut = i915_lut_handle_alloc(); err = __eb_add_lut(eb, handle, vma);
if (unlikely(!lut)) { if (likely(!err))
err = -ENOMEM; return vma;
goto err_obj;
}
err = radix_tree_insert(handles_vma, handle, vma); i915_gem_object_put(obj);
if (unlikely(err)) { if (err != -EEXIST)
i915_lut_handle_free(lut); return ERR_PTR(err);
goto err_obj; } while (1);
} }
/* transfer ref to lut */ static int eb_lookup_vmas(struct i915_execbuffer *eb)
if (!atomic_fetch_inc(&vma->open_count)) {
i915_vma_reopen(vma); unsigned int batch = eb_batch_index(eb);
lut->handle = handle; unsigned int i;
lut->ctx = eb->gem_context; int err = 0;
i915_gem_object_lock(obj); INIT_LIST_HEAD(&eb->relocs);
list_add(&lut->obj_link, &obj->lut_list); INIT_LIST_HEAD(&eb->unbound);
i915_gem_object_unlock(obj);
for (i = 0; i < eb->buffer_count; i++) {
struct i915_vma *vma;
vma = eb_lookup_vma(eb, eb->exec[i].handle);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
break;
}
add_vma:
err = eb_validate_vma(eb, &eb->exec[i], vma); err = eb_validate_vma(eb, &eb->exec[i], vma);
if (unlikely(err)) if (unlikely(err)) {
goto err_vma; i915_vma_put(vma);
break;
}
eb_add_vma(eb, i, batch, vma); eb_add_vma(eb, i, batch, vma);
} }
return 0;
err_obj:
i915_gem_object_put(obj);
err_vma:
eb->vma[i].vma = NULL; eb->vma[i].vma = NULL;
return err; return err;
} }
...@@ -1494,9 +1534,7 @@ static int eb_relocate(struct i915_execbuffer *eb) ...@@ -1494,9 +1534,7 @@ static int eb_relocate(struct i915_execbuffer *eb)
{ {
int err; int err;
mutex_lock(&eb->gem_context->mutex);
err = eb_lookup_vmas(eb); err = eb_lookup_vmas(eb);
mutex_unlock(&eb->gem_context->mutex);
if (err) if (err)
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment