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(size: sizeof(*ctx), GFP_KERNEL); |
21 | if (!ctx) |
22 | return NULL; |
23 | |
24 | kref_init(kref: &ctx->ref); |
25 | INIT_LIST_HEAD(list: &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(list: &ctx->stale.engines); |
33 | |
34 | i915_gem_context_set_persistence(ctx); |
35 | |
36 | if (name) { |
37 | struct i915_ppgtt *ppgtt; |
38 | |
39 | strscpy(ctx->name, name, sizeof(ctx->name)); |
40 | |
41 | ppgtt = mock_ppgtt(i915, name); |
42 | if (!ppgtt) |
43 | goto err_free; |
44 | |
45 | ctx->vm = &ppgtt->vm; |
46 | } |
47 | |
48 | mutex_init(&ctx->engines_mutex); |
49 | e = default_engines(ctx, rcs_sseu: null_sseu); |
50 | if (IS_ERR(ptr: e)) |
51 | goto err_vm; |
52 | RCU_INIT_POINTER(ctx->engines, e); |
53 | |
54 | INIT_RADIX_TREE(&ctx->handles_vma, GFP_KERNEL); |
55 | mutex_init(&ctx->lut_mutex); |
56 | |
57 | return ctx; |
58 | |
59 | err_vm: |
60 | if (ctx->vm) |
61 | i915_vm_put(vm: ctx->vm); |
62 | err_free: |
63 | kfree(objp: ctx); |
64 | return NULL; |
65 | } |
66 | |
67 | void mock_context_close(struct i915_gem_context *ctx) |
68 | { |
69 | context_close(ctx); |
70 | } |
71 | |
72 | void mock_init_contexts(struct drm_i915_private *i915) |
73 | { |
74 | init_contexts(gc: &i915->gem.contexts); |
75 | } |
76 | |
77 | struct i915_gem_context * |
78 | live_context(struct drm_i915_private *i915, struct file *file) |
79 | { |
80 | struct drm_i915_file_private *fpriv = to_drm_file(f: file)->driver_priv; |
81 | struct i915_gem_proto_context *pc; |
82 | struct i915_gem_context *ctx; |
83 | int err; |
84 | u32 id; |
85 | |
86 | pc = proto_context_create(fpriv, i915, flags: 0); |
87 | if (IS_ERR(ptr: pc)) |
88 | return ERR_CAST(ptr: pc); |
89 | |
90 | ctx = i915_gem_create_context(i915, pc); |
91 | proto_context_close(i915, pc); |
92 | if (IS_ERR(ptr: ctx)) |
93 | return ctx; |
94 | |
95 | i915_gem_context_set_no_error_capture(ctx); |
96 | |
97 | err = xa_alloc(xa: &fpriv->context_xa, id: &id, NULL, xa_limit_32b, GFP_KERNEL); |
98 | if (err < 0) |
99 | goto err_ctx; |
100 | |
101 | gem_context_register(ctx, fpriv, id); |
102 | |
103 | return ctx; |
104 | |
105 | err_ctx: |
106 | context_close(ctx); |
107 | return ERR_PTR(error: err); |
108 | } |
109 | |
110 | struct i915_gem_context * |
111 | live_context_for_engine(struct intel_engine_cs *engine, struct file *file) |
112 | { |
113 | struct i915_gem_engines *engines; |
114 | struct i915_gem_context *ctx; |
115 | struct intel_sseu null_sseu = {}; |
116 | struct intel_context *ce; |
117 | |
118 | engines = alloc_engines(count: 1); |
119 | if (!engines) |
120 | return ERR_PTR(error: -ENOMEM); |
121 | |
122 | ctx = live_context(i915: engine->i915, file); |
123 | if (IS_ERR(ptr: ctx)) { |
124 | __free_engines(e: engines, count: 0); |
125 | return ctx; |
126 | } |
127 | |
128 | ce = intel_context_create(engine); |
129 | if (IS_ERR(ptr: ce)) { |
130 | __free_engines(e: engines, count: 0); |
131 | return ERR_CAST(ptr: ce); |
132 | } |
133 | |
134 | intel_context_set_gem(ce, ctx, sseu: null_sseu); |
135 | engines->engines[0] = ce; |
136 | engines->num_engines = 1; |
137 | |
138 | mutex_lock(&ctx->engines_mutex); |
139 | i915_gem_context_set_user_engines(ctx); |
140 | engines = rcu_replace_pointer(ctx->engines, engines, 1); |
141 | mutex_unlock(lock: &ctx->engines_mutex); |
142 | |
143 | engines_idle_release(ctx, engines); |
144 | |
145 | return ctx; |
146 | } |
147 | |
148 | struct i915_gem_context * |
149 | kernel_context(struct drm_i915_private *i915, |
150 | struct i915_address_space *vm) |
151 | { |
152 | struct i915_gem_context *ctx; |
153 | struct i915_gem_proto_context *pc; |
154 | |
155 | pc = proto_context_create(NULL, i915, flags: 0); |
156 | if (IS_ERR(ptr: pc)) |
157 | return ERR_CAST(ptr: pc); |
158 | |
159 | if (vm) { |
160 | if (pc->vm) |
161 | i915_vm_put(vm: pc->vm); |
162 | pc->vm = i915_vm_get(vm); |
163 | } |
164 | |
165 | ctx = i915_gem_create_context(i915, pc); |
166 | proto_context_close(i915, pc); |
167 | if (IS_ERR(ptr: ctx)) |
168 | return ctx; |
169 | |
170 | i915_gem_context_clear_bannable(ctx); |
171 | i915_gem_context_set_persistence(ctx); |
172 | i915_gem_context_set_no_error_capture(ctx); |
173 | |
174 | return ctx; |
175 | } |
176 | |
177 | void kernel_context_close(struct i915_gem_context *ctx) |
178 | { |
179 | context_close(ctx); |
180 | } |
181 | |