mirror of
https://github.com/torvalds/linux.git
synced 2026-04-27 19:12:29 -04:00
drm/i915: Move context management under GEM
Keep track of the GEM contexts underneath i915->gem.contexts and assign them their own lock for the purposes of list management. v2: Focus on lock tracking; ctx->vm is protected by ctx->mutex v3: Correct split with removal of logical HW ID Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191004134015.13204-15-chris@chris-wilson.co.uk
This commit is contained in:
@@ -218,9 +218,12 @@ static struct i915_gem_engines *default_engines(struct i915_gem_context *ctx)
|
||||
|
||||
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));
|
||||
|
||||
spin_lock(&ctx->i915->gem.contexts.lock);
|
||||
list_del(&ctx->link);
|
||||
spin_unlock(&ctx->i915->gem.contexts.lock);
|
||||
|
||||
free_engines(rcu_access_pointer(ctx->engines));
|
||||
mutex_destroy(&ctx->engines_mutex);
|
||||
|
||||
@@ -230,67 +233,54 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
|
||||
kfree(ctx->name);
|
||||
put_pid(ctx->pid);
|
||||
|
||||
list_del(&ctx->link);
|
||||
mutex_destroy(&ctx->mutex);
|
||||
|
||||
kfree_rcu(ctx, rcu);
|
||||
}
|
||||
|
||||
static void contexts_free(struct drm_i915_private *i915)
|
||||
static void contexts_free_all(struct llist_node *list)
|
||||
{
|
||||
struct llist_node *freed = llist_del_all(&i915->contexts.free_list);
|
||||
struct i915_gem_context *ctx, *cn;
|
||||
|
||||
lockdep_assert_held(&i915->drm.struct_mutex);
|
||||
|
||||
llist_for_each_entry_safe(ctx, cn, freed, free_link)
|
||||
llist_for_each_entry_safe(ctx, cn, list, free_link)
|
||||
i915_gem_context_free(ctx);
|
||||
}
|
||||
|
||||
static void contexts_free_first(struct drm_i915_private *i915)
|
||||
static void contexts_flush_free(struct i915_gem_contexts *gc)
|
||||
{
|
||||
struct i915_gem_context *ctx;
|
||||
struct llist_node *freed;
|
||||
|
||||
lockdep_assert_held(&i915->drm.struct_mutex);
|
||||
|
||||
freed = llist_del_first(&i915->contexts.free_list);
|
||||
if (!freed)
|
||||
return;
|
||||
|
||||
ctx = container_of(freed, typeof(*ctx), free_link);
|
||||
i915_gem_context_free(ctx);
|
||||
contexts_free_all(llist_del_all(&gc->free_list));
|
||||
}
|
||||
|
||||
static void contexts_free_worker(struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *i915 =
|
||||
container_of(work, typeof(*i915), contexts.free_work);
|
||||
struct i915_gem_contexts *gc =
|
||||
container_of(work, typeof(*gc), free_work);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
contexts_free(i915);
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
contexts_flush_free(gc);
|
||||
}
|
||||
|
||||
void i915_gem_context_release(struct kref *ref)
|
||||
{
|
||||
struct i915_gem_context *ctx = container_of(ref, typeof(*ctx), ref);
|
||||
struct drm_i915_private *i915 = ctx->i915;
|
||||
struct i915_gem_contexts *gc = &ctx->i915->gem.contexts;
|
||||
|
||||
trace_i915_context_free(ctx);
|
||||
if (llist_add(&ctx->free_link, &i915->contexts.free_list))
|
||||
queue_work(i915->wq, &i915->contexts.free_work);
|
||||
if (llist_add(&ctx->free_link, &gc->free_list))
|
||||
schedule_work(&gc->free_work);
|
||||
}
|
||||
|
||||
static void context_close(struct i915_gem_context *ctx)
|
||||
{
|
||||
struct i915_address_space *vm;
|
||||
|
||||
i915_gem_context_set_closed(ctx);
|
||||
|
||||
if (ctx->vm)
|
||||
i915_vm_close(ctx->vm);
|
||||
|
||||
mutex_lock(&ctx->mutex);
|
||||
|
||||
vm = i915_gem_context_vm(ctx);
|
||||
if (vm)
|
||||
i915_vm_close(vm);
|
||||
|
||||
ctx->file_priv = ERR_PTR(-EBADF);
|
||||
|
||||
/*
|
||||
@@ -317,7 +307,6 @@ __create_context(struct drm_i915_private *i915)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
kref_init(&ctx->ref);
|
||||
list_add_tail(&ctx->link, &i915->contexts.list);
|
||||
ctx->i915 = i915;
|
||||
ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL);
|
||||
mutex_init(&ctx->mutex);
|
||||
@@ -343,6 +332,10 @@ __create_context(struct drm_i915_private *i915)
|
||||
for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++)
|
||||
ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES;
|
||||
|
||||
spin_lock(&i915->gem.contexts.lock);
|
||||
list_add_tail(&ctx->link, &i915->gem.contexts.list);
|
||||
spin_unlock(&i915->gem.contexts.lock);
|
||||
|
||||
return ctx;
|
||||
|
||||
err_free:
|
||||
@@ -372,11 +365,11 @@ static void __apply_ppgtt(struct intel_context *ce, void *vm)
|
||||
static struct i915_address_space *
|
||||
__set_ppgtt(struct i915_gem_context *ctx, struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_address_space *old = ctx->vm;
|
||||
struct i915_address_space *old = i915_gem_context_vm(ctx);
|
||||
|
||||
GEM_BUG_ON(old && i915_vm_is_4lvl(vm) != i915_vm_is_4lvl(old));
|
||||
|
||||
ctx->vm = i915_vm_open(vm);
|
||||
rcu_assign_pointer(ctx->vm, i915_vm_open(vm));
|
||||
context_apply_all(ctx, __apply_ppgtt, vm);
|
||||
|
||||
return old;
|
||||
@@ -385,7 +378,7 @@ __set_ppgtt(struct i915_gem_context *ctx, struct i915_address_space *vm)
|
||||
static void __assign_ppgtt(struct i915_gem_context *ctx,
|
||||
struct i915_address_space *vm)
|
||||
{
|
||||
if (vm == ctx->vm)
|
||||
if (vm == rcu_access_pointer(ctx->vm))
|
||||
return;
|
||||
|
||||
vm = __set_ppgtt(ctx, vm);
|
||||
@@ -417,27 +410,25 @@ static void __assign_timeline(struct i915_gem_context *ctx,
|
||||
}
|
||||
|
||||
static struct i915_gem_context *
|
||||
i915_gem_create_context(struct drm_i915_private *dev_priv, unsigned int flags)
|
||||
i915_gem_create_context(struct drm_i915_private *i915, unsigned int flags)
|
||||
{
|
||||
struct i915_gem_context *ctx;
|
||||
|
||||
lockdep_assert_held(&dev_priv->drm.struct_mutex);
|
||||
|
||||
if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE &&
|
||||
!HAS_EXECLISTS(dev_priv))
|
||||
!HAS_EXECLISTS(i915))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Reap the most stale context */
|
||||
contexts_free_first(dev_priv);
|
||||
/* Reap the stale contexts */
|
||||
contexts_flush_free(&i915->gem.contexts);
|
||||
|
||||
ctx = __create_context(dev_priv);
|
||||
ctx = __create_context(i915);
|
||||
if (IS_ERR(ctx))
|
||||
return ctx;
|
||||
|
||||
if (HAS_FULL_PPGTT(dev_priv)) {
|
||||
if (HAS_FULL_PPGTT(i915)) {
|
||||
struct i915_ppgtt *ppgtt;
|
||||
|
||||
ppgtt = i915_ppgtt_create(dev_priv);
|
||||
ppgtt = i915_ppgtt_create(i915);
|
||||
if (IS_ERR(ppgtt)) {
|
||||
DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
|
||||
PTR_ERR(ppgtt));
|
||||
@@ -445,14 +436,17 @@ i915_gem_create_context(struct drm_i915_private *dev_priv, unsigned int flags)
|
||||
return ERR_CAST(ppgtt);
|
||||
}
|
||||
|
||||
mutex_lock(&ctx->mutex);
|
||||
__assign_ppgtt(ctx, &ppgtt->vm);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
i915_vm_put(&ppgtt->vm);
|
||||
}
|
||||
|
||||
if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) {
|
||||
struct intel_timeline *timeline;
|
||||
|
||||
timeline = intel_timeline_create(&dev_priv->gt, NULL);
|
||||
timeline = intel_timeline_create(&i915->gt, NULL);
|
||||
if (IS_ERR(timeline)) {
|
||||
context_close(ctx);
|
||||
return ERR_CAST(timeline);
|
||||
@@ -497,42 +491,40 @@ i915_gem_context_create_kernel(struct drm_i915_private *i915, int prio)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void init_contexts(struct drm_i915_private *i915)
|
||||
static void init_contexts(struct i915_gem_contexts *gc)
|
||||
{
|
||||
mutex_init(&i915->contexts.mutex);
|
||||
INIT_LIST_HEAD(&i915->contexts.list);
|
||||
spin_lock_init(&gc->lock);
|
||||
INIT_LIST_HEAD(&gc->list);
|
||||
|
||||
INIT_WORK(&i915->contexts.free_work, contexts_free_worker);
|
||||
init_llist_head(&i915->contexts.free_list);
|
||||
INIT_WORK(&gc->free_work, contexts_free_worker);
|
||||
init_llist_head(&gc->free_list);
|
||||
}
|
||||
|
||||
int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
|
||||
int i915_gem_init_contexts(struct drm_i915_private *i915)
|
||||
{
|
||||
struct i915_gem_context *ctx;
|
||||
|
||||
/* Reassure ourselves we are only called once */
|
||||
GEM_BUG_ON(dev_priv->kernel_context);
|
||||
GEM_BUG_ON(i915->kernel_context);
|
||||
|
||||
init_contexts(dev_priv);
|
||||
init_contexts(&i915->gem.contexts);
|
||||
|
||||
/* lowest priority; idle task */
|
||||
ctx = i915_gem_context_create_kernel(dev_priv, I915_PRIORITY_MIN);
|
||||
ctx = i915_gem_context_create_kernel(i915, I915_PRIORITY_MIN);
|
||||
if (IS_ERR(ctx)) {
|
||||
DRM_ERROR("Failed to create default global context\n");
|
||||
return PTR_ERR(ctx);
|
||||
}
|
||||
dev_priv->kernel_context = ctx;
|
||||
i915->kernel_context = ctx;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s context support initialized\n",
|
||||
DRIVER_CAPS(dev_priv)->has_logical_contexts ?
|
||||
DRIVER_CAPS(i915)->has_logical_contexts ?
|
||||
"logical" : "fake");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_gem_contexts_fini(struct drm_i915_private *i915)
|
||||
void i915_gem_driver_release__contexts(struct drm_i915_private *i915)
|
||||
{
|
||||
lockdep_assert_held(&i915->drm.struct_mutex);
|
||||
|
||||
destroy_kernel_context(&i915->kernel_context);
|
||||
}
|
||||
|
||||
@@ -551,11 +543,16 @@ static int vm_idr_cleanup(int id, void *p, void *data)
|
||||
static int gem_context_register(struct i915_gem_context *ctx,
|
||||
struct drm_i915_file_private *fpriv)
|
||||
{
|
||||
struct i915_address_space *vm;
|
||||
int ret;
|
||||
|
||||
ctx->file_priv = fpriv;
|
||||
if (ctx->vm)
|
||||
ctx->vm->file = fpriv;
|
||||
|
||||
mutex_lock(&ctx->mutex);
|
||||
vm = i915_gem_context_vm(ctx);
|
||||
if (vm)
|
||||
WRITE_ONCE(vm->file, fpriv); /* XXX */
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
ctx->pid = get_task_pid(current, PIDTYPE_PID);
|
||||
ctx->name = kasprintf(GFP_KERNEL, "%s[%d]",
|
||||
@@ -592,9 +589,7 @@ int i915_gem_context_open(struct drm_i915_private *i915,
|
||||
idr_init(&file_priv->context_idr);
|
||||
idr_init_base(&file_priv->vm_idr, 1);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
ctx = i915_gem_create_context(i915, 0);
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
if (IS_ERR(ctx)) {
|
||||
err = PTR_ERR(ctx);
|
||||
goto err;
|
||||
@@ -622,6 +617,7 @@ err:
|
||||
void i915_gem_context_close(struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||
struct drm_i915_private *i915 = file_priv->dev_priv;
|
||||
|
||||
idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
|
||||
idr_destroy(&file_priv->context_idr);
|
||||
@@ -630,6 +626,8 @@ void i915_gem_context_close(struct drm_file *file)
|
||||
idr_for_each(&file_priv->vm_idr, vm_idr_cleanup, NULL);
|
||||
idr_destroy(&file_priv->vm_idr);
|
||||
mutex_destroy(&file_priv->vm_idr_lock);
|
||||
|
||||
contexts_flush_free(&i915->gem.contexts);
|
||||
}
|
||||
|
||||
int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
|
||||
@@ -808,16 +806,12 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv,
|
||||
struct i915_address_space *vm;
|
||||
int ret;
|
||||
|
||||
if (!ctx->vm)
|
||||
if (!rcu_access_pointer(ctx->vm))
|
||||
return -ENODEV;
|
||||
|
||||
/* XXX rcu acquire? */
|
||||
ret = mutex_lock_interruptible(&ctx->i915->drm.struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rcu_read_lock();
|
||||
vm = i915_vm_get(ctx->vm);
|
||||
mutex_unlock(&ctx->i915->drm.struct_mutex);
|
||||
rcu_read_unlock();
|
||||
|
||||
ret = mutex_lock_interruptible(&file_priv->vm_idr_lock);
|
||||
if (ret)
|
||||
@@ -926,7 +920,7 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv,
|
||||
if (args->size)
|
||||
return -EINVAL;
|
||||
|
||||
if (!ctx->vm)
|
||||
if (!rcu_access_pointer(ctx->vm))
|
||||
return -ENODEV;
|
||||
|
||||
if (upper_32_bits(args->value))
|
||||
@@ -940,17 +934,20 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv,
|
||||
if (!vm)
|
||||
return -ENOENT;
|
||||
|
||||
err = mutex_lock_interruptible(&ctx->i915->drm.struct_mutex);
|
||||
err = mutex_lock_interruptible(&ctx->mutex);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (vm == ctx->vm)
|
||||
if (i915_gem_context_is_closed(ctx)) {
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vm == rcu_access_pointer(ctx->vm))
|
||||
goto unlock;
|
||||
|
||||
/* Teardown the existing obj:vma cache, it will have to be rebuilt. */
|
||||
mutex_lock(&ctx->mutex);
|
||||
lut_close(ctx);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
old = __set_ppgtt(ctx, vm);
|
||||
|
||||
@@ -970,8 +967,7 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv,
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&ctx->i915->drm.struct_mutex);
|
||||
|
||||
mutex_unlock(&ctx->mutex);
|
||||
out:
|
||||
i915_vm_put(vm);
|
||||
return err;
|
||||
@@ -1827,10 +1823,11 @@ static int clone_vm(struct i915_gem_context *dst,
|
||||
struct i915_gem_context *src)
|
||||
{
|
||||
struct i915_address_space *vm;
|
||||
int err = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
vm = READ_ONCE(src->vm);
|
||||
vm = rcu_dereference(src->vm);
|
||||
if (!vm)
|
||||
break;
|
||||
|
||||
@@ -1852,7 +1849,7 @@ static int clone_vm(struct i915_gem_context *dst,
|
||||
* it cannot be reallocated elsewhere.
|
||||
*/
|
||||
|
||||
if (vm == READ_ONCE(src->vm))
|
||||
if (vm == rcu_access_pointer(src->vm))
|
||||
break;
|
||||
|
||||
i915_vm_put(vm);
|
||||
@@ -1860,11 +1857,16 @@ static int clone_vm(struct i915_gem_context *dst,
|
||||
rcu_read_unlock();
|
||||
|
||||
if (vm) {
|
||||
__assign_ppgtt(dst, vm);
|
||||
if (!mutex_lock_interruptible(&dst->mutex)) {
|
||||
__assign_ppgtt(dst, vm);
|
||||
mutex_unlock(&dst->mutex);
|
||||
} else {
|
||||
err = -EINTR;
|
||||
}
|
||||
i915_vm_put(vm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int create_clone(struct i915_user_extension __user *ext, void *data)
|
||||
@@ -1954,12 +1956,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = i915_mutex_lock_interruptible(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ext_data.ctx = i915_gem_create_context(i915, args->flags);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (IS_ERR(ext_data.ctx))
|
||||
return PTR_ERR(ext_data.ctx);
|
||||
|
||||
@@ -2086,10 +2083,12 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
case I915_CONTEXT_PARAM_GTT_SIZE:
|
||||
args->size = 0;
|
||||
if (ctx->vm)
|
||||
args->value = ctx->vm->total;
|
||||
rcu_read_lock();
|
||||
if (rcu_access_pointer(ctx->vm))
|
||||
args->value = rcu_dereference(ctx->vm)->total;
|
||||
else
|
||||
args->value = to_i915(dev)->ggtt.vm.total;
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
|
||||
case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:
|
||||
@@ -2155,7 +2154,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
|
||||
int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_i915_private *i915 = to_i915(dev);
|
||||
struct drm_i915_reset_stats *args = data;
|
||||
struct i915_gem_context *ctx;
|
||||
int ret;
|
||||
@@ -2177,7 +2176,7 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
|
||||
*/
|
||||
|
||||
if (capable(CAP_SYS_ADMIN))
|
||||
args->reset_count = i915_reset_count(&dev_priv->gpu_error);
|
||||
args->reset_count = i915_reset_count(&i915->gpu_error);
|
||||
else
|
||||
args->reset_count = 0;
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
|
||||
#include "gt/intel_context.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem.h"
|
||||
#include "i915_gem_gtt.h"
|
||||
#include "i915_scheduler.h"
|
||||
#include "intel_device_info.h"
|
||||
|
||||
@@ -118,8 +120,8 @@ static inline bool i915_gem_context_is_kernel(struct i915_gem_context *ctx)
|
||||
}
|
||||
|
||||
/* i915_gem_context.c */
|
||||
int __must_check i915_gem_contexts_init(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_contexts_fini(struct drm_i915_private *dev_priv);
|
||||
int __must_check i915_gem_init_contexts(struct drm_i915_private *i915);
|
||||
void i915_gem_driver_release__contexts(struct drm_i915_private *i915);
|
||||
|
||||
int i915_gem_context_open(struct drm_i915_private *i915,
|
||||
struct drm_file *file);
|
||||
@@ -158,6 +160,27 @@ static inline void i915_gem_context_put(struct i915_gem_context *ctx)
|
||||
kref_put(&ctx->ref, i915_gem_context_release);
|
||||
}
|
||||
|
||||
static inline struct i915_address_space *
|
||||
i915_gem_context_vm(struct i915_gem_context *ctx)
|
||||
{
|
||||
return rcu_dereference_protected(ctx->vm, lockdep_is_held(&ctx->mutex));
|
||||
}
|
||||
|
||||
static inline struct i915_address_space *
|
||||
i915_gem_context_get_vm_rcu(struct i915_gem_context *ctx)
|
||||
{
|
||||
struct i915_address_space *vm;
|
||||
|
||||
rcu_read_lock();
|
||||
vm = rcu_dereference(ctx->vm);
|
||||
if (!vm)
|
||||
vm = &ctx->i915->ggtt.vm;
|
||||
vm = i915_vm_get(vm);
|
||||
rcu_read_unlock();
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
static inline struct i915_gem_engines *
|
||||
i915_gem_context_engines(struct i915_gem_context *ctx)
|
||||
{
|
||||
|
||||
@@ -88,7 +88,7 @@ struct i915_gem_context {
|
||||
* In other modes, this is a NULL pointer with the expectation that
|
||||
* the caller uses the shared global GTT.
|
||||
*/
|
||||
struct i915_address_space *vm;
|
||||
struct i915_address_space __rcu *vm;
|
||||
|
||||
/**
|
||||
* @pid: process id of creator
|
||||
|
||||
@@ -728,7 +728,7 @@ static int eb_select_context(struct i915_execbuffer *eb)
|
||||
return -ENOENT;
|
||||
|
||||
eb->gem_context = ctx;
|
||||
if (ctx->vm)
|
||||
if (rcu_access_pointer(ctx->vm))
|
||||
eb->invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
|
||||
|
||||
eb->context_flags = 0;
|
||||
|
||||
@@ -766,7 +766,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
|
||||
* On almost all of the older hw, we cannot tell the GPU that
|
||||
* a page is readonly.
|
||||
*/
|
||||
vm = dev_priv->kernel_context->vm;
|
||||
vm = rcu_dereference_protected(dev_priv->kernel_context->vm,
|
||||
true); /* static vm */
|
||||
if (!vm || !vm->has_read_only)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -1322,15 +1322,15 @@ static int igt_ppgtt_pin_update(void *arg)
|
||||
struct i915_gem_context *ctx = arg;
|
||||
struct drm_i915_private *dev_priv = ctx->i915;
|
||||
unsigned long supported = INTEL_INFO(dev_priv)->page_sizes;
|
||||
struct i915_address_space *vm = ctx->vm;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_gem_engines_iter it;
|
||||
struct i915_address_space *vm;
|
||||
struct intel_context *ce;
|
||||
struct i915_vma *vma;
|
||||
unsigned int flags = PIN_USER | PIN_OFFSET_FIXED;
|
||||
unsigned int n;
|
||||
int first, last;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Make sure there's no funny business when doing a PIN_UPDATE -- in the
|
||||
@@ -1340,9 +1340,10 @@ static int igt_ppgtt_pin_update(void *arg)
|
||||
* huge-gtt-pages.
|
||||
*/
|
||||
|
||||
if (!vm || !i915_vm_is_4lvl(vm)) {
|
||||
vm = i915_gem_context_get_vm_rcu(ctx);
|
||||
if (!i915_vm_is_4lvl(vm)) {
|
||||
pr_info("48b PPGTT not supported, skipping\n");
|
||||
return 0;
|
||||
goto out_vm;
|
||||
}
|
||||
|
||||
first = ilog2(I915_GTT_PAGE_SIZE_64K);
|
||||
@@ -1451,6 +1452,8 @@ out_close:
|
||||
i915_vma_close(vma);
|
||||
out_put:
|
||||
i915_gem_object_put(obj);
|
||||
out_vm:
|
||||
i915_vm_put(vm);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1460,7 +1463,7 @@ static int igt_tmpfs_fallback(void *arg)
|
||||
struct i915_gem_context *ctx = arg;
|
||||
struct drm_i915_private *i915 = ctx->i915;
|
||||
struct vfsmount *gemfs = i915->mm.gemfs;
|
||||
struct i915_address_space *vm = ctx->vm ?: &i915->ggtt.vm;
|
||||
struct i915_address_space *vm = i915_gem_context_get_vm_rcu(ctx);
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_vma *vma;
|
||||
u32 *vaddr;
|
||||
@@ -1510,6 +1513,7 @@ out_put:
|
||||
out_restore:
|
||||
i915->mm.gemfs = gemfs;
|
||||
|
||||
i915_vm_put(vm);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1517,14 +1521,14 @@ static int igt_shrink_thp(void *arg)
|
||||
{
|
||||
struct i915_gem_context *ctx = arg;
|
||||
struct drm_i915_private *i915 = ctx->i915;
|
||||
struct i915_address_space *vm = ctx->vm ?: &i915->ggtt.vm;
|
||||
struct i915_address_space *vm = i915_gem_context_get_vm_rcu(ctx);
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_gem_engines_iter it;
|
||||
struct intel_context *ce;
|
||||
struct i915_vma *vma;
|
||||
unsigned int flags = PIN_USER;
|
||||
unsigned int n;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Sanity check shrinking huge-paged object -- make sure nothing blows
|
||||
@@ -1533,12 +1537,14 @@ static int igt_shrink_thp(void *arg)
|
||||
|
||||
if (!igt_can_allocate_thp(i915)) {
|
||||
pr_info("missing THP support, skipping\n");
|
||||
return 0;
|
||||
goto out_vm;
|
||||
}
|
||||
|
||||
obj = i915_gem_object_create_shmem(i915, SZ_2M);
|
||||
if (IS_ERR(obj))
|
||||
return PTR_ERR(obj);
|
||||
if (IS_ERR(obj)) {
|
||||
err = PTR_ERR(obj);
|
||||
goto out_vm;
|
||||
}
|
||||
|
||||
vma = i915_vma_instance(obj, vm, NULL);
|
||||
if (IS_ERR(vma)) {
|
||||
@@ -1607,6 +1613,8 @@ out_close:
|
||||
i915_vma_close(vma);
|
||||
out_put:
|
||||
i915_gem_object_put(obj);
|
||||
out_vm:
|
||||
i915_vm_put(vm);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1675,6 +1683,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915)
|
||||
};
|
||||
struct drm_file *file;
|
||||
struct i915_gem_context *ctx;
|
||||
struct i915_address_space *vm;
|
||||
intel_wakeref_t wakeref;
|
||||
int err;
|
||||
|
||||
@@ -1699,8 +1708,11 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (ctx->vm)
|
||||
ctx->vm->scrub_64K = true;
|
||||
mutex_lock(&ctx->mutex);
|
||||
vm = i915_gem_context_vm(ctx);
|
||||
if (vm)
|
||||
WRITE_ONCE(vm->scrub_64K, true);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
err = i915_subtests(tests, ctx);
|
||||
|
||||
|
||||
@@ -53,19 +53,17 @@ static int live_nop_switch(void *arg)
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
err = -ENOMEM;
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
for (n = 0; n < nctx; n++) {
|
||||
ctx[n] = live_context(i915, file);
|
||||
if (IS_ERR(ctx[n])) {
|
||||
err = PTR_ERR(ctx[n]);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +77,7 @@ static int live_nop_switch(void *arg)
|
||||
rq = igt_request_alloc(ctx[n], engine);
|
||||
if (IS_ERR(rq)) {
|
||||
err = PTR_ERR(rq);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
i915_request_add(rq);
|
||||
}
|
||||
@@ -87,7 +85,7 @@ static int live_nop_switch(void *arg)
|
||||
pr_err("Failed to populated %d contexts\n", nctx);
|
||||
intel_gt_set_wedged(&i915->gt);
|
||||
err = -EIO;
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
times[1] = ktime_get_raw();
|
||||
@@ -97,7 +95,7 @@ static int live_nop_switch(void *arg)
|
||||
|
||||
err = igt_live_test_begin(&t, i915, __func__, engine->name);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
end_time = jiffies + i915_selftest.timeout_jiffies;
|
||||
for_each_prime_number_from(prime, 2, 8192) {
|
||||
@@ -107,7 +105,7 @@ static int live_nop_switch(void *arg)
|
||||
rq = igt_request_alloc(ctx[n % nctx], engine);
|
||||
if (IS_ERR(rq)) {
|
||||
err = PTR_ERR(rq);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -143,7 +141,7 @@ static int live_nop_switch(void *arg)
|
||||
|
||||
err = igt_live_test_end(&t);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
pr_info("Switch latencies on %s: 1 = %lluns, %lu = %lluns\n",
|
||||
engine->name,
|
||||
@@ -151,8 +149,7 @@ static int live_nop_switch(void *arg)
|
||||
prime - 1, div64_u64(ktime_to_ns(times[1]), prime - 1));
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
out_file:
|
||||
mock_file_free(i915, file);
|
||||
return err;
|
||||
}
|
||||
@@ -253,12 +250,10 @@ static int live_parallel_switch(void *arg)
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
ctx = live_context(i915, file);
|
||||
if (IS_ERR(ctx)) {
|
||||
err = PTR_ERR(ctx);
|
||||
goto out_locked;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
engines = i915_gem_context_lock_engines(ctx);
|
||||
@@ -268,7 +263,7 @@ static int live_parallel_switch(void *arg)
|
||||
if (!data) {
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
err = -ENOMEM;
|
||||
goto out_locked;
|
||||
goto out;
|
||||
}
|
||||
|
||||
m = 0; /* Use the first context as our template for the engines */
|
||||
@@ -276,7 +271,7 @@ static int live_parallel_switch(void *arg)
|
||||
err = intel_context_pin(ce);
|
||||
if (err) {
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
goto out_locked;
|
||||
goto out;
|
||||
}
|
||||
data[m++].ce[0] = intel_context_get(ce);
|
||||
}
|
||||
@@ -287,7 +282,7 @@ static int live_parallel_switch(void *arg)
|
||||
ctx = live_context(i915, file);
|
||||
if (IS_ERR(ctx)) {
|
||||
err = PTR_ERR(ctx);
|
||||
goto out_locked;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (m = 0; m < count; m++) {
|
||||
@@ -296,20 +291,18 @@ static int live_parallel_switch(void *arg)
|
||||
|
||||
ce = intel_context_create(ctx, data[m].ce[0]->engine);
|
||||
if (IS_ERR(ce))
|
||||
goto out_locked;
|
||||
goto out;
|
||||
|
||||
err = intel_context_pin(ce);
|
||||
if (err) {
|
||||
intel_context_put(ce);
|
||||
goto out_locked;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data[m].ce[n] = ce;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
for (fn = func; !err && *fn; fn++) {
|
||||
struct igt_live_test t;
|
||||
int n;
|
||||
@@ -354,8 +347,7 @@ static int live_parallel_switch(void *arg)
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
}
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
out_locked:
|
||||
out:
|
||||
for (n = 0; n < count; n++) {
|
||||
for (m = 0; m < ARRAY_SIZE(data->ce); m++) {
|
||||
if (!data[n].ce[m])
|
||||
@@ -365,8 +357,8 @@ out_locked:
|
||||
intel_context_put(data[n].ce[m]);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
kfree(data);
|
||||
out_file:
|
||||
mock_file_free(i915, file);
|
||||
return err;
|
||||
}
|
||||
@@ -626,11 +618,9 @@ static int igt_ctx_exec(void *arg)
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
err = igt_live_test_begin(&t, i915, __func__, engine->name);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
ncontexts = 0;
|
||||
ndwords = 0;
|
||||
@@ -642,7 +632,7 @@ static int igt_ctx_exec(void *arg)
|
||||
ctx = kernel_context(i915);
|
||||
if (IS_ERR(ctx)) {
|
||||
err = PTR_ERR(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
ce = i915_gem_context_get_engine(ctx, engine->legacy_idx);
|
||||
@@ -654,7 +644,7 @@ static int igt_ctx_exec(void *arg)
|
||||
err = PTR_ERR(obj);
|
||||
intel_context_put(ce);
|
||||
kernel_context_close(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,17 +653,18 @@ static int igt_ctx_exec(void *arg)
|
||||
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
|
||||
ndwords, dw, max_dwords(obj),
|
||||
engine->name,
|
||||
yesno(!!ctx->vm), err);
|
||||
yesno(!!rcu_access_pointer(ctx->vm)),
|
||||
err);
|
||||
intel_context_put(ce);
|
||||
kernel_context_close(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
err = throttle(ce, tq, ARRAY_SIZE(tq));
|
||||
if (err) {
|
||||
intel_context_put(ce);
|
||||
kernel_context_close(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
if (++dw == max_dwords(obj)) {
|
||||
@@ -703,11 +694,10 @@ static int igt_ctx_exec(void *arg)
|
||||
dw += rem;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
out_file:
|
||||
throttle_release(tq, ARRAY_SIZE(tq));
|
||||
if (igt_live_test_end(&t))
|
||||
err = -EIO;
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
mock_file_free(i915, file);
|
||||
if (err)
|
||||
@@ -742,22 +732,20 @@ static int igt_shared_ctx_exec(void *arg)
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
parent = live_context(i915, file);
|
||||
if (IS_ERR(parent)) {
|
||||
err = PTR_ERR(parent);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
if (!parent->vm) { /* not full-ppgtt; nothing to share */
|
||||
err = 0;
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
err = igt_live_test_begin(&t, i915, __func__, "");
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
for_each_engine(engine, i915, id) {
|
||||
unsigned long ncontexts, ndwords, dw;
|
||||
@@ -781,7 +769,9 @@ static int igt_shared_ctx_exec(void *arg)
|
||||
goto out_test;
|
||||
}
|
||||
|
||||
mutex_lock(&ctx->mutex);
|
||||
__assign_ppgtt(ctx, parent->vm);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
ce = i915_gem_context_get_engine(ctx, engine->legacy_idx);
|
||||
GEM_BUG_ON(IS_ERR(ce));
|
||||
@@ -801,7 +791,8 @@ static int igt_shared_ctx_exec(void *arg)
|
||||
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
|
||||
ndwords, dw, max_dwords(obj),
|
||||
engine->name,
|
||||
yesno(!!ctx->vm), err);
|
||||
yesno(!!rcu_access_pointer(ctx->vm)),
|
||||
err);
|
||||
intel_context_put(ce);
|
||||
kernel_context_close(ctx);
|
||||
goto out_test;
|
||||
@@ -840,17 +831,13 @@ static int igt_shared_ctx_exec(void *arg)
|
||||
dw += rem;
|
||||
}
|
||||
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
i915_gem_drain_freed_objects(i915);
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
}
|
||||
out_test:
|
||||
throttle_release(tq, ARRAY_SIZE(tq));
|
||||
if (igt_live_test_end(&t))
|
||||
err = -EIO;
|
||||
out_unlock:
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
out_file:
|
||||
mock_file_free(i915, file);
|
||||
return err;
|
||||
}
|
||||
@@ -1222,8 +1209,6 @@ __igt_ctx_sseu(struct drm_i915_private *i915,
|
||||
if (flags & TEST_RESET)
|
||||
igt_global_reset_lock(&i915->gt);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
ctx = live_context(i915, file);
|
||||
if (IS_ERR(ctx)) {
|
||||
ret = PTR_ERR(ctx);
|
||||
@@ -1278,8 +1263,6 @@ out_put:
|
||||
i915_gem_object_put(obj);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
if (flags & TEST_RESET)
|
||||
igt_global_reset_unlock(&i915->gt);
|
||||
|
||||
@@ -1339,23 +1322,24 @@ static int igt_ctx_readonly(void *arg)
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
err = igt_live_test_begin(&t, i915, __func__, "");
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
ctx = live_context(i915, file);
|
||||
if (IS_ERR(ctx)) {
|
||||
err = PTR_ERR(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
vm = ctx->vm ?: &i915->ggtt.alias->vm;
|
||||
rcu_read_lock();
|
||||
vm = rcu_dereference(ctx->vm) ?: &i915->ggtt.alias->vm;
|
||||
if (!vm || !vm->has_read_only) {
|
||||
rcu_read_unlock();
|
||||
err = 0;
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
ndwords = 0;
|
||||
dw = 0;
|
||||
@@ -1373,7 +1357,7 @@ static int igt_ctx_readonly(void *arg)
|
||||
if (IS_ERR(obj)) {
|
||||
err = PTR_ERR(obj);
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
if (prandom_u32_state(&prng) & 1)
|
||||
@@ -1384,15 +1368,17 @@ static int igt_ctx_readonly(void *arg)
|
||||
if (err) {
|
||||
pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n",
|
||||
ndwords, dw, max_dwords(obj),
|
||||
ce->engine->name, yesno(!!ctx->vm), err);
|
||||
ce->engine->name,
|
||||
yesno(!!rcu_access_pointer(ctx->vm)),
|
||||
err);
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
err = throttle(ce, tq, ARRAY_SIZE(tq));
|
||||
if (err) {
|
||||
i915_gem_context_unlock_engines(ctx);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
if (++dw == max_dwords(obj)) {
|
||||
@@ -1424,20 +1410,19 @@ static int igt_ctx_readonly(void *arg)
|
||||
dw += rem;
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
out_file:
|
||||
throttle_release(tq, ARRAY_SIZE(tq));
|
||||
if (igt_live_test_end(&t))
|
||||
err = -EIO;
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
mock_file_free(i915, file);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int check_scratch(struct i915_gem_context *ctx, u64 offset)
|
||||
static int check_scratch(struct i915_address_space *vm, u64 offset)
|
||||
{
|
||||
struct drm_mm_node *node =
|
||||
__drm_mm_interval_first(&ctx->vm->mm,
|
||||
__drm_mm_interval_first(&vm->mm,
|
||||
offset, offset + sizeof(u32) - 1);
|
||||
if (!node || node->start > offset)
|
||||
return 0;
|
||||
@@ -1455,6 +1440,7 @@ static int write_to_scratch(struct i915_gem_context *ctx,
|
||||
{
|
||||
struct drm_i915_private *i915 = ctx->i915;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_address_space *vm;
|
||||
struct i915_request *rq;
|
||||
struct i915_vma *vma;
|
||||
u32 *cmd;
|
||||
@@ -1487,17 +1473,18 @@ static int write_to_scratch(struct i915_gem_context *ctx,
|
||||
|
||||
intel_gt_chipset_flush(engine->gt);
|
||||
|
||||
vma = i915_vma_instance(obj, ctx->vm, NULL);
|
||||
vm = i915_gem_context_get_vm_rcu(ctx);
|
||||
vma = i915_vma_instance(obj, vm, NULL);
|
||||
if (IS_ERR(vma)) {
|
||||
err = PTR_ERR(vma);
|
||||
goto err;
|
||||
goto err_vm;
|
||||
}
|
||||
|
||||
err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED);
|
||||
if (err)
|
||||
goto err;
|
||||
goto err_vm;
|
||||
|
||||
err = check_scratch(ctx, offset);
|
||||
err = check_scratch(vm, offset);
|
||||
if (err)
|
||||
goto err_unpin;
|
||||
|
||||
@@ -1523,6 +1510,7 @@ static int write_to_scratch(struct i915_gem_context *ctx,
|
||||
|
||||
i915_request_add(rq);
|
||||
|
||||
i915_vm_put(vm);
|
||||
return 0;
|
||||
|
||||
skip_request:
|
||||
@@ -1531,6 +1519,8 @@ err_request:
|
||||
i915_request_add(rq);
|
||||
err_unpin:
|
||||
i915_vma_unpin(vma);
|
||||
err_vm:
|
||||
i915_vm_put(vm);
|
||||
err:
|
||||
i915_gem_object_put(obj);
|
||||
return err;
|
||||
@@ -1542,6 +1532,7 @@ static int read_from_scratch(struct i915_gem_context *ctx,
|
||||
{
|
||||
struct drm_i915_private *i915 = ctx->i915;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_address_space *vm;
|
||||
const u32 RCS_GPR0 = 0x2600; /* not all engines have their own GPR! */
|
||||
const u32 result = 0x100;
|
||||
struct i915_request *rq;
|
||||
@@ -1586,17 +1577,18 @@ static int read_from_scratch(struct i915_gem_context *ctx,
|
||||
|
||||
intel_gt_chipset_flush(engine->gt);
|
||||
|
||||
vma = i915_vma_instance(obj, ctx->vm, NULL);
|
||||
vm = i915_gem_context_get_vm_rcu(ctx);
|
||||
vma = i915_vma_instance(obj, vm, NULL);
|
||||
if (IS_ERR(vma)) {
|
||||
err = PTR_ERR(vma);
|
||||
goto err;
|
||||
goto err_vm;
|
||||
}
|
||||
|
||||
err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_OFFSET_FIXED);
|
||||
if (err)
|
||||
goto err;
|
||||
goto err_vm;
|
||||
|
||||
err = check_scratch(ctx, offset);
|
||||
err = check_scratch(vm, offset);
|
||||
if (err)
|
||||
goto err_unpin;
|
||||
|
||||
@@ -1627,12 +1619,12 @@ static int read_from_scratch(struct i915_gem_context *ctx,
|
||||
err = i915_gem_object_set_to_cpu_domain(obj, false);
|
||||
i915_gem_object_unlock(obj);
|
||||
if (err)
|
||||
goto err;
|
||||
goto err_vm;
|
||||
|
||||
cmd = i915_gem_object_pin_map(obj, I915_MAP_WB);
|
||||
if (IS_ERR(cmd)) {
|
||||
err = PTR_ERR(cmd);
|
||||
goto err;
|
||||
goto err_vm;
|
||||
}
|
||||
|
||||
*value = cmd[result / sizeof(*cmd)];
|
||||
@@ -1647,6 +1639,8 @@ err_request:
|
||||
i915_request_add(rq);
|
||||
err_unpin:
|
||||
i915_vma_unpin(vma);
|
||||
err_vm:
|
||||
i915_vm_put(vm);
|
||||
err:
|
||||
i915_gem_object_put(obj);
|
||||
return err;
|
||||
@@ -1677,27 +1671,25 @@ static int igt_vm_isolation(void *arg)
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
err = igt_live_test_begin(&t, i915, __func__, "");
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
ctx_a = live_context(i915, file);
|
||||
if (IS_ERR(ctx_a)) {
|
||||
err = PTR_ERR(ctx_a);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
ctx_b = live_context(i915, file);
|
||||
if (IS_ERR(ctx_b)) {
|
||||
err = PTR_ERR(ctx_b);
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
/* We can only test vm isolation, if the vm are distinct */
|
||||
if (ctx_a->vm == ctx_b->vm)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
vm_total = ctx_a->vm->total;
|
||||
GEM_BUG_ON(ctx_b->vm->total != vm_total);
|
||||
@@ -1726,7 +1718,7 @@ static int igt_vm_isolation(void *arg)
|
||||
err = read_from_scratch(ctx_b, engine,
|
||||
offset, &value);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
|
||||
if (value) {
|
||||
pr_err("%s: Read %08x from scratch (offset 0x%08x_%08x), after %lu reads!\n",
|
||||
@@ -1735,7 +1727,7 @@ static int igt_vm_isolation(void *arg)
|
||||
lower_32_bits(offset),
|
||||
this);
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
goto out_file;
|
||||
}
|
||||
|
||||
this++;
|
||||
@@ -1745,11 +1737,9 @@ static int igt_vm_isolation(void *arg)
|
||||
pr_info("Checked %lu scratch offsets across %d engines\n",
|
||||
count, RUNTIME_INFO(i915)->num_engines);
|
||||
|
||||
out_unlock:
|
||||
out_file:
|
||||
if (igt_live_test_end(&t))
|
||||
err = -EIO;
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
|
||||
mock_file_free(i915, file);
|
||||
return err;
|
||||
}
|
||||
@@ -1781,13 +1771,9 @@ static int mock_context_barrier(void *arg)
|
||||
* a request; useful for retiring old state after loading new.
|
||||
*/
|
||||
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
ctx = mock_context(i915, "mock");
|
||||
if (!ctx) {
|
||||
err = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
counter = 0;
|
||||
err = context_barrier_task(ctx, 0,
|
||||
@@ -1860,8 +1846,6 @@ static int mock_context_barrier(void *arg)
|
||||
|
||||
out:
|
||||
mock_context_close(ctx);
|
||||
unlock:
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
return err;
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(x) x
|
||||
|
||||
@@ -42,7 +42,10 @@ mock_context(struct drm_i915_private *i915,
|
||||
if (!ppgtt)
|
||||
goto err_put;
|
||||
|
||||
mutex_lock(&ctx->mutex);
|
||||
__set_ppgtt(ctx, &ppgtt->vm);
|
||||
mutex_unlock(&ctx->mutex);
|
||||
|
||||
i915_vm_put(&ppgtt->vm);
|
||||
}
|
||||
|
||||
@@ -65,7 +68,7 @@ void mock_context_close(struct i915_gem_context *ctx)
|
||||
|
||||
void mock_init_contexts(struct drm_i915_private *i915)
|
||||
{
|
||||
init_contexts(i915);
|
||||
init_contexts(&i915->gem.contexts);
|
||||
}
|
||||
|
||||
struct i915_gem_context *
|
||||
@@ -74,8 +77,6 @@ live_context(struct drm_i915_private *i915, struct drm_file *file)
|
||||
struct i915_gem_context *ctx;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&i915->drm.struct_mutex);
|
||||
|
||||
ctx = i915_gem_create_context(i915, 0);
|
||||
if (IS_ERR(ctx))
|
||||
return ctx;
|
||||
|
||||
Reference in New Issue
Block a user