/* * SPDX-License-Identifier: MIT * * Copyright © 2016 Intel Corporation */ #include "i915_file_private.h" #include "mock_context.h" #include "selftests/mock_drm.h" #include "selftests/mock_gtt.h" struct i915_gem_context * mock_context(struct drm_i915_private *i915, const char *name) { struct i915_gem_context *ctx; struct i915_gem_engines *e; struct intel_sseu null_sseu = {}; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return NULL; kref_init(&ctx->ref); INIT_LIST_HEAD(&ctx->link); ctx->i915 = i915; INIT_WORK(&ctx->release_work, i915_gem_context_release_work); mutex_init(&ctx->mutex); spin_lock_init(&ctx->stale.lock); INIT_LIST_HEAD(&ctx->stale.engines); i915_gem_context_set_persistence(ctx); if (name) { struct i915_ppgtt *ppgtt; strscpy(ctx->name, name, sizeof(ctx->name)); ppgtt = mock_ppgtt(i915, name); if (!ppgtt) goto err_free; ctx->vm = &ppgtt->vm; } mutex_init(&ctx->engines_mutex); e = default_engines(ctx, null_sseu); if (IS_ERR(e)) goto err_vm; RCU_INIT_POINTER(ctx->engines, e); INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); mutex_init(&ctx->lut_mutex); return ctx; err_vm: if (ctx->vm) i915_vm_put(ctx->vm); err_free: kfree(ctx); return NULL; } void mock_context_close(struct i915_gem_context *ctx) { context_close(ctx); } void mock_init_contexts(struct drm_i915_private *i915) { init_contexts(&i915->gem.contexts); } struct i915_gem_context * live_context(struct drm_i915_private *i915, struct file *file) { struct drm_i915_file_private *fpriv = to_drm_file(file)->driver_priv; struct i915_gem_proto_context *pc; struct i915_gem_context *ctx; int err; u32 id; pc = proto_context_create(fpriv, i915, 0); if (IS_ERR(pc)) return ERR_CAST(pc); ctx = i915_gem_create_context(i915, pc); proto_context_close(i915, pc); if (IS_ERR(ctx)) return ctx; i915_gem_context_set_no_error_capture(ctx); err = xa_alloc(&fpriv->context_xa, &id, NULL, xa_limit_32b, GFP_KERNEL); if (err < 0) goto err_ctx; gem_context_register(ctx, fpriv, id); return ctx; err_ctx: context_close(ctx); return ERR_PTR(err); } struct i915_gem_context * live_context_for_engine(struct intel_engine_cs *engine, struct file *file) { struct i915_gem_engines *engines; struct i915_gem_context *ctx; struct intel_sseu null_sseu = {}; struct intel_context *ce; engines = alloc_engines(1); if (!engines) return ERR_PTR(-ENOMEM); ctx = live_context(engine->i915, file); if (IS_ERR(ctx)) { __free_engines(engines, 0); return ctx; } ce = intel_context_create(engine); if (IS_ERR(ce)) { __free_engines(engines, 0); return ERR_CAST(ce); } intel_context_set_gem(ce, ctx, null_sseu); engines->engines[0] = ce; engines->num_engines = 1; mutex_lock(&ctx->engines_mutex); i915_gem_context_set_user_engines(ctx); engines = rcu_replace_pointer(ctx->engines, engines, 1); mutex_unlock(&ctx->engines_mutex); engines_idle_release(ctx, engines); return ctx; } struct i915_gem_context * kernel_context(struct drm_i915_private *i915, struct i915_address_space *vm) { struct i915_gem_context *ctx; struct i915_gem_proto_context *pc; pc = proto_context_create(NULL, i915, 0); if (IS_ERR(pc)) return ERR_CAST(pc); if (vm) { if (pc->vm) i915_vm_put(pc->vm); pc->vm = i915_vm_get(vm); } ctx = i915_gem_create_context(i915, pc); proto_context_close(i915, pc); if (IS_ERR(ctx)) return ctx; i915_gem_context_clear_bannable(ctx); i915_gem_context_set_persistence(ctx); i915_gem_context_set_no_error_capture(ctx); return ctx; } void kernel_context_close(struct i915_gem_context *ctx) { context_close(ctx); }