1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2018-2019 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker */
23*d83cc019SAndroid Build Coastguard Worker
24*d83cc019SAndroid Build Coastguard Worker #include <sched.h>
25*d83cc019SAndroid Build Coastguard Worker
26*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
27*d83cc019SAndroid Build Coastguard Worker #include "igt_perf.h"
28*d83cc019SAndroid Build Coastguard Worker #include "i915/gem_ring.h"
29*d83cc019SAndroid Build Coastguard Worker #include "sw_sync.h"
30*d83cc019SAndroid Build Coastguard Worker
31*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Exercise in-kernel load-balancing");
32*d83cc019SAndroid Build Coastguard Worker
33*d83cc019SAndroid Build Coastguard Worker #define INSTANCE_COUNT (1 << I915_PMU_SAMPLE_INSTANCE_BITS)
34*d83cc019SAndroid Build Coastguard Worker
sizeof_load_balance(int count)35*d83cc019SAndroid Build Coastguard Worker static size_t sizeof_load_balance(int count)
36*d83cc019SAndroid Build Coastguard Worker {
37*d83cc019SAndroid Build Coastguard Worker return offsetof(struct i915_context_engines_load_balance,
38*d83cc019SAndroid Build Coastguard Worker engines[count]);
39*d83cc019SAndroid Build Coastguard Worker }
40*d83cc019SAndroid Build Coastguard Worker
sizeof_param_engines(int count)41*d83cc019SAndroid Build Coastguard Worker static size_t sizeof_param_engines(int count)
42*d83cc019SAndroid Build Coastguard Worker {
43*d83cc019SAndroid Build Coastguard Worker return offsetof(struct i915_context_param_engines,
44*d83cc019SAndroid Build Coastguard Worker engines[count]);
45*d83cc019SAndroid Build Coastguard Worker }
46*d83cc019SAndroid Build Coastguard Worker
sizeof_engines_bond(int count)47*d83cc019SAndroid Build Coastguard Worker static size_t sizeof_engines_bond(int count)
48*d83cc019SAndroid Build Coastguard Worker {
49*d83cc019SAndroid Build Coastguard Worker return offsetof(struct i915_context_engines_bond,
50*d83cc019SAndroid Build Coastguard Worker engines[count]);
51*d83cc019SAndroid Build Coastguard Worker }
52*d83cc019SAndroid Build Coastguard Worker
53*d83cc019SAndroid Build Coastguard Worker #define alloca0(sz) ({ size_t sz__ = (sz); memset(alloca(sz__), 0, sz__); })
54*d83cc019SAndroid Build Coastguard Worker
has_class_instance(int i915,uint16_t class,uint16_t instance)55*d83cc019SAndroid Build Coastguard Worker static bool has_class_instance(int i915, uint16_t class, uint16_t instance)
56*d83cc019SAndroid Build Coastguard Worker {
57*d83cc019SAndroid Build Coastguard Worker int fd;
58*d83cc019SAndroid Build Coastguard Worker
59*d83cc019SAndroid Build Coastguard Worker fd = perf_i915_open(I915_PMU_ENGINE_BUSY(class, instance));
60*d83cc019SAndroid Build Coastguard Worker if (fd != -1) {
61*d83cc019SAndroid Build Coastguard Worker close(fd);
62*d83cc019SAndroid Build Coastguard Worker return true;
63*d83cc019SAndroid Build Coastguard Worker }
64*d83cc019SAndroid Build Coastguard Worker
65*d83cc019SAndroid Build Coastguard Worker return false;
66*d83cc019SAndroid Build Coastguard Worker }
67*d83cc019SAndroid Build Coastguard Worker
68*d83cc019SAndroid Build Coastguard Worker static struct i915_engine_class_instance *
list_engines(int i915,uint32_t class_mask,unsigned int * out)69*d83cc019SAndroid Build Coastguard Worker list_engines(int i915, uint32_t class_mask, unsigned int *out)
70*d83cc019SAndroid Build Coastguard Worker {
71*d83cc019SAndroid Build Coastguard Worker unsigned int count = 0, size = 64;
72*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *engines;
73*d83cc019SAndroid Build Coastguard Worker
74*d83cc019SAndroid Build Coastguard Worker engines = malloc(size * sizeof(*engines));
75*d83cc019SAndroid Build Coastguard Worker igt_assert(engines);
76*d83cc019SAndroid Build Coastguard Worker
77*d83cc019SAndroid Build Coastguard Worker for (enum drm_i915_gem_engine_class class = I915_ENGINE_CLASS_RENDER;
78*d83cc019SAndroid Build Coastguard Worker class_mask;
79*d83cc019SAndroid Build Coastguard Worker class++, class_mask >>= 1) {
80*d83cc019SAndroid Build Coastguard Worker if (!(class_mask & 1))
81*d83cc019SAndroid Build Coastguard Worker continue;
82*d83cc019SAndroid Build Coastguard Worker
83*d83cc019SAndroid Build Coastguard Worker for (unsigned int instance = 0;
84*d83cc019SAndroid Build Coastguard Worker instance < INSTANCE_COUNT;
85*d83cc019SAndroid Build Coastguard Worker instance++) {
86*d83cc019SAndroid Build Coastguard Worker if (!has_class_instance(i915, class, instance))
87*d83cc019SAndroid Build Coastguard Worker continue;
88*d83cc019SAndroid Build Coastguard Worker
89*d83cc019SAndroid Build Coastguard Worker if (count == size) {
90*d83cc019SAndroid Build Coastguard Worker size *= 2;
91*d83cc019SAndroid Build Coastguard Worker engines = realloc(engines,
92*d83cc019SAndroid Build Coastguard Worker size * sizeof(*engines));
93*d83cc019SAndroid Build Coastguard Worker igt_assert(engines);
94*d83cc019SAndroid Build Coastguard Worker }
95*d83cc019SAndroid Build Coastguard Worker
96*d83cc019SAndroid Build Coastguard Worker engines[count++] = (struct i915_engine_class_instance){
97*d83cc019SAndroid Build Coastguard Worker .engine_class = class,
98*d83cc019SAndroid Build Coastguard Worker .engine_instance = instance,
99*d83cc019SAndroid Build Coastguard Worker };
100*d83cc019SAndroid Build Coastguard Worker }
101*d83cc019SAndroid Build Coastguard Worker }
102*d83cc019SAndroid Build Coastguard Worker
103*d83cc019SAndroid Build Coastguard Worker if (!count) {
104*d83cc019SAndroid Build Coastguard Worker free(engines);
105*d83cc019SAndroid Build Coastguard Worker engines = NULL;
106*d83cc019SAndroid Build Coastguard Worker }
107*d83cc019SAndroid Build Coastguard Worker
108*d83cc019SAndroid Build Coastguard Worker *out = count;
109*d83cc019SAndroid Build Coastguard Worker return engines;
110*d83cc019SAndroid Build Coastguard Worker }
111*d83cc019SAndroid Build Coastguard Worker
__set_engines(int i915,uint32_t ctx,const struct i915_engine_class_instance * ci,unsigned int count)112*d83cc019SAndroid Build Coastguard Worker static int __set_engines(int i915, uint32_t ctx,
113*d83cc019SAndroid Build Coastguard Worker const struct i915_engine_class_instance *ci,
114*d83cc019SAndroid Build Coastguard Worker unsigned int count)
115*d83cc019SAndroid Build Coastguard Worker {
116*d83cc019SAndroid Build Coastguard Worker struct i915_context_param_engines *engines =
117*d83cc019SAndroid Build Coastguard Worker alloca0(sizeof_param_engines(count));
118*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_context_param p = {
119*d83cc019SAndroid Build Coastguard Worker .ctx_id = ctx,
120*d83cc019SAndroid Build Coastguard Worker .param = I915_CONTEXT_PARAM_ENGINES,
121*d83cc019SAndroid Build Coastguard Worker .size = sizeof_param_engines(count),
122*d83cc019SAndroid Build Coastguard Worker .value = to_user_pointer(engines)
123*d83cc019SAndroid Build Coastguard Worker };
124*d83cc019SAndroid Build Coastguard Worker
125*d83cc019SAndroid Build Coastguard Worker engines->extensions = 0;
126*d83cc019SAndroid Build Coastguard Worker memcpy(engines->engines, ci, count * sizeof(*ci));
127*d83cc019SAndroid Build Coastguard Worker
128*d83cc019SAndroid Build Coastguard Worker return __gem_context_set_param(i915, &p);
129*d83cc019SAndroid Build Coastguard Worker }
130*d83cc019SAndroid Build Coastguard Worker
set_engines(int i915,uint32_t ctx,const struct i915_engine_class_instance * ci,unsigned int count)131*d83cc019SAndroid Build Coastguard Worker static void set_engines(int i915, uint32_t ctx,
132*d83cc019SAndroid Build Coastguard Worker const struct i915_engine_class_instance *ci,
133*d83cc019SAndroid Build Coastguard Worker unsigned int count)
134*d83cc019SAndroid Build Coastguard Worker {
135*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__set_engines(i915, ctx, ci, count), 0);
136*d83cc019SAndroid Build Coastguard Worker }
137*d83cc019SAndroid Build Coastguard Worker
__set_load_balancer(int i915,uint32_t ctx,const struct i915_engine_class_instance * ci,unsigned int count,void * ext)138*d83cc019SAndroid Build Coastguard Worker static int __set_load_balancer(int i915, uint32_t ctx,
139*d83cc019SAndroid Build Coastguard Worker const struct i915_engine_class_instance *ci,
140*d83cc019SAndroid Build Coastguard Worker unsigned int count,
141*d83cc019SAndroid Build Coastguard Worker void *ext)
142*d83cc019SAndroid Build Coastguard Worker {
143*d83cc019SAndroid Build Coastguard Worker struct i915_context_engines_load_balance *balancer =
144*d83cc019SAndroid Build Coastguard Worker alloca0(sizeof_load_balance(count));
145*d83cc019SAndroid Build Coastguard Worker struct i915_context_param_engines *engines =
146*d83cc019SAndroid Build Coastguard Worker alloca0(sizeof_param_engines(count + 1));
147*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_context_param p = {
148*d83cc019SAndroid Build Coastguard Worker .ctx_id = ctx,
149*d83cc019SAndroid Build Coastguard Worker .param = I915_CONTEXT_PARAM_ENGINES,
150*d83cc019SAndroid Build Coastguard Worker .size = sizeof_param_engines(count + 1),
151*d83cc019SAndroid Build Coastguard Worker .value = to_user_pointer(engines)
152*d83cc019SAndroid Build Coastguard Worker };
153*d83cc019SAndroid Build Coastguard Worker
154*d83cc019SAndroid Build Coastguard Worker balancer->base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE;
155*d83cc019SAndroid Build Coastguard Worker balancer->base.next_extension = to_user_pointer(ext);
156*d83cc019SAndroid Build Coastguard Worker
157*d83cc019SAndroid Build Coastguard Worker igt_assert(count);
158*d83cc019SAndroid Build Coastguard Worker balancer->num_siblings = count;
159*d83cc019SAndroid Build Coastguard Worker memcpy(balancer->engines, ci, count * sizeof(*ci));
160*d83cc019SAndroid Build Coastguard Worker
161*d83cc019SAndroid Build Coastguard Worker engines->extensions = to_user_pointer(balancer);
162*d83cc019SAndroid Build Coastguard Worker engines->engines[0].engine_class =
163*d83cc019SAndroid Build Coastguard Worker I915_ENGINE_CLASS_INVALID;
164*d83cc019SAndroid Build Coastguard Worker engines->engines[0].engine_instance =
165*d83cc019SAndroid Build Coastguard Worker I915_ENGINE_CLASS_INVALID_NONE;
166*d83cc019SAndroid Build Coastguard Worker memcpy(engines->engines + 1, ci, count * sizeof(*ci));
167*d83cc019SAndroid Build Coastguard Worker
168*d83cc019SAndroid Build Coastguard Worker return __gem_context_set_param(i915, &p);
169*d83cc019SAndroid Build Coastguard Worker }
170*d83cc019SAndroid Build Coastguard Worker
set_load_balancer(int i915,uint32_t ctx,const struct i915_engine_class_instance * ci,unsigned int count,void * ext)171*d83cc019SAndroid Build Coastguard Worker static void set_load_balancer(int i915, uint32_t ctx,
172*d83cc019SAndroid Build Coastguard Worker const struct i915_engine_class_instance *ci,
173*d83cc019SAndroid Build Coastguard Worker unsigned int count,
174*d83cc019SAndroid Build Coastguard Worker void *ext)
175*d83cc019SAndroid Build Coastguard Worker {
176*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__set_load_balancer(i915, ctx, ci, count, ext), 0);
177*d83cc019SAndroid Build Coastguard Worker }
178*d83cc019SAndroid Build Coastguard Worker
load_balancer_create(int i915,const struct i915_engine_class_instance * ci,unsigned int count)179*d83cc019SAndroid Build Coastguard Worker static uint32_t load_balancer_create(int i915,
180*d83cc019SAndroid Build Coastguard Worker const struct i915_engine_class_instance *ci,
181*d83cc019SAndroid Build Coastguard Worker unsigned int count)
182*d83cc019SAndroid Build Coastguard Worker {
183*d83cc019SAndroid Build Coastguard Worker uint32_t ctx;
184*d83cc019SAndroid Build Coastguard Worker
185*d83cc019SAndroid Build Coastguard Worker ctx = gem_context_create(i915);
186*d83cc019SAndroid Build Coastguard Worker set_load_balancer(i915, ctx, ci, count, NULL);
187*d83cc019SAndroid Build Coastguard Worker
188*d83cc019SAndroid Build Coastguard Worker return ctx;
189*d83cc019SAndroid Build Coastguard Worker }
190*d83cc019SAndroid Build Coastguard Worker
__batch_create(int i915,uint32_t offset)191*d83cc019SAndroid Build Coastguard Worker static uint32_t __batch_create(int i915, uint32_t offset)
192*d83cc019SAndroid Build Coastguard Worker {
193*d83cc019SAndroid Build Coastguard Worker const uint32_t bbe = MI_BATCH_BUFFER_END;
194*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
195*d83cc019SAndroid Build Coastguard Worker
196*d83cc019SAndroid Build Coastguard Worker handle = gem_create(i915, ALIGN(offset + 4, 4096));
197*d83cc019SAndroid Build Coastguard Worker gem_write(i915, handle, offset, &bbe, sizeof(bbe));
198*d83cc019SAndroid Build Coastguard Worker
199*d83cc019SAndroid Build Coastguard Worker return handle;
200*d83cc019SAndroid Build Coastguard Worker }
201*d83cc019SAndroid Build Coastguard Worker
batch_create(int i915)202*d83cc019SAndroid Build Coastguard Worker static uint32_t batch_create(int i915)
203*d83cc019SAndroid Build Coastguard Worker {
204*d83cc019SAndroid Build Coastguard Worker return __batch_create(i915, 0);
205*d83cc019SAndroid Build Coastguard Worker }
206*d83cc019SAndroid Build Coastguard Worker
invalid_balancer(int i915)207*d83cc019SAndroid Build Coastguard Worker static void invalid_balancer(int i915)
208*d83cc019SAndroid Build Coastguard Worker {
209*d83cc019SAndroid Build Coastguard Worker I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(balancer, 64);
210*d83cc019SAndroid Build Coastguard Worker I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 64);
211*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_context_param p = {
212*d83cc019SAndroid Build Coastguard Worker .param = I915_CONTEXT_PARAM_ENGINES,
213*d83cc019SAndroid Build Coastguard Worker .value = to_user_pointer(&engines)
214*d83cc019SAndroid Build Coastguard Worker };
215*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
216*d83cc019SAndroid Build Coastguard Worker void *ptr;
217*d83cc019SAndroid Build Coastguard Worker
218*d83cc019SAndroid Build Coastguard Worker /*
219*d83cc019SAndroid Build Coastguard Worker * Assume that I915_CONTEXT_PARAM_ENGINE validates the array
220*d83cc019SAndroid Build Coastguard Worker * of engines[], our job is to determine if the load_balancer
221*d83cc019SAndroid Build Coastguard Worker * extension explodes.
222*d83cc019SAndroid Build Coastguard Worker */
223*d83cc019SAndroid Build Coastguard Worker
224*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 32; class++) {
225*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
226*d83cc019SAndroid Build Coastguard Worker unsigned int count;
227*d83cc019SAndroid Build Coastguard Worker
228*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1 << class, &count);
229*d83cc019SAndroid Build Coastguard Worker if (!ci)
230*d83cc019SAndroid Build Coastguard Worker continue;
231*d83cc019SAndroid Build Coastguard Worker
232*d83cc019SAndroid Build Coastguard Worker igt_assert_lte(count, 64);
233*d83cc019SAndroid Build Coastguard Worker
234*d83cc019SAndroid Build Coastguard Worker p.ctx_id = gem_context_create(i915);
235*d83cc019SAndroid Build Coastguard Worker p.size = (sizeof(struct i915_context_param_engines) +
236*d83cc019SAndroid Build Coastguard Worker (count + 1) * sizeof(*engines.engines));
237*d83cc019SAndroid Build Coastguard Worker
238*d83cc019SAndroid Build Coastguard Worker memset(&engines, 0, sizeof(engines));
239*d83cc019SAndroid Build Coastguard Worker engines.engines[0].engine_class = I915_ENGINE_CLASS_INVALID;
240*d83cc019SAndroid Build Coastguard Worker engines.engines[0].engine_instance = I915_ENGINE_CLASS_INVALID_NONE;
241*d83cc019SAndroid Build Coastguard Worker memcpy(engines.engines + 1, ci, count * sizeof(*ci));
242*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
243*d83cc019SAndroid Build Coastguard Worker
244*d83cc019SAndroid Build Coastguard Worker engines.extensions = -1ull;
245*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
246*d83cc019SAndroid Build Coastguard Worker
247*d83cc019SAndroid Build Coastguard Worker engines.extensions = 1ull;
248*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
249*d83cc019SAndroid Build Coastguard Worker
250*d83cc019SAndroid Build Coastguard Worker memset(&balancer, 0, sizeof(balancer));
251*d83cc019SAndroid Build Coastguard Worker balancer.base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE;
252*d83cc019SAndroid Build Coastguard Worker balancer.num_siblings = count;
253*d83cc019SAndroid Build Coastguard Worker memcpy(balancer.engines, ci, count * sizeof(*ci));
254*d83cc019SAndroid Build Coastguard Worker
255*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(&balancer);
256*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
257*d83cc019SAndroid Build Coastguard Worker
258*d83cc019SAndroid Build Coastguard Worker balancer.engine_index = 1;
259*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EEXIST);
260*d83cc019SAndroid Build Coastguard Worker
261*d83cc019SAndroid Build Coastguard Worker balancer.engine_index = count;
262*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EEXIST);
263*d83cc019SAndroid Build Coastguard Worker
264*d83cc019SAndroid Build Coastguard Worker balancer.engine_index = count + 1;
265*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EINVAL);
266*d83cc019SAndroid Build Coastguard Worker
267*d83cc019SAndroid Build Coastguard Worker balancer.engine_index = 0;
268*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
269*d83cc019SAndroid Build Coastguard Worker
270*d83cc019SAndroid Build Coastguard Worker balancer.base.next_extension = to_user_pointer(&balancer);
271*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EEXIST);
272*d83cc019SAndroid Build Coastguard Worker
273*d83cc019SAndroid Build Coastguard Worker balancer.base.next_extension = -1ull;
274*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
275*d83cc019SAndroid Build Coastguard Worker
276*d83cc019SAndroid Build Coastguard Worker handle = gem_create(i915, 4096 * 3);
277*d83cc019SAndroid Build Coastguard Worker ptr = gem_mmap__gtt(i915, handle, 4096 * 3, PROT_WRITE);
278*d83cc019SAndroid Build Coastguard Worker gem_close(i915, handle);
279*d83cc019SAndroid Build Coastguard Worker
280*d83cc019SAndroid Build Coastguard Worker memset(&engines, 0, sizeof(engines));
281*d83cc019SAndroid Build Coastguard Worker engines.engines[0].engine_class = I915_ENGINE_CLASS_INVALID;
282*d83cc019SAndroid Build Coastguard Worker engines.engines[0].engine_instance = I915_ENGINE_CLASS_INVALID_NONE;
283*d83cc019SAndroid Build Coastguard Worker engines.engines[1].engine_class = I915_ENGINE_CLASS_INVALID;
284*d83cc019SAndroid Build Coastguard Worker engines.engines[1].engine_instance = I915_ENGINE_CLASS_INVALID_NONE;
285*d83cc019SAndroid Build Coastguard Worker memcpy(engines.engines + 2, ci, count * sizeof(ci));
286*d83cc019SAndroid Build Coastguard Worker p.size = (sizeof(struct i915_context_param_engines) +
287*d83cc019SAndroid Build Coastguard Worker (count + 2) * sizeof(*engines.engines));
288*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
289*d83cc019SAndroid Build Coastguard Worker
290*d83cc019SAndroid Build Coastguard Worker balancer.base.next_extension = 0;
291*d83cc019SAndroid Build Coastguard Worker balancer.engine_index = 1;
292*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(&balancer);
293*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
294*d83cc019SAndroid Build Coastguard Worker
295*d83cc019SAndroid Build Coastguard Worker memcpy(ptr + 4096 - 8, &balancer, sizeof(balancer));
296*d83cc019SAndroid Build Coastguard Worker memcpy(ptr + 8192 - 8, &balancer, sizeof(balancer));
297*d83cc019SAndroid Build Coastguard Worker balancer.engine_index = 0;
298*d83cc019SAndroid Build Coastguard Worker
299*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(ptr) + 4096 - 8;
300*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
301*d83cc019SAndroid Build Coastguard Worker
302*d83cc019SAndroid Build Coastguard Worker balancer.base.next_extension = engines.extensions;
303*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(&balancer);
304*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
305*d83cc019SAndroid Build Coastguard Worker
306*d83cc019SAndroid Build Coastguard Worker munmap(ptr, 4096);
307*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
308*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(ptr) + 4096 - 8;
309*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
310*d83cc019SAndroid Build Coastguard Worker
311*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(ptr) + 8192 - 8;
312*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
313*d83cc019SAndroid Build Coastguard Worker
314*d83cc019SAndroid Build Coastguard Worker balancer.base.next_extension = engines.extensions;
315*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(&balancer);
316*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
317*d83cc019SAndroid Build Coastguard Worker
318*d83cc019SAndroid Build Coastguard Worker munmap(ptr + 8192, 4096);
319*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
320*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(ptr) + 8192 - 8;
321*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
322*d83cc019SAndroid Build Coastguard Worker
323*d83cc019SAndroid Build Coastguard Worker munmap(ptr + 4096, 4096);
324*d83cc019SAndroid Build Coastguard Worker
325*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, p.ctx_id);
326*d83cc019SAndroid Build Coastguard Worker free(ci);
327*d83cc019SAndroid Build Coastguard Worker }
328*d83cc019SAndroid Build Coastguard Worker }
329*d83cc019SAndroid Build Coastguard Worker
invalid_bonds(int i915)330*d83cc019SAndroid Build Coastguard Worker static void invalid_bonds(int i915)
331*d83cc019SAndroid Build Coastguard Worker {
332*d83cc019SAndroid Build Coastguard Worker I915_DEFINE_CONTEXT_ENGINES_BOND(bonds[16], 1);
333*d83cc019SAndroid Build Coastguard Worker I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 1);
334*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_context_param p = {
335*d83cc019SAndroid Build Coastguard Worker .ctx_id = gem_context_create(i915),
336*d83cc019SAndroid Build Coastguard Worker .param = I915_CONTEXT_PARAM_ENGINES,
337*d83cc019SAndroid Build Coastguard Worker .value = to_user_pointer(&engines),
338*d83cc019SAndroid Build Coastguard Worker .size = sizeof(engines),
339*d83cc019SAndroid Build Coastguard Worker };
340*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
341*d83cc019SAndroid Build Coastguard Worker void *ptr;
342*d83cc019SAndroid Build Coastguard Worker
343*d83cc019SAndroid Build Coastguard Worker memset(&engines, 0, sizeof(engines));
344*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
345*d83cc019SAndroid Build Coastguard Worker
346*d83cc019SAndroid Build Coastguard Worker memset(bonds, 0, sizeof(bonds));
347*d83cc019SAndroid Build Coastguard Worker for (int n = 0; n < ARRAY_SIZE(bonds); n++) {
348*d83cc019SAndroid Build Coastguard Worker bonds[n].base.name = I915_CONTEXT_ENGINES_EXT_BOND;
349*d83cc019SAndroid Build Coastguard Worker bonds[n].base.next_extension =
350*d83cc019SAndroid Build Coastguard Worker n ? to_user_pointer(&bonds[n - 1]) : 0;
351*d83cc019SAndroid Build Coastguard Worker bonds[n].num_bonds = 1;
352*d83cc019SAndroid Build Coastguard Worker }
353*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(&bonds);
354*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
355*d83cc019SAndroid Build Coastguard Worker
356*d83cc019SAndroid Build Coastguard Worker bonds[0].base.next_extension = -1ull;
357*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
358*d83cc019SAndroid Build Coastguard Worker
359*d83cc019SAndroid Build Coastguard Worker bonds[0].base.next_extension = to_user_pointer(&bonds[0]);
360*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -E2BIG);
361*d83cc019SAndroid Build Coastguard Worker
362*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(&bonds[1]);
363*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -E2BIG);
364*d83cc019SAndroid Build Coastguard Worker bonds[0].base.next_extension = 0;
365*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
366*d83cc019SAndroid Build Coastguard Worker
367*d83cc019SAndroid Build Coastguard Worker handle = gem_create(i915, 4096 * 3);
368*d83cc019SAndroid Build Coastguard Worker ptr = gem_mmap__gtt(i915, handle, 4096 * 3, PROT_WRITE);
369*d83cc019SAndroid Build Coastguard Worker gem_close(i915, handle);
370*d83cc019SAndroid Build Coastguard Worker
371*d83cc019SAndroid Build Coastguard Worker memcpy(ptr + 4096, &bonds[0], sizeof(bonds[0]));
372*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(ptr) + 4096;
373*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
374*d83cc019SAndroid Build Coastguard Worker
375*d83cc019SAndroid Build Coastguard Worker memcpy(ptr, &bonds[0], sizeof(bonds[0]));
376*d83cc019SAndroid Build Coastguard Worker bonds[0].base.next_extension = to_user_pointer(ptr);
377*d83cc019SAndroid Build Coastguard Worker memcpy(ptr + 4096, &bonds[0], sizeof(bonds[0]));
378*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
379*d83cc019SAndroid Build Coastguard Worker
380*d83cc019SAndroid Build Coastguard Worker munmap(ptr, 4096);
381*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
382*d83cc019SAndroid Build Coastguard Worker
383*d83cc019SAndroid Build Coastguard Worker bonds[0].base.next_extension = 0;
384*d83cc019SAndroid Build Coastguard Worker memcpy(ptr + 8192, &bonds[0], sizeof(bonds[0]));
385*d83cc019SAndroid Build Coastguard Worker bonds[0].base.next_extension = to_user_pointer(ptr) + 8192;
386*d83cc019SAndroid Build Coastguard Worker memcpy(ptr + 4096, &bonds[0], sizeof(bonds[0]));
387*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
388*d83cc019SAndroid Build Coastguard Worker
389*d83cc019SAndroid Build Coastguard Worker munmap(ptr + 8192, 4096);
390*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
391*d83cc019SAndroid Build Coastguard Worker
392*d83cc019SAndroid Build Coastguard Worker munmap(ptr + 4096, 4096);
393*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(__gem_context_set_param(i915, &p), -EFAULT);
394*d83cc019SAndroid Build Coastguard Worker
395*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, p.ctx_id);
396*d83cc019SAndroid Build Coastguard Worker }
397*d83cc019SAndroid Build Coastguard Worker
kick_kthreads(void)398*d83cc019SAndroid Build Coastguard Worker static void kick_kthreads(void)
399*d83cc019SAndroid Build Coastguard Worker {
400*d83cc019SAndroid Build Coastguard Worker usleep(20 * 1000); /* 20ms should be enough for ksoftirqd! */
401*d83cc019SAndroid Build Coastguard Worker }
402*d83cc019SAndroid Build Coastguard Worker
measure_load(int pmu,int period_us)403*d83cc019SAndroid Build Coastguard Worker static double measure_load(int pmu, int period_us)
404*d83cc019SAndroid Build Coastguard Worker {
405*d83cc019SAndroid Build Coastguard Worker uint64_t data[2];
406*d83cc019SAndroid Build Coastguard Worker uint64_t d_t, d_v;
407*d83cc019SAndroid Build Coastguard Worker
408*d83cc019SAndroid Build Coastguard Worker kick_kthreads();
409*d83cc019SAndroid Build Coastguard Worker
410*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data));
411*d83cc019SAndroid Build Coastguard Worker d_v = -data[0];
412*d83cc019SAndroid Build Coastguard Worker d_t = -data[1];
413*d83cc019SAndroid Build Coastguard Worker
414*d83cc019SAndroid Build Coastguard Worker usleep(period_us);
415*d83cc019SAndroid Build Coastguard Worker
416*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data));
417*d83cc019SAndroid Build Coastguard Worker d_v += data[0];
418*d83cc019SAndroid Build Coastguard Worker d_t += data[1];
419*d83cc019SAndroid Build Coastguard Worker
420*d83cc019SAndroid Build Coastguard Worker return d_v / (double)d_t;
421*d83cc019SAndroid Build Coastguard Worker }
422*d83cc019SAndroid Build Coastguard Worker
measure_min_load(int pmu,unsigned int num,int period_us)423*d83cc019SAndroid Build Coastguard Worker static double measure_min_load(int pmu, unsigned int num, int period_us)
424*d83cc019SAndroid Build Coastguard Worker {
425*d83cc019SAndroid Build Coastguard Worker uint64_t data[2 + num];
426*d83cc019SAndroid Build Coastguard Worker uint64_t d_t, d_v[num];
427*d83cc019SAndroid Build Coastguard Worker uint64_t min = -1, max = 0;
428*d83cc019SAndroid Build Coastguard Worker
429*d83cc019SAndroid Build Coastguard Worker kick_kthreads();
430*d83cc019SAndroid Build Coastguard Worker
431*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data));
432*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < num; n++)
433*d83cc019SAndroid Build Coastguard Worker d_v[n] = -data[2 + n];
434*d83cc019SAndroid Build Coastguard Worker d_t = -data[1];
435*d83cc019SAndroid Build Coastguard Worker
436*d83cc019SAndroid Build Coastguard Worker usleep(period_us);
437*d83cc019SAndroid Build Coastguard Worker
438*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data));
439*d83cc019SAndroid Build Coastguard Worker
440*d83cc019SAndroid Build Coastguard Worker d_t += data[1];
441*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < num; n++) {
442*d83cc019SAndroid Build Coastguard Worker d_v[n] += data[2 + n];
443*d83cc019SAndroid Build Coastguard Worker igt_debug("engine[%d]: %.1f%%\n",
444*d83cc019SAndroid Build Coastguard Worker n, d_v[n] / (double)d_t * 100);
445*d83cc019SAndroid Build Coastguard Worker if (d_v[n] < min)
446*d83cc019SAndroid Build Coastguard Worker min = d_v[n];
447*d83cc019SAndroid Build Coastguard Worker if (d_v[n] > max)
448*d83cc019SAndroid Build Coastguard Worker max = d_v[n];
449*d83cc019SAndroid Build Coastguard Worker }
450*d83cc019SAndroid Build Coastguard Worker
451*d83cc019SAndroid Build Coastguard Worker igt_debug("elapsed: %"PRIu64"ns, load [%.1f, %.1f]%%\n",
452*d83cc019SAndroid Build Coastguard Worker d_t, min / (double)d_t * 100, max / (double)d_t * 100);
453*d83cc019SAndroid Build Coastguard Worker
454*d83cc019SAndroid Build Coastguard Worker return min / (double)d_t;
455*d83cc019SAndroid Build Coastguard Worker }
456*d83cc019SAndroid Build Coastguard Worker
measure_all_load(int pmu,double * v,unsigned int num,int period_us)457*d83cc019SAndroid Build Coastguard Worker static void measure_all_load(int pmu, double *v, unsigned int num, int period_us)
458*d83cc019SAndroid Build Coastguard Worker {
459*d83cc019SAndroid Build Coastguard Worker uint64_t data[2 + num];
460*d83cc019SAndroid Build Coastguard Worker uint64_t d_t, d_v[num];
461*d83cc019SAndroid Build Coastguard Worker
462*d83cc019SAndroid Build Coastguard Worker kick_kthreads();
463*d83cc019SAndroid Build Coastguard Worker
464*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data));
465*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < num; n++)
466*d83cc019SAndroid Build Coastguard Worker d_v[n] = -data[2 + n];
467*d83cc019SAndroid Build Coastguard Worker d_t = -data[1];
468*d83cc019SAndroid Build Coastguard Worker
469*d83cc019SAndroid Build Coastguard Worker usleep(period_us);
470*d83cc019SAndroid Build Coastguard Worker
471*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(read(pmu, data, sizeof(data)), sizeof(data));
472*d83cc019SAndroid Build Coastguard Worker
473*d83cc019SAndroid Build Coastguard Worker d_t += data[1];
474*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < num; n++) {
475*d83cc019SAndroid Build Coastguard Worker d_v[n] += data[2 + n];
476*d83cc019SAndroid Build Coastguard Worker igt_debug("engine[%d]: %.1f%%\n",
477*d83cc019SAndroid Build Coastguard Worker n, d_v[n] / (double)d_t * 100);
478*d83cc019SAndroid Build Coastguard Worker v[n] = d_v[n] / (double)d_t;
479*d83cc019SAndroid Build Coastguard Worker }
480*d83cc019SAndroid Build Coastguard Worker }
481*d83cc019SAndroid Build Coastguard Worker
add_pmu(int pmu,const struct i915_engine_class_instance * ci)482*d83cc019SAndroid Build Coastguard Worker static int add_pmu(int pmu, const struct i915_engine_class_instance *ci)
483*d83cc019SAndroid Build Coastguard Worker {
484*d83cc019SAndroid Build Coastguard Worker return perf_i915_open_group(I915_PMU_ENGINE_BUSY(ci->engine_class,
485*d83cc019SAndroid Build Coastguard Worker ci->engine_instance),
486*d83cc019SAndroid Build Coastguard Worker pmu);
487*d83cc019SAndroid Build Coastguard Worker }
488*d83cc019SAndroid Build Coastguard Worker
class_to_str(int class)489*d83cc019SAndroid Build Coastguard Worker static const char *class_to_str(int class)
490*d83cc019SAndroid Build Coastguard Worker {
491*d83cc019SAndroid Build Coastguard Worker const char *str[] = {
492*d83cc019SAndroid Build Coastguard Worker [I915_ENGINE_CLASS_RENDER] = "rcs",
493*d83cc019SAndroid Build Coastguard Worker [I915_ENGINE_CLASS_COPY] = "bcs",
494*d83cc019SAndroid Build Coastguard Worker [I915_ENGINE_CLASS_VIDEO] = "vcs",
495*d83cc019SAndroid Build Coastguard Worker [I915_ENGINE_CLASS_VIDEO_ENHANCE] = "vecs",
496*d83cc019SAndroid Build Coastguard Worker };
497*d83cc019SAndroid Build Coastguard Worker
498*d83cc019SAndroid Build Coastguard Worker if (class < ARRAY_SIZE(str))
499*d83cc019SAndroid Build Coastguard Worker return str[class];
500*d83cc019SAndroid Build Coastguard Worker
501*d83cc019SAndroid Build Coastguard Worker return "unk";
502*d83cc019SAndroid Build Coastguard Worker }
503*d83cc019SAndroid Build Coastguard Worker
check_individual_engine(int i915,uint32_t ctx,const struct i915_engine_class_instance * ci,int idx)504*d83cc019SAndroid Build Coastguard Worker static void check_individual_engine(int i915,
505*d83cc019SAndroid Build Coastguard Worker uint32_t ctx,
506*d83cc019SAndroid Build Coastguard Worker const struct i915_engine_class_instance *ci,
507*d83cc019SAndroid Build Coastguard Worker int idx)
508*d83cc019SAndroid Build Coastguard Worker {
509*d83cc019SAndroid Build Coastguard Worker igt_spin_t *spin;
510*d83cc019SAndroid Build Coastguard Worker double load;
511*d83cc019SAndroid Build Coastguard Worker int pmu;
512*d83cc019SAndroid Build Coastguard Worker
513*d83cc019SAndroid Build Coastguard Worker pmu = perf_i915_open(I915_PMU_ENGINE_BUSY(ci[idx].engine_class,
514*d83cc019SAndroid Build Coastguard Worker ci[idx].engine_instance));
515*d83cc019SAndroid Build Coastguard Worker
516*d83cc019SAndroid Build Coastguard Worker spin = igt_spin_new(i915, .ctx = ctx, .engine = idx + 1);
517*d83cc019SAndroid Build Coastguard Worker load = measure_load(pmu, 10000);
518*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, spin);
519*d83cc019SAndroid Build Coastguard Worker
520*d83cc019SAndroid Build Coastguard Worker close(pmu);
521*d83cc019SAndroid Build Coastguard Worker
522*d83cc019SAndroid Build Coastguard Worker igt_assert_f(load > 0.90,
523*d83cc019SAndroid Build Coastguard Worker "engine %d (class:instance %d:%d) was found to be only %.1f%% busy\n",
524*d83cc019SAndroid Build Coastguard Worker idx, ci[idx].engine_class, ci[idx].engine_instance, load*100);
525*d83cc019SAndroid Build Coastguard Worker }
526*d83cc019SAndroid Build Coastguard Worker
individual(int i915)527*d83cc019SAndroid Build Coastguard Worker static void individual(int i915)
528*d83cc019SAndroid Build Coastguard Worker {
529*d83cc019SAndroid Build Coastguard Worker uint32_t ctx;
530*d83cc019SAndroid Build Coastguard Worker
531*d83cc019SAndroid Build Coastguard Worker /*
532*d83cc019SAndroid Build Coastguard Worker * I915_CONTEXT_PARAM_ENGINE allows us to index into the user
533*d83cc019SAndroid Build Coastguard Worker * supplied array from gem_execbuf(). Our check is to build the
534*d83cc019SAndroid Build Coastguard Worker * ctx->engine[] with various different engine classes, feed in
535*d83cc019SAndroid Build Coastguard Worker * a spinner and then ask pmu to confirm it the expected engine
536*d83cc019SAndroid Build Coastguard Worker * was busy.
537*d83cc019SAndroid Build Coastguard Worker */
538*d83cc019SAndroid Build Coastguard Worker
539*d83cc019SAndroid Build Coastguard Worker ctx = gem_context_create(i915);
540*d83cc019SAndroid Build Coastguard Worker
541*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 32; class++) {
542*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
543*d83cc019SAndroid Build Coastguard Worker unsigned int count;
544*d83cc019SAndroid Build Coastguard Worker
545*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1u << class, &count);
546*d83cc019SAndroid Build Coastguard Worker if (!ci)
547*d83cc019SAndroid Build Coastguard Worker continue;
548*d83cc019SAndroid Build Coastguard Worker
549*d83cc019SAndroid Build Coastguard Worker for (int pass = 0; pass < count; pass++) { /* approx. count! */
550*d83cc019SAndroid Build Coastguard Worker igt_assert(sizeof(*ci) == sizeof(int));
551*d83cc019SAndroid Build Coastguard Worker igt_permute_array(ci, count, igt_exchange_int);
552*d83cc019SAndroid Build Coastguard Worker set_load_balancer(i915, ctx, ci, count, NULL);
553*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < count; n++)
554*d83cc019SAndroid Build Coastguard Worker check_individual_engine(i915, ctx, ci, n);
555*d83cc019SAndroid Build Coastguard Worker }
556*d83cc019SAndroid Build Coastguard Worker
557*d83cc019SAndroid Build Coastguard Worker free(ci);
558*d83cc019SAndroid Build Coastguard Worker }
559*d83cc019SAndroid Build Coastguard Worker
560*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, ctx);
561*d83cc019SAndroid Build Coastguard Worker gem_quiescent_gpu(i915);
562*d83cc019SAndroid Build Coastguard Worker }
563*d83cc019SAndroid Build Coastguard Worker
bonded(int i915,unsigned int flags)564*d83cc019SAndroid Build Coastguard Worker static void bonded(int i915, unsigned int flags)
565*d83cc019SAndroid Build Coastguard Worker #define CORK 0x1
566*d83cc019SAndroid Build Coastguard Worker {
567*d83cc019SAndroid Build Coastguard Worker I915_DEFINE_CONTEXT_ENGINES_BOND(bonds[16], 1);
568*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *master_engines;
569*d83cc019SAndroid Build Coastguard Worker uint32_t master;
570*d83cc019SAndroid Build Coastguard Worker
571*d83cc019SAndroid Build Coastguard Worker /*
572*d83cc019SAndroid Build Coastguard Worker * I915_CONTEXT_PARAM_ENGINE provides an extension that allows us
573*d83cc019SAndroid Build Coastguard Worker * to specify which engine(s) to pair with a parallel (EXEC_SUBMIT)
574*d83cc019SAndroid Build Coastguard Worker * request submitted to another engine.
575*d83cc019SAndroid Build Coastguard Worker */
576*d83cc019SAndroid Build Coastguard Worker
577*d83cc019SAndroid Build Coastguard Worker master = gem_queue_create(i915);
578*d83cc019SAndroid Build Coastguard Worker
579*d83cc019SAndroid Build Coastguard Worker memset(bonds, 0, sizeof(bonds));
580*d83cc019SAndroid Build Coastguard Worker for (int n = 0; n < ARRAY_SIZE(bonds); n++) {
581*d83cc019SAndroid Build Coastguard Worker bonds[n].base.name = I915_CONTEXT_ENGINES_EXT_BOND;
582*d83cc019SAndroid Build Coastguard Worker bonds[n].base.next_extension =
583*d83cc019SAndroid Build Coastguard Worker n ? to_user_pointer(&bonds[n - 1]) : 0;
584*d83cc019SAndroid Build Coastguard Worker bonds[n].num_bonds = 1;
585*d83cc019SAndroid Build Coastguard Worker }
586*d83cc019SAndroid Build Coastguard Worker
587*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 32; class++) {
588*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *siblings;
589*d83cc019SAndroid Build Coastguard Worker unsigned int count, limit, *order;
590*d83cc019SAndroid Build Coastguard Worker uint32_t ctx;
591*d83cc019SAndroid Build Coastguard Worker int n;
592*d83cc019SAndroid Build Coastguard Worker
593*d83cc019SAndroid Build Coastguard Worker siblings = list_engines(i915, 1u << class, &count);
594*d83cc019SAndroid Build Coastguard Worker if (!siblings)
595*d83cc019SAndroid Build Coastguard Worker continue;
596*d83cc019SAndroid Build Coastguard Worker
597*d83cc019SAndroid Build Coastguard Worker if (count < 2) {
598*d83cc019SAndroid Build Coastguard Worker free(siblings);
599*d83cc019SAndroid Build Coastguard Worker continue;
600*d83cc019SAndroid Build Coastguard Worker }
601*d83cc019SAndroid Build Coastguard Worker
602*d83cc019SAndroid Build Coastguard Worker master_engines = list_engines(i915, ~(1u << class), &limit);
603*d83cc019SAndroid Build Coastguard Worker set_engines(i915, master, master_engines, limit);
604*d83cc019SAndroid Build Coastguard Worker
605*d83cc019SAndroid Build Coastguard Worker limit = min(count, limit);
606*d83cc019SAndroid Build Coastguard Worker igt_assert(limit <= ARRAY_SIZE(bonds));
607*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < limit; n++) {
608*d83cc019SAndroid Build Coastguard Worker bonds[n].master = master_engines[n];
609*d83cc019SAndroid Build Coastguard Worker bonds[n].engines[0] = siblings[n];
610*d83cc019SAndroid Build Coastguard Worker }
611*d83cc019SAndroid Build Coastguard Worker
612*d83cc019SAndroid Build Coastguard Worker ctx = gem_context_clone(i915,
613*d83cc019SAndroid Build Coastguard Worker master, I915_CONTEXT_CLONE_VM,
614*d83cc019SAndroid Build Coastguard Worker I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE);
615*d83cc019SAndroid Build Coastguard Worker set_load_balancer(i915, ctx, siblings, count, &bonds[limit - 1]);
616*d83cc019SAndroid Build Coastguard Worker
617*d83cc019SAndroid Build Coastguard Worker order = malloc(sizeof(*order) * 8 * limit);
618*d83cc019SAndroid Build Coastguard Worker igt_assert(order);
619*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < limit; n++)
620*d83cc019SAndroid Build Coastguard Worker order[2 * limit - n - 1] = order[n] = n % limit;
621*d83cc019SAndroid Build Coastguard Worker memcpy(order + 2 * limit, order, 2 * limit * sizeof(*order));
622*d83cc019SAndroid Build Coastguard Worker memcpy(order + 4 * limit, order, 4 * limit * sizeof(*order));
623*d83cc019SAndroid Build Coastguard Worker igt_permute_array(order + 2 * limit, 6 * limit, igt_exchange_int);
624*d83cc019SAndroid Build Coastguard Worker
625*d83cc019SAndroid Build Coastguard Worker for (n = 0; n < 8 * limit; n++) {
626*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 eb;
627*d83cc019SAndroid Build Coastguard Worker igt_spin_t *spin, *plug;
628*d83cc019SAndroid Build Coastguard Worker IGT_CORK_HANDLE(cork);
629*d83cc019SAndroid Build Coastguard Worker double v[limit];
630*d83cc019SAndroid Build Coastguard Worker int pmu[limit + 1];
631*d83cc019SAndroid Build Coastguard Worker int bond = order[n];
632*d83cc019SAndroid Build Coastguard Worker
633*d83cc019SAndroid Build Coastguard Worker pmu[0] = -1;
634*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i < limit; i++)
635*d83cc019SAndroid Build Coastguard Worker pmu[i] = add_pmu(pmu[0], &siblings[i]);
636*d83cc019SAndroid Build Coastguard Worker pmu[limit] = add_pmu(pmu[0], &master_engines[bond]);
637*d83cc019SAndroid Build Coastguard Worker
638*d83cc019SAndroid Build Coastguard Worker igt_assert(siblings[bond].engine_class !=
639*d83cc019SAndroid Build Coastguard Worker master_engines[bond].engine_class);
640*d83cc019SAndroid Build Coastguard Worker
641*d83cc019SAndroid Build Coastguard Worker plug = NULL;
642*d83cc019SAndroid Build Coastguard Worker if (flags & CORK) {
643*d83cc019SAndroid Build Coastguard Worker plug = __igt_spin_new(i915,
644*d83cc019SAndroid Build Coastguard Worker .ctx = master,
645*d83cc019SAndroid Build Coastguard Worker .engine = bond,
646*d83cc019SAndroid Build Coastguard Worker .dependency = igt_cork_plug(&cork, i915));
647*d83cc019SAndroid Build Coastguard Worker }
648*d83cc019SAndroid Build Coastguard Worker
649*d83cc019SAndroid Build Coastguard Worker spin = __igt_spin_new(i915,
650*d83cc019SAndroid Build Coastguard Worker .ctx = master,
651*d83cc019SAndroid Build Coastguard Worker .engine = bond,
652*d83cc019SAndroid Build Coastguard Worker .flags = IGT_SPIN_FENCE_OUT);
653*d83cc019SAndroid Build Coastguard Worker
654*d83cc019SAndroid Build Coastguard Worker eb = spin->execbuf;
655*d83cc019SAndroid Build Coastguard Worker eb.rsvd1 = ctx;
656*d83cc019SAndroid Build Coastguard Worker eb.rsvd2 = spin->out_fence;
657*d83cc019SAndroid Build Coastguard Worker eb.flags = I915_EXEC_FENCE_SUBMIT;
658*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &eb);
659*d83cc019SAndroid Build Coastguard Worker
660*d83cc019SAndroid Build Coastguard Worker if (plug) {
661*d83cc019SAndroid Build Coastguard Worker igt_cork_unplug(&cork);
662*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, plug);
663*d83cc019SAndroid Build Coastguard Worker }
664*d83cc019SAndroid Build Coastguard Worker
665*d83cc019SAndroid Build Coastguard Worker measure_all_load(pmu[0], v, limit + 1, 10000);
666*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, spin);
667*d83cc019SAndroid Build Coastguard Worker
668*d83cc019SAndroid Build Coastguard Worker igt_assert_f(v[bond] > 0.90,
669*d83cc019SAndroid Build Coastguard Worker "engine %d (class:instance %s:%d) was found to be only %.1f%% busy\n",
670*d83cc019SAndroid Build Coastguard Worker bond,
671*d83cc019SAndroid Build Coastguard Worker class_to_str(siblings[bond].engine_class),
672*d83cc019SAndroid Build Coastguard Worker siblings[bond].engine_instance,
673*d83cc019SAndroid Build Coastguard Worker 100 * v[bond]);
674*d83cc019SAndroid Build Coastguard Worker for (int other = 0; other < limit; other++) {
675*d83cc019SAndroid Build Coastguard Worker if (other == bond)
676*d83cc019SAndroid Build Coastguard Worker continue;
677*d83cc019SAndroid Build Coastguard Worker
678*d83cc019SAndroid Build Coastguard Worker igt_assert_f(v[other] == 0,
679*d83cc019SAndroid Build Coastguard Worker "engine %d (class:instance %s:%d) was not idle, and actually %.1f%% busy\n",
680*d83cc019SAndroid Build Coastguard Worker other,
681*d83cc019SAndroid Build Coastguard Worker class_to_str(siblings[other].engine_class),
682*d83cc019SAndroid Build Coastguard Worker siblings[other].engine_instance,
683*d83cc019SAndroid Build Coastguard Worker 100 * v[other]);
684*d83cc019SAndroid Build Coastguard Worker }
685*d83cc019SAndroid Build Coastguard Worker igt_assert_f(v[limit] > 0.90,
686*d83cc019SAndroid Build Coastguard Worker "master (class:instance %s:%d) was found to be only %.1f%% busy\n",
687*d83cc019SAndroid Build Coastguard Worker class_to_str(master_engines[bond].engine_class),
688*d83cc019SAndroid Build Coastguard Worker master_engines[bond].engine_instance,
689*d83cc019SAndroid Build Coastguard Worker 100 * v[limit]);
690*d83cc019SAndroid Build Coastguard Worker
691*d83cc019SAndroid Build Coastguard Worker close(pmu[0]);
692*d83cc019SAndroid Build Coastguard Worker }
693*d83cc019SAndroid Build Coastguard Worker
694*d83cc019SAndroid Build Coastguard Worker free(order);
695*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, ctx);
696*d83cc019SAndroid Build Coastguard Worker free(master_engines);
697*d83cc019SAndroid Build Coastguard Worker free(siblings);
698*d83cc019SAndroid Build Coastguard Worker }
699*d83cc019SAndroid Build Coastguard Worker
700*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, master);
701*d83cc019SAndroid Build Coastguard Worker }
702*d83cc019SAndroid Build Coastguard Worker
indices(int i915)703*d83cc019SAndroid Build Coastguard Worker static void indices(int i915)
704*d83cc019SAndroid Build Coastguard Worker {
705*d83cc019SAndroid Build Coastguard Worker I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, I915_EXEC_RING_MASK + 1);
706*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_context_param p = {
707*d83cc019SAndroid Build Coastguard Worker .ctx_id = gem_context_create(i915),
708*d83cc019SAndroid Build Coastguard Worker .param = I915_CONTEXT_PARAM_ENGINES,
709*d83cc019SAndroid Build Coastguard Worker .value = to_user_pointer(&engines)
710*d83cc019SAndroid Build Coastguard Worker };
711*d83cc019SAndroid Build Coastguard Worker
712*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 batch = {
713*d83cc019SAndroid Build Coastguard Worker .handle = batch_create(i915),
714*d83cc019SAndroid Build Coastguard Worker };
715*d83cc019SAndroid Build Coastguard Worker
716*d83cc019SAndroid Build Coastguard Worker unsigned int nengines = 0;
717*d83cc019SAndroid Build Coastguard Worker void *balancers = NULL;
718*d83cc019SAndroid Build Coastguard Worker
719*d83cc019SAndroid Build Coastguard Worker /*
720*d83cc019SAndroid Build Coastguard Worker * We can populate our engine map with multiple virtual engines.
721*d83cc019SAndroid Build Coastguard Worker * Do so.
722*d83cc019SAndroid Build Coastguard Worker */
723*d83cc019SAndroid Build Coastguard Worker
724*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 32; class++) {
725*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
726*d83cc019SAndroid Build Coastguard Worker unsigned int count;
727*d83cc019SAndroid Build Coastguard Worker
728*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1u << class, &count);
729*d83cc019SAndroid Build Coastguard Worker if (!ci)
730*d83cc019SAndroid Build Coastguard Worker continue;
731*d83cc019SAndroid Build Coastguard Worker
732*d83cc019SAndroid Build Coastguard Worker for (int n = 0; n < count; n++) {
733*d83cc019SAndroid Build Coastguard Worker struct i915_context_engines_load_balance *balancer;
734*d83cc019SAndroid Build Coastguard Worker
735*d83cc019SAndroid Build Coastguard Worker engines.engines[nengines].engine_class =
736*d83cc019SAndroid Build Coastguard Worker I915_ENGINE_CLASS_INVALID;
737*d83cc019SAndroid Build Coastguard Worker engines.engines[nengines].engine_instance =
738*d83cc019SAndroid Build Coastguard Worker I915_ENGINE_CLASS_INVALID_NONE;
739*d83cc019SAndroid Build Coastguard Worker
740*d83cc019SAndroid Build Coastguard Worker balancer = calloc(sizeof_load_balance(count), 1);
741*d83cc019SAndroid Build Coastguard Worker igt_assert(balancer);
742*d83cc019SAndroid Build Coastguard Worker
743*d83cc019SAndroid Build Coastguard Worker balancer->base.name =
744*d83cc019SAndroid Build Coastguard Worker I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE;
745*d83cc019SAndroid Build Coastguard Worker balancer->base.next_extension =
746*d83cc019SAndroid Build Coastguard Worker to_user_pointer(balancers);
747*d83cc019SAndroid Build Coastguard Worker balancers = balancer;
748*d83cc019SAndroid Build Coastguard Worker
749*d83cc019SAndroid Build Coastguard Worker balancer->engine_index = nengines++;
750*d83cc019SAndroid Build Coastguard Worker balancer->num_siblings = count;
751*d83cc019SAndroid Build Coastguard Worker
752*d83cc019SAndroid Build Coastguard Worker memcpy(balancer->engines,
753*d83cc019SAndroid Build Coastguard Worker ci, count * sizeof(*ci));
754*d83cc019SAndroid Build Coastguard Worker }
755*d83cc019SAndroid Build Coastguard Worker free(ci);
756*d83cc019SAndroid Build Coastguard Worker }
757*d83cc019SAndroid Build Coastguard Worker
758*d83cc019SAndroid Build Coastguard Worker igt_require(balancers);
759*d83cc019SAndroid Build Coastguard Worker engines.extensions = to_user_pointer(balancers);
760*d83cc019SAndroid Build Coastguard Worker p.size = (sizeof(struct i915_engine_class_instance) * nengines +
761*d83cc019SAndroid Build Coastguard Worker sizeof(struct i915_context_param_engines));
762*d83cc019SAndroid Build Coastguard Worker gem_context_set_param(i915, &p);
763*d83cc019SAndroid Build Coastguard Worker
764*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < nengines; n++) {
765*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 eb = {
766*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = to_user_pointer(&batch),
767*d83cc019SAndroid Build Coastguard Worker .buffer_count = 1,
768*d83cc019SAndroid Build Coastguard Worker .flags = n,
769*d83cc019SAndroid Build Coastguard Worker .rsvd1 = p.ctx_id,
770*d83cc019SAndroid Build Coastguard Worker };
771*d83cc019SAndroid Build Coastguard Worker igt_debug("Executing on index=%d\n", n);
772*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &eb);
773*d83cc019SAndroid Build Coastguard Worker }
774*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, p.ctx_id);
775*d83cc019SAndroid Build Coastguard Worker
776*d83cc019SAndroid Build Coastguard Worker gem_sync(i915, batch.handle);
777*d83cc019SAndroid Build Coastguard Worker gem_close(i915, batch.handle);
778*d83cc019SAndroid Build Coastguard Worker
779*d83cc019SAndroid Build Coastguard Worker while (balancers) {
780*d83cc019SAndroid Build Coastguard Worker struct i915_context_engines_load_balance *b, *n;
781*d83cc019SAndroid Build Coastguard Worker
782*d83cc019SAndroid Build Coastguard Worker b = balancers;
783*d83cc019SAndroid Build Coastguard Worker n = from_user_pointer(b->base.next_extension);
784*d83cc019SAndroid Build Coastguard Worker free(b);
785*d83cc019SAndroid Build Coastguard Worker
786*d83cc019SAndroid Build Coastguard Worker balancers = n;
787*d83cc019SAndroid Build Coastguard Worker }
788*d83cc019SAndroid Build Coastguard Worker
789*d83cc019SAndroid Build Coastguard Worker gem_quiescent_gpu(i915);
790*d83cc019SAndroid Build Coastguard Worker }
791*d83cc019SAndroid Build Coastguard Worker
busy(int i915)792*d83cc019SAndroid Build Coastguard Worker static void busy(int i915)
793*d83cc019SAndroid Build Coastguard Worker {
794*d83cc019SAndroid Build Coastguard Worker uint32_t scratch = gem_create(i915, 4096);
795*d83cc019SAndroid Build Coastguard Worker
796*d83cc019SAndroid Build Coastguard Worker /*
797*d83cc019SAndroid Build Coastguard Worker * Check that virtual engines are reported via GEM_BUSY.
798*d83cc019SAndroid Build Coastguard Worker *
799*d83cc019SAndroid Build Coastguard Worker * When running, the batch will be on the real engine and report
800*d83cc019SAndroid Build Coastguard Worker * the actual class.
801*d83cc019SAndroid Build Coastguard Worker *
802*d83cc019SAndroid Build Coastguard Worker * Prior to running, if the load-balancer is across multiple
803*d83cc019SAndroid Build Coastguard Worker * classes we don't know which engine the batch will
804*d83cc019SAndroid Build Coastguard Worker * execute on, so we report them all!
805*d83cc019SAndroid Build Coastguard Worker *
806*d83cc019SAndroid Build Coastguard Worker * However, as we only support (and test) creating a load-balancer
807*d83cc019SAndroid Build Coastguard Worker * from engines of only one class, that can be propagated accurately
808*d83cc019SAndroid Build Coastguard Worker * through to GEM_BUSY.
809*d83cc019SAndroid Build Coastguard Worker */
810*d83cc019SAndroid Build Coastguard Worker
811*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 16; class++) {
812*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_busy busy;
813*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
814*d83cc019SAndroid Build Coastguard Worker unsigned int count;
815*d83cc019SAndroid Build Coastguard Worker igt_spin_t *spin[2];
816*d83cc019SAndroid Build Coastguard Worker uint32_t ctx;
817*d83cc019SAndroid Build Coastguard Worker
818*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1u << class, &count);
819*d83cc019SAndroid Build Coastguard Worker if (!ci)
820*d83cc019SAndroid Build Coastguard Worker continue;
821*d83cc019SAndroid Build Coastguard Worker
822*d83cc019SAndroid Build Coastguard Worker ctx = load_balancer_create(i915, ci, count);
823*d83cc019SAndroid Build Coastguard Worker free(ci);
824*d83cc019SAndroid Build Coastguard Worker
825*d83cc019SAndroid Build Coastguard Worker spin[0] = __igt_spin_new(i915,
826*d83cc019SAndroid Build Coastguard Worker .ctx = ctx,
827*d83cc019SAndroid Build Coastguard Worker .flags = IGT_SPIN_POLL_RUN);
828*d83cc019SAndroid Build Coastguard Worker spin[1] = __igt_spin_new(i915,
829*d83cc019SAndroid Build Coastguard Worker .ctx = ctx,
830*d83cc019SAndroid Build Coastguard Worker .dependency = scratch);
831*d83cc019SAndroid Build Coastguard Worker
832*d83cc019SAndroid Build Coastguard Worker igt_spin_busywait_until_started(spin[0]);
833*d83cc019SAndroid Build Coastguard Worker
834*d83cc019SAndroid Build Coastguard Worker /* Running: actual class */
835*d83cc019SAndroid Build Coastguard Worker busy.handle = spin[0]->handle;
836*d83cc019SAndroid Build Coastguard Worker do_ioctl(i915, DRM_IOCTL_I915_GEM_BUSY, &busy);
837*d83cc019SAndroid Build Coastguard Worker igt_assert_eq_u32(busy.busy, 1u << (class + 16));
838*d83cc019SAndroid Build Coastguard Worker
839*d83cc019SAndroid Build Coastguard Worker /* Queued(read): expected class */
840*d83cc019SAndroid Build Coastguard Worker busy.handle = spin[1]->handle;
841*d83cc019SAndroid Build Coastguard Worker do_ioctl(i915, DRM_IOCTL_I915_GEM_BUSY, &busy);
842*d83cc019SAndroid Build Coastguard Worker igt_assert_eq_u32(busy.busy, 1u << (class + 16));
843*d83cc019SAndroid Build Coastguard Worker
844*d83cc019SAndroid Build Coastguard Worker /* Queued(write): expected class */
845*d83cc019SAndroid Build Coastguard Worker busy.handle = scratch;
846*d83cc019SAndroid Build Coastguard Worker do_ioctl(i915, DRM_IOCTL_I915_GEM_BUSY, &busy);
847*d83cc019SAndroid Build Coastguard Worker igt_assert_eq_u32(busy.busy,
848*d83cc019SAndroid Build Coastguard Worker (1u << (class + 16)) | (class + 1));
849*d83cc019SAndroid Build Coastguard Worker
850*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, spin[1]);
851*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, spin[0]);
852*d83cc019SAndroid Build Coastguard Worker
853*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, ctx);
854*d83cc019SAndroid Build Coastguard Worker }
855*d83cc019SAndroid Build Coastguard Worker
856*d83cc019SAndroid Build Coastguard Worker gem_close(i915, scratch);
857*d83cc019SAndroid Build Coastguard Worker gem_quiescent_gpu(i915);
858*d83cc019SAndroid Build Coastguard Worker }
859*d83cc019SAndroid Build Coastguard Worker
full(int i915,unsigned int flags)860*d83cc019SAndroid Build Coastguard Worker static void full(int i915, unsigned int flags)
861*d83cc019SAndroid Build Coastguard Worker #define PULSE 0x1
862*d83cc019SAndroid Build Coastguard Worker #define LATE 0x2
863*d83cc019SAndroid Build Coastguard Worker {
864*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 batch = {
865*d83cc019SAndroid Build Coastguard Worker .handle = batch_create(i915),
866*d83cc019SAndroid Build Coastguard Worker };
867*d83cc019SAndroid Build Coastguard Worker
868*d83cc019SAndroid Build Coastguard Worker if (flags & LATE)
869*d83cc019SAndroid Build Coastguard Worker igt_require_sw_sync();
870*d83cc019SAndroid Build Coastguard Worker
871*d83cc019SAndroid Build Coastguard Worker /*
872*d83cc019SAndroid Build Coastguard Worker * I915_CONTEXT_PARAM_ENGINE changes the meaning of engine selector in
873*d83cc019SAndroid Build Coastguard Worker * execbuf to utilize our own map, into which we replace I915_EXEC_DEFAULT
874*d83cc019SAndroid Build Coastguard Worker * to provide an automatic selection from the other ctx->engine[]. It
875*d83cc019SAndroid Build Coastguard Worker * employs load-balancing to evenly distribute the workload the
876*d83cc019SAndroid Build Coastguard Worker * array. If we submit N spinners, we expect them to be simultaneously
877*d83cc019SAndroid Build Coastguard Worker * running across N engines and use PMU to confirm that the entire
878*d83cc019SAndroid Build Coastguard Worker * set of engines are busy.
879*d83cc019SAndroid Build Coastguard Worker *
880*d83cc019SAndroid Build Coastguard Worker * We complicate matters by interspersing short-lived tasks to
881*d83cc019SAndroid Build Coastguard Worker * challenge the kernel to search for space in which to insert new
882*d83cc019SAndroid Build Coastguard Worker * batches.
883*d83cc019SAndroid Build Coastguard Worker */
884*d83cc019SAndroid Build Coastguard Worker
885*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 32; class++) {
886*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
887*d83cc019SAndroid Build Coastguard Worker igt_spin_t *spin = NULL;
888*d83cc019SAndroid Build Coastguard Worker IGT_CORK_FENCE(cork);
889*d83cc019SAndroid Build Coastguard Worker unsigned int count;
890*d83cc019SAndroid Build Coastguard Worker double load;
891*d83cc019SAndroid Build Coastguard Worker int fence = -1;
892*d83cc019SAndroid Build Coastguard Worker int *pmu;
893*d83cc019SAndroid Build Coastguard Worker
894*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1u << class, &count);
895*d83cc019SAndroid Build Coastguard Worker if (!ci)
896*d83cc019SAndroid Build Coastguard Worker continue;
897*d83cc019SAndroid Build Coastguard Worker
898*d83cc019SAndroid Build Coastguard Worker pmu = malloc(sizeof(*pmu) * count);
899*d83cc019SAndroid Build Coastguard Worker igt_assert(pmu);
900*d83cc019SAndroid Build Coastguard Worker
901*d83cc019SAndroid Build Coastguard Worker if (flags & LATE)
902*d83cc019SAndroid Build Coastguard Worker fence = igt_cork_plug(&cork, i915);
903*d83cc019SAndroid Build Coastguard Worker
904*d83cc019SAndroid Build Coastguard Worker pmu[0] = -1;
905*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < count; n++) {
906*d83cc019SAndroid Build Coastguard Worker uint32_t ctx;
907*d83cc019SAndroid Build Coastguard Worker
908*d83cc019SAndroid Build Coastguard Worker pmu[n] = add_pmu(pmu[0], &ci[n]);
909*d83cc019SAndroid Build Coastguard Worker
910*d83cc019SAndroid Build Coastguard Worker if (flags & PULSE) {
911*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 eb = {
912*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = to_user_pointer(&batch),
913*d83cc019SAndroid Build Coastguard Worker .buffer_count = 1,
914*d83cc019SAndroid Build Coastguard Worker .rsvd2 = fence,
915*d83cc019SAndroid Build Coastguard Worker .flags = flags & LATE ? I915_EXEC_FENCE_IN : 0,
916*d83cc019SAndroid Build Coastguard Worker };
917*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &eb);
918*d83cc019SAndroid Build Coastguard Worker }
919*d83cc019SAndroid Build Coastguard Worker
920*d83cc019SAndroid Build Coastguard Worker /*
921*d83cc019SAndroid Build Coastguard Worker * Each spinner needs to be one a new timeline,
922*d83cc019SAndroid Build Coastguard Worker * otherwise they will just sit in the single queue
923*d83cc019SAndroid Build Coastguard Worker * and not run concurrently.
924*d83cc019SAndroid Build Coastguard Worker */
925*d83cc019SAndroid Build Coastguard Worker ctx = load_balancer_create(i915, ci, count);
926*d83cc019SAndroid Build Coastguard Worker
927*d83cc019SAndroid Build Coastguard Worker if (spin == NULL) {
928*d83cc019SAndroid Build Coastguard Worker spin = __igt_spin_new(i915, .ctx = ctx);
929*d83cc019SAndroid Build Coastguard Worker } else {
930*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 eb = {
931*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = spin->execbuf.buffers_ptr,
932*d83cc019SAndroid Build Coastguard Worker .buffer_count = spin->execbuf.buffer_count,
933*d83cc019SAndroid Build Coastguard Worker .rsvd1 = ctx,
934*d83cc019SAndroid Build Coastguard Worker .rsvd2 = fence,
935*d83cc019SAndroid Build Coastguard Worker .flags = flags & LATE ? I915_EXEC_FENCE_IN : 0,
936*d83cc019SAndroid Build Coastguard Worker };
937*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &eb);
938*d83cc019SAndroid Build Coastguard Worker }
939*d83cc019SAndroid Build Coastguard Worker
940*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, ctx);
941*d83cc019SAndroid Build Coastguard Worker }
942*d83cc019SAndroid Build Coastguard Worker
943*d83cc019SAndroid Build Coastguard Worker if (flags & LATE) {
944*d83cc019SAndroid Build Coastguard Worker igt_cork_unplug(&cork);
945*d83cc019SAndroid Build Coastguard Worker close(fence);
946*d83cc019SAndroid Build Coastguard Worker }
947*d83cc019SAndroid Build Coastguard Worker
948*d83cc019SAndroid Build Coastguard Worker load = measure_min_load(pmu[0], count, 10000);
949*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, spin);
950*d83cc019SAndroid Build Coastguard Worker
951*d83cc019SAndroid Build Coastguard Worker close(pmu[0]);
952*d83cc019SAndroid Build Coastguard Worker free(pmu);
953*d83cc019SAndroid Build Coastguard Worker
954*d83cc019SAndroid Build Coastguard Worker free(ci);
955*d83cc019SAndroid Build Coastguard Worker
956*d83cc019SAndroid Build Coastguard Worker igt_assert_f(load > 0.90,
957*d83cc019SAndroid Build Coastguard Worker "minimum load for %d x class:%d was found to be only %.1f%% busy\n",
958*d83cc019SAndroid Build Coastguard Worker count, class, load*100);
959*d83cc019SAndroid Build Coastguard Worker gem_quiescent_gpu(i915);
960*d83cc019SAndroid Build Coastguard Worker }
961*d83cc019SAndroid Build Coastguard Worker
962*d83cc019SAndroid Build Coastguard Worker gem_close(i915, batch.handle);
963*d83cc019SAndroid Build Coastguard Worker gem_quiescent_gpu(i915);
964*d83cc019SAndroid Build Coastguard Worker }
965*d83cc019SAndroid Build Coastguard Worker
nop(int i915)966*d83cc019SAndroid Build Coastguard Worker static void nop(int i915)
967*d83cc019SAndroid Build Coastguard Worker {
968*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 batch = {
969*d83cc019SAndroid Build Coastguard Worker .handle = batch_create(i915),
970*d83cc019SAndroid Build Coastguard Worker };
971*d83cc019SAndroid Build Coastguard Worker
972*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 32; class++) {
973*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
974*d83cc019SAndroid Build Coastguard Worker unsigned int count;
975*d83cc019SAndroid Build Coastguard Worker uint32_t ctx;
976*d83cc019SAndroid Build Coastguard Worker
977*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1u << class, &count);
978*d83cc019SAndroid Build Coastguard Worker if (!ci)
979*d83cc019SAndroid Build Coastguard Worker continue;
980*d83cc019SAndroid Build Coastguard Worker
981*d83cc019SAndroid Build Coastguard Worker ctx = load_balancer_create(i915, ci, count);
982*d83cc019SAndroid Build Coastguard Worker
983*d83cc019SAndroid Build Coastguard Worker for (int n = 0; n < count; n++) {
984*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf = {
985*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = to_user_pointer(&batch),
986*d83cc019SAndroid Build Coastguard Worker .buffer_count = 1,
987*d83cc019SAndroid Build Coastguard Worker .flags = n + 1,
988*d83cc019SAndroid Build Coastguard Worker .rsvd1 = ctx,
989*d83cc019SAndroid Build Coastguard Worker };
990*d83cc019SAndroid Build Coastguard Worker struct timespec tv = {};
991*d83cc019SAndroid Build Coastguard Worker unsigned long nops;
992*d83cc019SAndroid Build Coastguard Worker double t;
993*d83cc019SAndroid Build Coastguard Worker
994*d83cc019SAndroid Build Coastguard Worker igt_nsec_elapsed(&tv);
995*d83cc019SAndroid Build Coastguard Worker nops = 0;
996*d83cc019SAndroid Build Coastguard Worker do {
997*d83cc019SAndroid Build Coastguard Worker for (int r = 0; r < 1024; r++)
998*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &execbuf);
999*d83cc019SAndroid Build Coastguard Worker nops += 1024;
1000*d83cc019SAndroid Build Coastguard Worker } while (igt_seconds_elapsed(&tv) < 2);
1001*d83cc019SAndroid Build Coastguard Worker gem_sync(i915, batch.handle);
1002*d83cc019SAndroid Build Coastguard Worker
1003*d83cc019SAndroid Build Coastguard Worker t = igt_nsec_elapsed(&tv) * 1e-3 / nops;
1004*d83cc019SAndroid Build Coastguard Worker igt_info("%s:%d %.3fus\n", class_to_str(class), n, t);
1005*d83cc019SAndroid Build Coastguard Worker }
1006*d83cc019SAndroid Build Coastguard Worker
1007*d83cc019SAndroid Build Coastguard Worker {
1008*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf = {
1009*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = to_user_pointer(&batch),
1010*d83cc019SAndroid Build Coastguard Worker .buffer_count = 1,
1011*d83cc019SAndroid Build Coastguard Worker .rsvd1 = ctx,
1012*d83cc019SAndroid Build Coastguard Worker };
1013*d83cc019SAndroid Build Coastguard Worker struct timespec tv = {};
1014*d83cc019SAndroid Build Coastguard Worker unsigned long nops;
1015*d83cc019SAndroid Build Coastguard Worker double t;
1016*d83cc019SAndroid Build Coastguard Worker
1017*d83cc019SAndroid Build Coastguard Worker igt_nsec_elapsed(&tv);
1018*d83cc019SAndroid Build Coastguard Worker nops = 0;
1019*d83cc019SAndroid Build Coastguard Worker do {
1020*d83cc019SAndroid Build Coastguard Worker for (int r = 0; r < 1024; r++)
1021*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &execbuf);
1022*d83cc019SAndroid Build Coastguard Worker nops += 1024;
1023*d83cc019SAndroid Build Coastguard Worker } while (igt_seconds_elapsed(&tv) < 2);
1024*d83cc019SAndroid Build Coastguard Worker gem_sync(i915, batch.handle);
1025*d83cc019SAndroid Build Coastguard Worker
1026*d83cc019SAndroid Build Coastguard Worker t = igt_nsec_elapsed(&tv) * 1e-3 / nops;
1027*d83cc019SAndroid Build Coastguard Worker igt_info("%s:* %.3fus\n", class_to_str(class), t);
1028*d83cc019SAndroid Build Coastguard Worker }
1029*d83cc019SAndroid Build Coastguard Worker
1030*d83cc019SAndroid Build Coastguard Worker
1031*d83cc019SAndroid Build Coastguard Worker igt_fork(child, count) {
1032*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf = {
1033*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = to_user_pointer(&batch),
1034*d83cc019SAndroid Build Coastguard Worker .buffer_count = 1,
1035*d83cc019SAndroid Build Coastguard Worker .flags = child + 1,
1036*d83cc019SAndroid Build Coastguard Worker .rsvd1 = gem_context_clone(i915, ctx,
1037*d83cc019SAndroid Build Coastguard Worker I915_CONTEXT_CLONE_ENGINES, 0),
1038*d83cc019SAndroid Build Coastguard Worker };
1039*d83cc019SAndroid Build Coastguard Worker struct timespec tv = {};
1040*d83cc019SAndroid Build Coastguard Worker unsigned long nops;
1041*d83cc019SAndroid Build Coastguard Worker double t;
1042*d83cc019SAndroid Build Coastguard Worker
1043*d83cc019SAndroid Build Coastguard Worker igt_nsec_elapsed(&tv);
1044*d83cc019SAndroid Build Coastguard Worker nops = 0;
1045*d83cc019SAndroid Build Coastguard Worker do {
1046*d83cc019SAndroid Build Coastguard Worker for (int r = 0; r < 1024; r++)
1047*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &execbuf);
1048*d83cc019SAndroid Build Coastguard Worker nops += 1024;
1049*d83cc019SAndroid Build Coastguard Worker } while (igt_seconds_elapsed(&tv) < 2);
1050*d83cc019SAndroid Build Coastguard Worker gem_sync(i915, batch.handle);
1051*d83cc019SAndroid Build Coastguard Worker
1052*d83cc019SAndroid Build Coastguard Worker t = igt_nsec_elapsed(&tv) * 1e-3 / nops;
1053*d83cc019SAndroid Build Coastguard Worker igt_info("[%d] %s:%d %.3fus\n",
1054*d83cc019SAndroid Build Coastguard Worker child, class_to_str(class), child, t);
1055*d83cc019SAndroid Build Coastguard Worker
1056*d83cc019SAndroid Build Coastguard Worker memset(&tv, 0, sizeof(tv));
1057*d83cc019SAndroid Build Coastguard Worker execbuf.flags = 0;
1058*d83cc019SAndroid Build Coastguard Worker
1059*d83cc019SAndroid Build Coastguard Worker igt_nsec_elapsed(&tv);
1060*d83cc019SAndroid Build Coastguard Worker nops = 0;
1061*d83cc019SAndroid Build Coastguard Worker do {
1062*d83cc019SAndroid Build Coastguard Worker for (int r = 0; r < 1024; r++)
1063*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &execbuf);
1064*d83cc019SAndroid Build Coastguard Worker nops += 1024;
1065*d83cc019SAndroid Build Coastguard Worker } while (igt_seconds_elapsed(&tv) < 2);
1066*d83cc019SAndroid Build Coastguard Worker gem_sync(i915, batch.handle);
1067*d83cc019SAndroid Build Coastguard Worker
1068*d83cc019SAndroid Build Coastguard Worker t = igt_nsec_elapsed(&tv) * 1e-3 / nops;
1069*d83cc019SAndroid Build Coastguard Worker igt_info("[%d] %s:* %.3fus\n",
1070*d83cc019SAndroid Build Coastguard Worker child, class_to_str(class), t);
1071*d83cc019SAndroid Build Coastguard Worker
1072*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, execbuf.rsvd1);
1073*d83cc019SAndroid Build Coastguard Worker }
1074*d83cc019SAndroid Build Coastguard Worker
1075*d83cc019SAndroid Build Coastguard Worker igt_waitchildren();
1076*d83cc019SAndroid Build Coastguard Worker
1077*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, ctx);
1078*d83cc019SAndroid Build Coastguard Worker free(ci);
1079*d83cc019SAndroid Build Coastguard Worker }
1080*d83cc019SAndroid Build Coastguard Worker
1081*d83cc019SAndroid Build Coastguard Worker gem_close(i915, batch.handle);
1082*d83cc019SAndroid Build Coastguard Worker gem_quiescent_gpu(i915);
1083*d83cc019SAndroid Build Coastguard Worker }
1084*d83cc019SAndroid Build Coastguard Worker
ping(int i915,uint32_t ctx,unsigned int engine)1085*d83cc019SAndroid Build Coastguard Worker static void ping(int i915, uint32_t ctx, unsigned int engine)
1086*d83cc019SAndroid Build Coastguard Worker {
1087*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 obj = {
1088*d83cc019SAndroid Build Coastguard Worker .handle = batch_create(i915),
1089*d83cc019SAndroid Build Coastguard Worker };
1090*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 execbuf = {
1091*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = to_user_pointer(&obj),
1092*d83cc019SAndroid Build Coastguard Worker .buffer_count = 1,
1093*d83cc019SAndroid Build Coastguard Worker .flags = engine,
1094*d83cc019SAndroid Build Coastguard Worker .rsvd1 = ctx,
1095*d83cc019SAndroid Build Coastguard Worker };
1096*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &execbuf);
1097*d83cc019SAndroid Build Coastguard Worker gem_sync(i915, obj.handle);
1098*d83cc019SAndroid Build Coastguard Worker gem_close(i915, obj.handle);
1099*d83cc019SAndroid Build Coastguard Worker }
1100*d83cc019SAndroid Build Coastguard Worker
semaphore(int i915)1101*d83cc019SAndroid Build Coastguard Worker static void semaphore(int i915)
1102*d83cc019SAndroid Build Coastguard Worker {
1103*d83cc019SAndroid Build Coastguard Worker uint32_t block[2], scratch;
1104*d83cc019SAndroid Build Coastguard Worker igt_spin_t *spin[3];
1105*d83cc019SAndroid Build Coastguard Worker
1106*d83cc019SAndroid Build Coastguard Worker /*
1107*d83cc019SAndroid Build Coastguard Worker * If we are using HW semaphores to launch serialised requests
1108*d83cc019SAndroid Build Coastguard Worker * on different engine concurrently, we want to verify that real
1109*d83cc019SAndroid Build Coastguard Worker * work is unimpeded.
1110*d83cc019SAndroid Build Coastguard Worker */
1111*d83cc019SAndroid Build Coastguard Worker igt_require(gem_scheduler_has_preemption(i915));
1112*d83cc019SAndroid Build Coastguard Worker
1113*d83cc019SAndroid Build Coastguard Worker block[0] = gem_context_create(i915);
1114*d83cc019SAndroid Build Coastguard Worker block[1] = gem_context_create(i915);
1115*d83cc019SAndroid Build Coastguard Worker
1116*d83cc019SAndroid Build Coastguard Worker scratch = gem_create(i915, 4096);
1117*d83cc019SAndroid Build Coastguard Worker spin[2] = igt_spin_new(i915, .dependency = scratch);
1118*d83cc019SAndroid Build Coastguard Worker for (int class = 1; class < 32; class++) {
1119*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
1120*d83cc019SAndroid Build Coastguard Worker unsigned int count;
1121*d83cc019SAndroid Build Coastguard Worker uint32_t vip;
1122*d83cc019SAndroid Build Coastguard Worker
1123*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1u << class, &count);
1124*d83cc019SAndroid Build Coastguard Worker if (!ci)
1125*d83cc019SAndroid Build Coastguard Worker continue;
1126*d83cc019SAndroid Build Coastguard Worker
1127*d83cc019SAndroid Build Coastguard Worker if (count < ARRAY_SIZE(block))
1128*d83cc019SAndroid Build Coastguard Worker continue;
1129*d83cc019SAndroid Build Coastguard Worker
1130*d83cc019SAndroid Build Coastguard Worker /* Ensure that we completely occupy all engines in this group */
1131*d83cc019SAndroid Build Coastguard Worker count = ARRAY_SIZE(block);
1132*d83cc019SAndroid Build Coastguard Worker
1133*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
1134*d83cc019SAndroid Build Coastguard Worker set_load_balancer(i915, block[i], ci, count, NULL);
1135*d83cc019SAndroid Build Coastguard Worker spin[i] = __igt_spin_new(i915,
1136*d83cc019SAndroid Build Coastguard Worker .ctx = block[i],
1137*d83cc019SAndroid Build Coastguard Worker .dependency = scratch);
1138*d83cc019SAndroid Build Coastguard Worker }
1139*d83cc019SAndroid Build Coastguard Worker
1140*d83cc019SAndroid Build Coastguard Worker /*
1141*d83cc019SAndroid Build Coastguard Worker * Either we haven't blocked both engines with semaphores,
1142*d83cc019SAndroid Build Coastguard Worker * or we let the vip through. If not, we hang.
1143*d83cc019SAndroid Build Coastguard Worker */
1144*d83cc019SAndroid Build Coastguard Worker vip = gem_context_create(i915);
1145*d83cc019SAndroid Build Coastguard Worker set_load_balancer(i915, vip, ci, count, NULL);
1146*d83cc019SAndroid Build Coastguard Worker ping(i915, vip, 0);
1147*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, vip);
1148*d83cc019SAndroid Build Coastguard Worker
1149*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i < count; i++)
1150*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, spin[i]);
1151*d83cc019SAndroid Build Coastguard Worker
1152*d83cc019SAndroid Build Coastguard Worker free(ci);
1153*d83cc019SAndroid Build Coastguard Worker }
1154*d83cc019SAndroid Build Coastguard Worker igt_spin_free(i915, spin[2]);
1155*d83cc019SAndroid Build Coastguard Worker gem_close(i915, scratch);
1156*d83cc019SAndroid Build Coastguard Worker
1157*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, block[1]);
1158*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, block[0]);
1159*d83cc019SAndroid Build Coastguard Worker
1160*d83cc019SAndroid Build Coastguard Worker gem_quiescent_gpu(i915);
1161*d83cc019SAndroid Build Coastguard Worker }
1162*d83cc019SAndroid Build Coastguard Worker
smoketest(int i915,int timeout)1163*d83cc019SAndroid Build Coastguard Worker static void smoketest(int i915, int timeout)
1164*d83cc019SAndroid Build Coastguard Worker {
1165*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_exec_object2 batch[2] = {
1166*d83cc019SAndroid Build Coastguard Worker { .handle = __batch_create(i915, 16380) }
1167*d83cc019SAndroid Build Coastguard Worker };
1168*d83cc019SAndroid Build Coastguard Worker unsigned int ncontext = 0;
1169*d83cc019SAndroid Build Coastguard Worker uint32_t *contexts = NULL;
1170*d83cc019SAndroid Build Coastguard Worker uint32_t *handles = NULL;
1171*d83cc019SAndroid Build Coastguard Worker
1172*d83cc019SAndroid Build Coastguard Worker igt_require_sw_sync();
1173*d83cc019SAndroid Build Coastguard Worker
1174*d83cc019SAndroid Build Coastguard Worker for (int class = 0; class < 32; class++) {
1175*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance *ci;
1176*d83cc019SAndroid Build Coastguard Worker unsigned int count = 0;
1177*d83cc019SAndroid Build Coastguard Worker
1178*d83cc019SAndroid Build Coastguard Worker ci = list_engines(i915, 1u << class, &count);
1179*d83cc019SAndroid Build Coastguard Worker if (!ci || count < 2) {
1180*d83cc019SAndroid Build Coastguard Worker free(ci);
1181*d83cc019SAndroid Build Coastguard Worker continue;
1182*d83cc019SAndroid Build Coastguard Worker }
1183*d83cc019SAndroid Build Coastguard Worker
1184*d83cc019SAndroid Build Coastguard Worker ncontext += 128;
1185*d83cc019SAndroid Build Coastguard Worker contexts = realloc(contexts, sizeof(*contexts) * ncontext);
1186*d83cc019SAndroid Build Coastguard Worker igt_assert(contexts);
1187*d83cc019SAndroid Build Coastguard Worker
1188*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = ncontext - 128; n < ncontext; n++) {
1189*d83cc019SAndroid Build Coastguard Worker contexts[n] = load_balancer_create(i915, ci, count);
1190*d83cc019SAndroid Build Coastguard Worker igt_assert(contexts[n]);
1191*d83cc019SAndroid Build Coastguard Worker }
1192*d83cc019SAndroid Build Coastguard Worker
1193*d83cc019SAndroid Build Coastguard Worker free(ci);
1194*d83cc019SAndroid Build Coastguard Worker }
1195*d83cc019SAndroid Build Coastguard Worker igt_debug("Created %d virtual engines (one per context)\n", ncontext);
1196*d83cc019SAndroid Build Coastguard Worker igt_require(ncontext);
1197*d83cc019SAndroid Build Coastguard Worker
1198*d83cc019SAndroid Build Coastguard Worker contexts = realloc(contexts, sizeof(*contexts) * ncontext * 4);
1199*d83cc019SAndroid Build Coastguard Worker igt_assert(contexts);
1200*d83cc019SAndroid Build Coastguard Worker memcpy(contexts + ncontext, contexts, ncontext * sizeof(*contexts));
1201*d83cc019SAndroid Build Coastguard Worker ncontext *= 2;
1202*d83cc019SAndroid Build Coastguard Worker memcpy(contexts + ncontext, contexts, ncontext * sizeof(*contexts));
1203*d83cc019SAndroid Build Coastguard Worker ncontext *= 2;
1204*d83cc019SAndroid Build Coastguard Worker
1205*d83cc019SAndroid Build Coastguard Worker handles = malloc(sizeof(*handles) * ncontext);
1206*d83cc019SAndroid Build Coastguard Worker igt_assert(handles);
1207*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < ncontext; n++)
1208*d83cc019SAndroid Build Coastguard Worker handles[n] = gem_create(i915, 4096);
1209*d83cc019SAndroid Build Coastguard Worker
1210*d83cc019SAndroid Build Coastguard Worker igt_until_timeout(timeout) {
1211*d83cc019SAndroid Build Coastguard Worker unsigned int count = 1 + (rand() % (ncontext - 1));
1212*d83cc019SAndroid Build Coastguard Worker IGT_CORK_FENCE(cork);
1213*d83cc019SAndroid Build Coastguard Worker int fence = igt_cork_plug(&cork, i915);
1214*d83cc019SAndroid Build Coastguard Worker
1215*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < count; n++) {
1216*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_execbuffer2 eb = {
1217*d83cc019SAndroid Build Coastguard Worker .buffers_ptr = to_user_pointer(batch),
1218*d83cc019SAndroid Build Coastguard Worker .buffer_count = ARRAY_SIZE(batch),
1219*d83cc019SAndroid Build Coastguard Worker .rsvd1 = contexts[n],
1220*d83cc019SAndroid Build Coastguard Worker .rsvd2 = fence,
1221*d83cc019SAndroid Build Coastguard Worker .flags = I915_EXEC_BATCH_FIRST | I915_EXEC_FENCE_IN,
1222*d83cc019SAndroid Build Coastguard Worker };
1223*d83cc019SAndroid Build Coastguard Worker batch[1].handle = handles[n];
1224*d83cc019SAndroid Build Coastguard Worker gem_execbuf(i915, &eb);
1225*d83cc019SAndroid Build Coastguard Worker }
1226*d83cc019SAndroid Build Coastguard Worker igt_permute_array(handles, count, igt_exchange_int);
1227*d83cc019SAndroid Build Coastguard Worker
1228*d83cc019SAndroid Build Coastguard Worker igt_cork_unplug(&cork);
1229*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < count; n++)
1230*d83cc019SAndroid Build Coastguard Worker gem_sync(i915, handles[n]);
1231*d83cc019SAndroid Build Coastguard Worker
1232*d83cc019SAndroid Build Coastguard Worker close(fence);
1233*d83cc019SAndroid Build Coastguard Worker }
1234*d83cc019SAndroid Build Coastguard Worker
1235*d83cc019SAndroid Build Coastguard Worker for (unsigned int n = 0; n < ncontext; n++) {
1236*d83cc019SAndroid Build Coastguard Worker gem_close(i915, handles[n]);
1237*d83cc019SAndroid Build Coastguard Worker __gem_context_destroy(i915, contexts[n]);
1238*d83cc019SAndroid Build Coastguard Worker }
1239*d83cc019SAndroid Build Coastguard Worker free(handles);
1240*d83cc019SAndroid Build Coastguard Worker free(contexts);
1241*d83cc019SAndroid Build Coastguard Worker gem_close(i915, batch[0].handle);
1242*d83cc019SAndroid Build Coastguard Worker }
1243*d83cc019SAndroid Build Coastguard Worker
has_context_engines(int i915)1244*d83cc019SAndroid Build Coastguard Worker static bool has_context_engines(int i915)
1245*d83cc019SAndroid Build Coastguard Worker {
1246*d83cc019SAndroid Build Coastguard Worker struct drm_i915_gem_context_param p = {
1247*d83cc019SAndroid Build Coastguard Worker .param = I915_CONTEXT_PARAM_ENGINES,
1248*d83cc019SAndroid Build Coastguard Worker };
1249*d83cc019SAndroid Build Coastguard Worker
1250*d83cc019SAndroid Build Coastguard Worker return __gem_context_set_param(i915, &p) == 0;
1251*d83cc019SAndroid Build Coastguard Worker }
1252*d83cc019SAndroid Build Coastguard Worker
has_load_balancer(int i915)1253*d83cc019SAndroid Build Coastguard Worker static bool has_load_balancer(int i915)
1254*d83cc019SAndroid Build Coastguard Worker {
1255*d83cc019SAndroid Build Coastguard Worker struct i915_engine_class_instance ci = {};
1256*d83cc019SAndroid Build Coastguard Worker uint32_t ctx;
1257*d83cc019SAndroid Build Coastguard Worker int err;
1258*d83cc019SAndroid Build Coastguard Worker
1259*d83cc019SAndroid Build Coastguard Worker ctx = gem_context_create(i915);
1260*d83cc019SAndroid Build Coastguard Worker err = __set_load_balancer(i915, ctx, &ci, 1, NULL);
1261*d83cc019SAndroid Build Coastguard Worker gem_context_destroy(i915, ctx);
1262*d83cc019SAndroid Build Coastguard Worker
1263*d83cc019SAndroid Build Coastguard Worker return err == 0;
1264*d83cc019SAndroid Build Coastguard Worker }
1265*d83cc019SAndroid Build Coastguard Worker
1266*d83cc019SAndroid Build Coastguard Worker igt_main
1267*d83cc019SAndroid Build Coastguard Worker {
1268*d83cc019SAndroid Build Coastguard Worker int i915 = -1;
1269*d83cc019SAndroid Build Coastguard Worker
1270*d83cc019SAndroid Build Coastguard Worker igt_skip_on_simulation();
1271*d83cc019SAndroid Build Coastguard Worker
1272*d83cc019SAndroid Build Coastguard Worker igt_fixture {
1273*d83cc019SAndroid Build Coastguard Worker i915 = drm_open_driver(DRIVER_INTEL);
1274*d83cc019SAndroid Build Coastguard Worker igt_require_gem(i915);
1275*d83cc019SAndroid Build Coastguard Worker
1276*d83cc019SAndroid Build Coastguard Worker gem_require_contexts(i915);
1277*d83cc019SAndroid Build Coastguard Worker igt_require(has_context_engines(i915));
1278*d83cc019SAndroid Build Coastguard Worker igt_require(has_load_balancer(i915));
1279*d83cc019SAndroid Build Coastguard Worker
1280*d83cc019SAndroid Build Coastguard Worker igt_fork_hang_detector(i915);
1281*d83cc019SAndroid Build Coastguard Worker }
1282*d83cc019SAndroid Build Coastguard Worker
1283*d83cc019SAndroid Build Coastguard Worker igt_subtest("invalid-balancer")
1284*d83cc019SAndroid Build Coastguard Worker invalid_balancer(i915);
1285*d83cc019SAndroid Build Coastguard Worker
1286*d83cc019SAndroid Build Coastguard Worker igt_subtest("invalid-bonds")
1287*d83cc019SAndroid Build Coastguard Worker invalid_bonds(i915);
1288*d83cc019SAndroid Build Coastguard Worker
1289*d83cc019SAndroid Build Coastguard Worker igt_subtest("individual")
1290*d83cc019SAndroid Build Coastguard Worker individual(i915);
1291*d83cc019SAndroid Build Coastguard Worker
1292*d83cc019SAndroid Build Coastguard Worker igt_subtest("indices")
1293*d83cc019SAndroid Build Coastguard Worker indices(i915);
1294*d83cc019SAndroid Build Coastguard Worker
1295*d83cc019SAndroid Build Coastguard Worker igt_subtest("busy")
1296*d83cc019SAndroid Build Coastguard Worker busy(i915);
1297*d83cc019SAndroid Build Coastguard Worker
1298*d83cc019SAndroid Build Coastguard Worker igt_subtest_group {
1299*d83cc019SAndroid Build Coastguard Worker static const struct {
1300*d83cc019SAndroid Build Coastguard Worker const char *name;
1301*d83cc019SAndroid Build Coastguard Worker unsigned int flags;
1302*d83cc019SAndroid Build Coastguard Worker } phases[] = {
1303*d83cc019SAndroid Build Coastguard Worker { "", 0 },
1304*d83cc019SAndroid Build Coastguard Worker { "-pulse", PULSE },
1305*d83cc019SAndroid Build Coastguard Worker { "-late", LATE },
1306*d83cc019SAndroid Build Coastguard Worker { "-late-pulse", PULSE | LATE },
1307*d83cc019SAndroid Build Coastguard Worker { }
1308*d83cc019SAndroid Build Coastguard Worker };
1309*d83cc019SAndroid Build Coastguard Worker for (typeof(*phases) *p = phases; p->name; p++)
1310*d83cc019SAndroid Build Coastguard Worker igt_subtest_f("full%s", p->name)
1311*d83cc019SAndroid Build Coastguard Worker full(i915, p->flags);
1312*d83cc019SAndroid Build Coastguard Worker }
1313*d83cc019SAndroid Build Coastguard Worker
1314*d83cc019SAndroid Build Coastguard Worker igt_subtest("nop")
1315*d83cc019SAndroid Build Coastguard Worker nop(i915);
1316*d83cc019SAndroid Build Coastguard Worker
1317*d83cc019SAndroid Build Coastguard Worker igt_subtest("semaphore")
1318*d83cc019SAndroid Build Coastguard Worker semaphore(i915);
1319*d83cc019SAndroid Build Coastguard Worker
1320*d83cc019SAndroid Build Coastguard Worker igt_subtest("smoke")
1321*d83cc019SAndroid Build Coastguard Worker smoketest(i915, 20);
1322*d83cc019SAndroid Build Coastguard Worker
1323*d83cc019SAndroid Build Coastguard Worker igt_subtest("bonded-imm")
1324*d83cc019SAndroid Build Coastguard Worker bonded(i915, 0);
1325*d83cc019SAndroid Build Coastguard Worker
1326*d83cc019SAndroid Build Coastguard Worker igt_subtest("bonded-cork")
1327*d83cc019SAndroid Build Coastguard Worker bonded(i915, CORK);
1328*d83cc019SAndroid Build Coastguard Worker
1329*d83cc019SAndroid Build Coastguard Worker igt_fixture {
1330*d83cc019SAndroid Build Coastguard Worker igt_stop_hang_detector();
1331*d83cc019SAndroid Build Coastguard Worker }
1332*d83cc019SAndroid Build Coastguard Worker }
1333