xref: /aosp_15_r20/external/igt-gpu-tools/tests/i915/gem_exec_balancer.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
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