1 /*
2  * SPDX-License-Identifier: MIT
3  *
4  * Copyright © 2016 Intel Corporation
5  */
6 
7 #include "i915_file_private.h"
8 #include "mock_context.h"
9 #include "selftests/mock_drm.h"
10 #include "selftests/mock_gtt.h"
11 
12 struct i915_gem_context *
13 mock_context(struct drm_i915_private *i915,
14 	     const char *name)
15 {
16 	struct i915_gem_context *ctx;
17 	struct i915_gem_engines *e;
18 	struct intel_sseu null_sseu = {};
19 
20 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
21 	if (!ctx)
22 		return NULL;
23 
24 	kref_init(&ctx->ref);
25 	INIT_LIST_HEAD(&ctx->link);
26 	ctx->i915 = i915;
27 	INIT_WORK(&ctx->release_work, i915_gem_context_release_work);
28 
29 	mutex_init(&ctx->mutex);
30 
31 	spin_lock_init(&ctx->stale.lock);
32 	INIT_LIST_HEAD(&ctx->stale.engines);
33 
34 	i915_gem_context_set_persistence(ctx);
35 
36 	if (name) {
37 		struct i915_ppgtt *ppgtt;
38 
39 		strncpy(ctx->name, name, sizeof(ctx->name) - 1);
40 
41 		ppgtt = mock_ppgtt(i915, name);
42 		if (!ppgtt)
43 			goto err_free;
44 
45 		ctx->vm = i915_vm_open(&ppgtt->vm);
46 		i915_vm_put(&ppgtt->vm);
47 	}
48 
49 	mutex_init(&ctx->engines_mutex);
50 	e = default_engines(ctx, null_sseu);
51 	if (IS_ERR(e))
52 		goto err_vm;
53 	RCU_INIT_POINTER(ctx->engines, e);
54 
55 	INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL);
56 	mutex_init(&ctx->lut_mutex);
57 
58 	return ctx;
59 
60 err_vm:
61 	if (ctx->vm)
62 		i915_vm_close(ctx->vm);
63 err_free:
64 	kfree(ctx);
65 	return NULL;
66 }
67 
68 void mock_context_close(struct i915_gem_context *ctx)
69 {
70 	context_close(ctx);
71 }
72 
73 void mock_init_contexts(struct drm_i915_private *i915)
74 {
75 	init_contexts(&i915->gem.contexts);
76 }
77 
78 struct i915_gem_context *
79 live_context(struct drm_i915_private *i915, struct file *file)
80 {
81 	struct drm_i915_file_private *fpriv = to_drm_file(file)->driver_priv;
82 	struct i915_gem_proto_context *pc;
83 	struct i915_gem_context *ctx;
84 	int err;
85 	u32 id;
86 
87 	pc = proto_context_create(i915, 0);
88 	if (IS_ERR(pc))
89 		return ERR_CAST(pc);
90 
91 	ctx = i915_gem_create_context(i915, pc);
92 	proto_context_close(i915, pc);
93 	if (IS_ERR(ctx))
94 		return ctx;
95 
96 	i915_gem_context_set_no_error_capture(ctx);
97 
98 	err = xa_alloc(&fpriv->context_xa, &id, NULL, xa_limit_32b, GFP_KERNEL);
99 	if (err < 0)
100 		goto err_ctx;
101 
102 	gem_context_register(ctx, fpriv, id);
103 
104 	return ctx;
105 
106 err_ctx:
107 	context_close(ctx);
108 	return ERR_PTR(err);
109 }
110 
111 struct i915_gem_context *
112 live_context_for_engine(struct intel_engine_cs *engine, struct file *file)
113 {
114 	struct i915_gem_engines *engines;
115 	struct i915_gem_context *ctx;
116 	struct intel_sseu null_sseu = {};
117 	struct intel_context *ce;
118 
119 	engines = alloc_engines(1);
120 	if (!engines)
121 		return ERR_PTR(-ENOMEM);
122 
123 	ctx = live_context(engine->i915, file);
124 	if (IS_ERR(ctx)) {
125 		__free_engines(engines, 0);
126 		return ctx;
127 	}
128 
129 	ce = intel_context_create(engine);
130 	if (IS_ERR(ce)) {
131 		__free_engines(engines, 0);
132 		return ERR_CAST(ce);
133 	}
134 
135 	intel_context_set_gem(ce, ctx, null_sseu);
136 	engines->engines[0] = ce;
137 	engines->num_engines = 1;
138 
139 	mutex_lock(&ctx->engines_mutex);
140 	i915_gem_context_set_user_engines(ctx);
141 	engines = rcu_replace_pointer(ctx->engines, engines, 1);
142 	mutex_unlock(&ctx->engines_mutex);
143 
144 	engines_idle_release(ctx, engines);
145 
146 	return ctx;
147 }
148 
149 struct i915_gem_context *
150 kernel_context(struct drm_i915_private *i915,
151 	       struct i915_address_space *vm)
152 {
153 	struct i915_gem_context *ctx;
154 	struct i915_gem_proto_context *pc;
155 
156 	pc = proto_context_create(i915, 0);
157 	if (IS_ERR(pc))
158 		return ERR_CAST(pc);
159 
160 	if (vm) {
161 		if (pc->vm)
162 			i915_vm_put(pc->vm);
163 		pc->vm = i915_vm_get(vm);
164 	}
165 
166 	ctx = i915_gem_create_context(i915, pc);
167 	proto_context_close(i915, pc);
168 	if (IS_ERR(ctx))
169 		return ctx;
170 
171 	i915_gem_context_clear_bannable(ctx);
172 	i915_gem_context_set_persistence(ctx);
173 	i915_gem_context_set_no_error_capture(ctx);
174 
175 	return ctx;
176 }
177 
178 void kernel_context_close(struct i915_gem_context *ctx)
179 {
180 	context_close(ctx);
181 }
182