xref: /aosp_15_r20/external/igt-gpu-tools/benchmarks/gem_wsim.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2017 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 
25*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
26*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
27*d83cc019SAndroid Build Coastguard Worker #include <stdint.h>
28*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
29*d83cc019SAndroid Build Coastguard Worker #include <string.h>
30*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
31*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
32*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
33*d83cc019SAndroid Build Coastguard Worker #include <poll.h>
34*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
35*d83cc019SAndroid Build Coastguard Worker #include <sys/types.h>
36*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
37*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
38*d83cc019SAndroid Build Coastguard Worker #include <sys/wait.h>
39*d83cc019SAndroid Build Coastguard Worker #include <time.h>
40*d83cc019SAndroid Build Coastguard Worker #include <assert.h>
41*d83cc019SAndroid Build Coastguard Worker #include <limits.h>
42*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
43*d83cc019SAndroid Build Coastguard Worker 
44*d83cc019SAndroid Build Coastguard Worker #include "intel_chipset.h"
45*d83cc019SAndroid Build Coastguard Worker #include "intel_reg.h"
46*d83cc019SAndroid Build Coastguard Worker #include "drm.h"
47*d83cc019SAndroid Build Coastguard Worker #include "ioctl_wrappers.h"
48*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
49*d83cc019SAndroid Build Coastguard Worker 
50*d83cc019SAndroid Build Coastguard Worker #include "intel_io.h"
51*d83cc019SAndroid Build Coastguard Worker #include "igt_aux.h"
52*d83cc019SAndroid Build Coastguard Worker #include "igt_rand.h"
53*d83cc019SAndroid Build Coastguard Worker #include "igt_perf.h"
54*d83cc019SAndroid Build Coastguard Worker #include "sw_sync.h"
55*d83cc019SAndroid Build Coastguard Worker #include "i915/gem_mman.h"
56*d83cc019SAndroid Build Coastguard Worker 
57*d83cc019SAndroid Build Coastguard Worker #include "ewma.h"
58*d83cc019SAndroid Build Coastguard Worker 
59*d83cc019SAndroid Build Coastguard Worker enum intel_engine_id {
60*d83cc019SAndroid Build Coastguard Worker 	DEFAULT,
61*d83cc019SAndroid Build Coastguard Worker 	RCS,
62*d83cc019SAndroid Build Coastguard Worker 	BCS,
63*d83cc019SAndroid Build Coastguard Worker 	VCS,
64*d83cc019SAndroid Build Coastguard Worker 	VCS1,
65*d83cc019SAndroid Build Coastguard Worker 	VCS2,
66*d83cc019SAndroid Build Coastguard Worker 	VECS,
67*d83cc019SAndroid Build Coastguard Worker 	NUM_ENGINES
68*d83cc019SAndroid Build Coastguard Worker };
69*d83cc019SAndroid Build Coastguard Worker 
70*d83cc019SAndroid Build Coastguard Worker struct duration {
71*d83cc019SAndroid Build Coastguard Worker 	unsigned int min, max;
72*d83cc019SAndroid Build Coastguard Worker };
73*d83cc019SAndroid Build Coastguard Worker 
74*d83cc019SAndroid Build Coastguard Worker enum w_type
75*d83cc019SAndroid Build Coastguard Worker {
76*d83cc019SAndroid Build Coastguard Worker 	BATCH,
77*d83cc019SAndroid Build Coastguard Worker 	SYNC,
78*d83cc019SAndroid Build Coastguard Worker 	DELAY,
79*d83cc019SAndroid Build Coastguard Worker 	PERIOD,
80*d83cc019SAndroid Build Coastguard Worker 	THROTTLE,
81*d83cc019SAndroid Build Coastguard Worker 	QD_THROTTLE,
82*d83cc019SAndroid Build Coastguard Worker 	SW_FENCE,
83*d83cc019SAndroid Build Coastguard Worker 	SW_FENCE_SIGNAL,
84*d83cc019SAndroid Build Coastguard Worker 	CTX_PRIORITY,
85*d83cc019SAndroid Build Coastguard Worker 	PREEMPTION,
86*d83cc019SAndroid Build Coastguard Worker 	ENGINE_MAP,
87*d83cc019SAndroid Build Coastguard Worker 	LOAD_BALANCE,
88*d83cc019SAndroid Build Coastguard Worker 	BOND,
89*d83cc019SAndroid Build Coastguard Worker 	TERMINATE,
90*d83cc019SAndroid Build Coastguard Worker 	SSEU
91*d83cc019SAndroid Build Coastguard Worker };
92*d83cc019SAndroid Build Coastguard Worker 
93*d83cc019SAndroid Build Coastguard Worker struct deps
94*d83cc019SAndroid Build Coastguard Worker {
95*d83cc019SAndroid Build Coastguard Worker 	int nr;
96*d83cc019SAndroid Build Coastguard Worker 	bool submit_fence;
97*d83cc019SAndroid Build Coastguard Worker 	int *list;
98*d83cc019SAndroid Build Coastguard Worker };
99*d83cc019SAndroid Build Coastguard Worker 
100*d83cc019SAndroid Build Coastguard Worker struct w_arg {
101*d83cc019SAndroid Build Coastguard Worker 	char *filename;
102*d83cc019SAndroid Build Coastguard Worker 	char *desc;
103*d83cc019SAndroid Build Coastguard Worker 	int prio;
104*d83cc019SAndroid Build Coastguard Worker 	bool sseu;
105*d83cc019SAndroid Build Coastguard Worker };
106*d83cc019SAndroid Build Coastguard Worker 
107*d83cc019SAndroid Build Coastguard Worker struct bond {
108*d83cc019SAndroid Build Coastguard Worker 	uint64_t mask;
109*d83cc019SAndroid Build Coastguard Worker 	enum intel_engine_id master;
110*d83cc019SAndroid Build Coastguard Worker };
111*d83cc019SAndroid Build Coastguard Worker 
112*d83cc019SAndroid Build Coastguard Worker struct w_step
113*d83cc019SAndroid Build Coastguard Worker {
114*d83cc019SAndroid Build Coastguard Worker 	/* Workload step metadata */
115*d83cc019SAndroid Build Coastguard Worker 	enum w_type type;
116*d83cc019SAndroid Build Coastguard Worker 	unsigned int context;
117*d83cc019SAndroid Build Coastguard Worker 	unsigned int engine;
118*d83cc019SAndroid Build Coastguard Worker 	struct duration duration;
119*d83cc019SAndroid Build Coastguard Worker 	bool unbound_duration;
120*d83cc019SAndroid Build Coastguard Worker 	struct deps data_deps;
121*d83cc019SAndroid Build Coastguard Worker 	struct deps fence_deps;
122*d83cc019SAndroid Build Coastguard Worker 	int emit_fence;
123*d83cc019SAndroid Build Coastguard Worker 	union {
124*d83cc019SAndroid Build Coastguard Worker 		int sync;
125*d83cc019SAndroid Build Coastguard Worker 		int delay;
126*d83cc019SAndroid Build Coastguard Worker 		int period;
127*d83cc019SAndroid Build Coastguard Worker 		int target;
128*d83cc019SAndroid Build Coastguard Worker 		int throttle;
129*d83cc019SAndroid Build Coastguard Worker 		int fence_signal;
130*d83cc019SAndroid Build Coastguard Worker 		int priority;
131*d83cc019SAndroid Build Coastguard Worker 		struct {
132*d83cc019SAndroid Build Coastguard Worker 			unsigned int engine_map_count;
133*d83cc019SAndroid Build Coastguard Worker 			enum intel_engine_id *engine_map;
134*d83cc019SAndroid Build Coastguard Worker 		};
135*d83cc019SAndroid Build Coastguard Worker 		bool load_balance;
136*d83cc019SAndroid Build Coastguard Worker 		struct {
137*d83cc019SAndroid Build Coastguard Worker 			uint64_t bond_mask;
138*d83cc019SAndroid Build Coastguard Worker 			enum intel_engine_id bond_master;
139*d83cc019SAndroid Build Coastguard Worker 		};
140*d83cc019SAndroid Build Coastguard Worker 		int sseu;
141*d83cc019SAndroid Build Coastguard Worker 	};
142*d83cc019SAndroid Build Coastguard Worker 
143*d83cc019SAndroid Build Coastguard Worker 	/* Implementation details */
144*d83cc019SAndroid Build Coastguard Worker 	unsigned int idx;
145*d83cc019SAndroid Build Coastguard Worker 	struct igt_list rq_link;
146*d83cc019SAndroid Build Coastguard Worker 	unsigned int request;
147*d83cc019SAndroid Build Coastguard Worker 	unsigned int preempt_us;
148*d83cc019SAndroid Build Coastguard Worker 
149*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 eb;
150*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 *obj;
151*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry reloc[5];
152*d83cc019SAndroid Build Coastguard Worker 	unsigned long bb_sz;
153*d83cc019SAndroid Build Coastguard Worker 	uint32_t bb_handle;
154*d83cc019SAndroid Build Coastguard Worker 	uint32_t *seqno_value;
155*d83cc019SAndroid Build Coastguard Worker 	uint32_t *seqno_address;
156*d83cc019SAndroid Build Coastguard Worker 	uint32_t *rt0_value;
157*d83cc019SAndroid Build Coastguard Worker 	uint32_t *rt0_address;
158*d83cc019SAndroid Build Coastguard Worker 	uint32_t *rt1_address;
159*d83cc019SAndroid Build Coastguard Worker 	uint32_t *latch_value;
160*d83cc019SAndroid Build Coastguard Worker 	uint32_t *latch_address;
161*d83cc019SAndroid Build Coastguard Worker 	uint32_t *recursive_bb_start;
162*d83cc019SAndroid Build Coastguard Worker };
163*d83cc019SAndroid Build Coastguard Worker 
164*d83cc019SAndroid Build Coastguard Worker DECLARE_EWMA(uint64_t, rt, 4, 2)
165*d83cc019SAndroid Build Coastguard Worker 
166*d83cc019SAndroid Build Coastguard Worker struct ctx {
167*d83cc019SAndroid Build Coastguard Worker 	uint32_t id;
168*d83cc019SAndroid Build Coastguard Worker 	int priority;
169*d83cc019SAndroid Build Coastguard Worker 	unsigned int engine_map_count;
170*d83cc019SAndroid Build Coastguard Worker 	enum intel_engine_id *engine_map;
171*d83cc019SAndroid Build Coastguard Worker 	unsigned int bond_count;
172*d83cc019SAndroid Build Coastguard Worker 	struct bond *bonds;
173*d83cc019SAndroid Build Coastguard Worker 	bool targets_instance;
174*d83cc019SAndroid Build Coastguard Worker 	bool wants_balance;
175*d83cc019SAndroid Build Coastguard Worker 	unsigned int static_vcs;
176*d83cc019SAndroid Build Coastguard Worker 	uint64_t sseu;
177*d83cc019SAndroid Build Coastguard Worker };
178*d83cc019SAndroid Build Coastguard Worker 
179*d83cc019SAndroid Build Coastguard Worker struct workload
180*d83cc019SAndroid Build Coastguard Worker {
181*d83cc019SAndroid Build Coastguard Worker 	unsigned int id;
182*d83cc019SAndroid Build Coastguard Worker 
183*d83cc019SAndroid Build Coastguard Worker 	unsigned int nr_steps;
184*d83cc019SAndroid Build Coastguard Worker 	struct w_step *steps;
185*d83cc019SAndroid Build Coastguard Worker 	int prio;
186*d83cc019SAndroid Build Coastguard Worker 	bool sseu;
187*d83cc019SAndroid Build Coastguard Worker 
188*d83cc019SAndroid Build Coastguard Worker 	pthread_t thread;
189*d83cc019SAndroid Build Coastguard Worker 	bool run;
190*d83cc019SAndroid Build Coastguard Worker 	bool background;
191*d83cc019SAndroid Build Coastguard Worker 	const struct workload_balancer *balancer;
192*d83cc019SAndroid Build Coastguard Worker 	unsigned int repeat;
193*d83cc019SAndroid Build Coastguard Worker 	unsigned int flags;
194*d83cc019SAndroid Build Coastguard Worker 	bool print_stats;
195*d83cc019SAndroid Build Coastguard Worker 
196*d83cc019SAndroid Build Coastguard Worker 	uint32_t bb_prng;
197*d83cc019SAndroid Build Coastguard Worker 	uint32_t prng;
198*d83cc019SAndroid Build Coastguard Worker 
199*d83cc019SAndroid Build Coastguard Worker 	struct timespec repeat_start;
200*d83cc019SAndroid Build Coastguard Worker 
201*d83cc019SAndroid Build Coastguard Worker 	unsigned int nr_ctxs;
202*d83cc019SAndroid Build Coastguard Worker 	struct ctx *ctx_list;
203*d83cc019SAndroid Build Coastguard Worker 
204*d83cc019SAndroid Build Coastguard Worker 	int sync_timeline;
205*d83cc019SAndroid Build Coastguard Worker 	uint32_t sync_seqno;
206*d83cc019SAndroid Build Coastguard Worker 
207*d83cc019SAndroid Build Coastguard Worker 	uint32_t seqno[NUM_ENGINES];
208*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 status_object[2];
209*d83cc019SAndroid Build Coastguard Worker 	uint32_t *status_page;
210*d83cc019SAndroid Build Coastguard Worker 	uint32_t *status_cs;
211*d83cc019SAndroid Build Coastguard Worker 	unsigned int vcs_rr;
212*d83cc019SAndroid Build Coastguard Worker 
213*d83cc019SAndroid Build Coastguard Worker 	unsigned long qd_sum[NUM_ENGINES];
214*d83cc019SAndroid Build Coastguard Worker 	unsigned long nr_bb[NUM_ENGINES];
215*d83cc019SAndroid Build Coastguard Worker 
216*d83cc019SAndroid Build Coastguard Worker 	struct igt_list requests[NUM_ENGINES];
217*d83cc019SAndroid Build Coastguard Worker 	unsigned int nrequest[NUM_ENGINES];
218*d83cc019SAndroid Build Coastguard Worker 
219*d83cc019SAndroid Build Coastguard Worker 	struct workload *global_wrk;
220*d83cc019SAndroid Build Coastguard Worker 	const struct workload_balancer *global_balancer;
221*d83cc019SAndroid Build Coastguard Worker 	pthread_mutex_t mutex;
222*d83cc019SAndroid Build Coastguard Worker 
223*d83cc019SAndroid Build Coastguard Worker 	union {
224*d83cc019SAndroid Build Coastguard Worker 		struct rtavg {
225*d83cc019SAndroid Build Coastguard Worker 			struct ewma_rt avg[NUM_ENGINES];
226*d83cc019SAndroid Build Coastguard Worker 			uint32_t last[NUM_ENGINES];
227*d83cc019SAndroid Build Coastguard Worker 		} rt;
228*d83cc019SAndroid Build Coastguard Worker 	};
229*d83cc019SAndroid Build Coastguard Worker 
230*d83cc019SAndroid Build Coastguard Worker 	struct busy_balancer {
231*d83cc019SAndroid Build Coastguard Worker 		int fd;
232*d83cc019SAndroid Build Coastguard Worker 		bool first;
233*d83cc019SAndroid Build Coastguard Worker 		unsigned int num_engines;
234*d83cc019SAndroid Build Coastguard Worker 		unsigned int engine_map[NUM_ENGINES];
235*d83cc019SAndroid Build Coastguard Worker 		uint64_t t_prev;
236*d83cc019SAndroid Build Coastguard Worker 		uint64_t prev[NUM_ENGINES];
237*d83cc019SAndroid Build Coastguard Worker 		double busy[NUM_ENGINES];
238*d83cc019SAndroid Build Coastguard Worker 	} busy_balancer;
239*d83cc019SAndroid Build Coastguard Worker };
240*d83cc019SAndroid Build Coastguard Worker 
241*d83cc019SAndroid Build Coastguard Worker static const unsigned int nop_calibration_us = 1000;
242*d83cc019SAndroid Build Coastguard Worker static unsigned long nop_calibration;
243*d83cc019SAndroid Build Coastguard Worker 
244*d83cc019SAndroid Build Coastguard Worker static unsigned int master_prng;
245*d83cc019SAndroid Build Coastguard Worker 
246*d83cc019SAndroid Build Coastguard Worker static unsigned int context_vcs_rr;
247*d83cc019SAndroid Build Coastguard Worker 
248*d83cc019SAndroid Build Coastguard Worker static int verbose = 1;
249*d83cc019SAndroid Build Coastguard Worker static int fd;
250*d83cc019SAndroid Build Coastguard Worker static struct drm_i915_gem_context_param_sseu device_sseu = {
251*d83cc019SAndroid Build Coastguard Worker 	.slice_mask = -1 /* Force read on first use. */
252*d83cc019SAndroid Build Coastguard Worker };
253*d83cc019SAndroid Build Coastguard Worker 
254*d83cc019SAndroid Build Coastguard Worker #define SWAPVCS		(1<<0)
255*d83cc019SAndroid Build Coastguard Worker #define SEQNO		(1<<1)
256*d83cc019SAndroid Build Coastguard Worker #define BALANCE		(1<<2)
257*d83cc019SAndroid Build Coastguard Worker #define RT		(1<<3)
258*d83cc019SAndroid Build Coastguard Worker #define VCS2REMAP	(1<<4)
259*d83cc019SAndroid Build Coastguard Worker #define INITVCSRR	(1<<5)
260*d83cc019SAndroid Build Coastguard Worker #define SYNCEDCLIENTS	(1<<6)
261*d83cc019SAndroid Build Coastguard Worker #define HEARTBEAT	(1<<7)
262*d83cc019SAndroid Build Coastguard Worker #define GLOBAL_BALANCE	(1<<8)
263*d83cc019SAndroid Build Coastguard Worker #define DEPSYNC		(1<<9)
264*d83cc019SAndroid Build Coastguard Worker #define I915		(1<<10)
265*d83cc019SAndroid Build Coastguard Worker #define SSEU		(1<<11)
266*d83cc019SAndroid Build Coastguard Worker 
267*d83cc019SAndroid Build Coastguard Worker #define SEQNO_IDX(engine) ((engine) * 16)
268*d83cc019SAndroid Build Coastguard Worker #define SEQNO_OFFSET(engine) (SEQNO_IDX(engine) * sizeof(uint32_t))
269*d83cc019SAndroid Build Coastguard Worker 
270*d83cc019SAndroid Build Coastguard Worker #define RCS_TIMESTAMP (0x2000 + 0x358)
271*d83cc019SAndroid Build Coastguard Worker #define REG(x) (volatile uint32_t *)((volatile char *)igt_global_mmio + x)
272*d83cc019SAndroid Build Coastguard Worker 
273*d83cc019SAndroid Build Coastguard Worker static const char *ring_str_map[NUM_ENGINES] = {
274*d83cc019SAndroid Build Coastguard Worker 	[DEFAULT] = "DEFAULT",
275*d83cc019SAndroid Build Coastguard Worker 	[RCS] = "RCS",
276*d83cc019SAndroid Build Coastguard Worker 	[BCS] = "BCS",
277*d83cc019SAndroid Build Coastguard Worker 	[VCS] = "VCS",
278*d83cc019SAndroid Build Coastguard Worker 	[VCS1] = "VCS1",
279*d83cc019SAndroid Build Coastguard Worker 	[VCS2] = "VCS2",
280*d83cc019SAndroid Build Coastguard Worker 	[VECS] = "VECS",
281*d83cc019SAndroid Build Coastguard Worker };
282*d83cc019SAndroid Build Coastguard Worker 
283*d83cc019SAndroid Build Coastguard Worker static int
parse_dependencies(unsigned int nr_steps,struct w_step * w,char * _desc)284*d83cc019SAndroid Build Coastguard Worker parse_dependencies(unsigned int nr_steps, struct w_step *w, char *_desc)
285*d83cc019SAndroid Build Coastguard Worker {
286*d83cc019SAndroid Build Coastguard Worker 	char *desc = strdup(_desc);
287*d83cc019SAndroid Build Coastguard Worker 	char *token, *tctx = NULL, *tstart = desc;
288*d83cc019SAndroid Build Coastguard Worker 
289*d83cc019SAndroid Build Coastguard Worker 	igt_assert(desc);
290*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!w->data_deps.nr && w->data_deps.nr == w->fence_deps.nr);
291*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!w->data_deps.list &&
292*d83cc019SAndroid Build Coastguard Worker 		   w->data_deps.list == w->fence_deps.list);
293*d83cc019SAndroid Build Coastguard Worker 
294*d83cc019SAndroid Build Coastguard Worker 	while ((token = strtok_r(tstart, "/", &tctx)) != NULL) {
295*d83cc019SAndroid Build Coastguard Worker 		bool submit_fence = false;
296*d83cc019SAndroid Build Coastguard Worker 		char *str = token;
297*d83cc019SAndroid Build Coastguard Worker 		struct deps *deps;
298*d83cc019SAndroid Build Coastguard Worker 		int dep;
299*d83cc019SAndroid Build Coastguard Worker 
300*d83cc019SAndroid Build Coastguard Worker 		tstart = NULL;
301*d83cc019SAndroid Build Coastguard Worker 
302*d83cc019SAndroid Build Coastguard Worker 		if (str[0] == '-' || (str[0] >= '0' && str[0] <= '9')) {
303*d83cc019SAndroid Build Coastguard Worker 			deps = &w->data_deps;
304*d83cc019SAndroid Build Coastguard Worker 		} else {
305*d83cc019SAndroid Build Coastguard Worker 			if (str[0] == 's')
306*d83cc019SAndroid Build Coastguard Worker 				submit_fence = true;
307*d83cc019SAndroid Build Coastguard Worker 			else if (str[0] != 'f')
308*d83cc019SAndroid Build Coastguard Worker 				return -1;
309*d83cc019SAndroid Build Coastguard Worker 
310*d83cc019SAndroid Build Coastguard Worker 			deps = &w->fence_deps;
311*d83cc019SAndroid Build Coastguard Worker 			str++;
312*d83cc019SAndroid Build Coastguard Worker 		}
313*d83cc019SAndroid Build Coastguard Worker 
314*d83cc019SAndroid Build Coastguard Worker 		dep = atoi(str);
315*d83cc019SAndroid Build Coastguard Worker 		if (dep > 0 || ((int)nr_steps + dep) < 0) {
316*d83cc019SAndroid Build Coastguard Worker 			if (deps->list)
317*d83cc019SAndroid Build Coastguard Worker 				free(deps->list);
318*d83cc019SAndroid Build Coastguard Worker 			return -1;
319*d83cc019SAndroid Build Coastguard Worker 		}
320*d83cc019SAndroid Build Coastguard Worker 
321*d83cc019SAndroid Build Coastguard Worker 		if (dep < 0) {
322*d83cc019SAndroid Build Coastguard Worker 			deps->nr++;
323*d83cc019SAndroid Build Coastguard Worker 			/* Multiple fences not yet supported. */
324*d83cc019SAndroid Build Coastguard Worker 			igt_assert(deps->nr == 1 || deps != &w->fence_deps);
325*d83cc019SAndroid Build Coastguard Worker 			deps->list = realloc(deps->list,
326*d83cc019SAndroid Build Coastguard Worker 					     sizeof(*deps->list) * deps->nr);
327*d83cc019SAndroid Build Coastguard Worker 			igt_assert(deps->list);
328*d83cc019SAndroid Build Coastguard Worker 			deps->list[deps->nr - 1] = dep;
329*d83cc019SAndroid Build Coastguard Worker 			deps->submit_fence = submit_fence;
330*d83cc019SAndroid Build Coastguard Worker 		}
331*d83cc019SAndroid Build Coastguard Worker 	}
332*d83cc019SAndroid Build Coastguard Worker 
333*d83cc019SAndroid Build Coastguard Worker 	free(desc);
334*d83cc019SAndroid Build Coastguard Worker 
335*d83cc019SAndroid Build Coastguard Worker 	return 0;
336*d83cc019SAndroid Build Coastguard Worker }
337*d83cc019SAndroid Build Coastguard Worker 
338*d83cc019SAndroid Build Coastguard Worker static void __attribute__((format(printf, 1, 2)))
wsim_err(const char * fmt,...)339*d83cc019SAndroid Build Coastguard Worker wsim_err(const char *fmt, ...)
340*d83cc019SAndroid Build Coastguard Worker {
341*d83cc019SAndroid Build Coastguard Worker 	va_list ap;
342*d83cc019SAndroid Build Coastguard Worker 
343*d83cc019SAndroid Build Coastguard Worker 	if (!verbose)
344*d83cc019SAndroid Build Coastguard Worker 		return;
345*d83cc019SAndroid Build Coastguard Worker 
346*d83cc019SAndroid Build Coastguard Worker 	va_start(ap, fmt);
347*d83cc019SAndroid Build Coastguard Worker 	vfprintf(stderr, fmt, ap);
348*d83cc019SAndroid Build Coastguard Worker 	va_end(ap);
349*d83cc019SAndroid Build Coastguard Worker }
350*d83cc019SAndroid Build Coastguard Worker 
351*d83cc019SAndroid Build Coastguard Worker #define check_arg(cond, fmt, ...) \
352*d83cc019SAndroid Build Coastguard Worker { \
353*d83cc019SAndroid Build Coastguard Worker 	if (cond) { \
354*d83cc019SAndroid Build Coastguard Worker 		wsim_err(fmt, __VA_ARGS__); \
355*d83cc019SAndroid Build Coastguard Worker 		return NULL; \
356*d83cc019SAndroid Build Coastguard Worker 	} \
357*d83cc019SAndroid Build Coastguard Worker }
358*d83cc019SAndroid Build Coastguard Worker 
str_to_engine(const char * str)359*d83cc019SAndroid Build Coastguard Worker static int str_to_engine(const char *str)
360*d83cc019SAndroid Build Coastguard Worker {
361*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
362*d83cc019SAndroid Build Coastguard Worker 
363*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(ring_str_map); i++) {
364*d83cc019SAndroid Build Coastguard Worker 		if (!strcasecmp(str, ring_str_map[i]))
365*d83cc019SAndroid Build Coastguard Worker 			return i;
366*d83cc019SAndroid Build Coastguard Worker 	}
367*d83cc019SAndroid Build Coastguard Worker 
368*d83cc019SAndroid Build Coastguard Worker 	return -1;
369*d83cc019SAndroid Build Coastguard Worker }
370*d83cc019SAndroid Build Coastguard Worker 
371*d83cc019SAndroid Build Coastguard Worker static bool __engines_queried;
372*d83cc019SAndroid Build Coastguard Worker static unsigned int __num_engines;
373*d83cc019SAndroid Build Coastguard Worker static struct i915_engine_class_instance *__engines;
374*d83cc019SAndroid Build Coastguard Worker 
375*d83cc019SAndroid Build Coastguard Worker static int
__i915_query(int i915,struct drm_i915_query * q)376*d83cc019SAndroid Build Coastguard Worker __i915_query(int i915, struct drm_i915_query *q)
377*d83cc019SAndroid Build Coastguard Worker {
378*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(i915, DRM_IOCTL_I915_QUERY, q))
379*d83cc019SAndroid Build Coastguard Worker 		return -errno;
380*d83cc019SAndroid Build Coastguard Worker 	return 0;
381*d83cc019SAndroid Build Coastguard Worker }
382*d83cc019SAndroid Build Coastguard Worker 
383*d83cc019SAndroid Build Coastguard Worker static int
__i915_query_items(int i915,struct drm_i915_query_item * items,uint32_t n_items)384*d83cc019SAndroid Build Coastguard Worker __i915_query_items(int i915, struct drm_i915_query_item *items, uint32_t n_items)
385*d83cc019SAndroid Build Coastguard Worker {
386*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query q = {
387*d83cc019SAndroid Build Coastguard Worker 		.num_items = n_items,
388*d83cc019SAndroid Build Coastguard Worker 		.items_ptr = to_user_pointer(items),
389*d83cc019SAndroid Build Coastguard Worker 	};
390*d83cc019SAndroid Build Coastguard Worker 	return __i915_query(i915, &q);
391*d83cc019SAndroid Build Coastguard Worker }
392*d83cc019SAndroid Build Coastguard Worker 
393*d83cc019SAndroid Build Coastguard Worker static void
i915_query_items(int i915,struct drm_i915_query_item * items,uint32_t n_items)394*d83cc019SAndroid Build Coastguard Worker i915_query_items(int i915, struct drm_i915_query_item *items, uint32_t n_items)
395*d83cc019SAndroid Build Coastguard Worker {
396*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__i915_query_items(i915, items, n_items), 0);
397*d83cc019SAndroid Build Coastguard Worker }
398*d83cc019SAndroid Build Coastguard Worker 
has_engine_query(int i915)399*d83cc019SAndroid Build Coastguard Worker static bool has_engine_query(int i915)
400*d83cc019SAndroid Build Coastguard Worker {
401*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_query_item item = {
402*d83cc019SAndroid Build Coastguard Worker 		.query_id = DRM_I915_QUERY_ENGINE_INFO,
403*d83cc019SAndroid Build Coastguard Worker 	};
404*d83cc019SAndroid Build Coastguard Worker 
405*d83cc019SAndroid Build Coastguard Worker 	return __i915_query_items(i915, &item, 1) == 0 && item.length > 0;
406*d83cc019SAndroid Build Coastguard Worker }
407*d83cc019SAndroid Build Coastguard Worker 
query_engines(void)408*d83cc019SAndroid Build Coastguard Worker static void query_engines(void)
409*d83cc019SAndroid Build Coastguard Worker {
410*d83cc019SAndroid Build Coastguard Worker 	struct i915_engine_class_instance *engines;
411*d83cc019SAndroid Build Coastguard Worker 	unsigned int num;
412*d83cc019SAndroid Build Coastguard Worker 
413*d83cc019SAndroid Build Coastguard Worker 	if (__engines_queried)
414*d83cc019SAndroid Build Coastguard Worker 		return;
415*d83cc019SAndroid Build Coastguard Worker 
416*d83cc019SAndroid Build Coastguard Worker 	__engines_queried = true;
417*d83cc019SAndroid Build Coastguard Worker 
418*d83cc019SAndroid Build Coastguard Worker 	if (!has_engine_query(fd)) {
419*d83cc019SAndroid Build Coastguard Worker 		unsigned int num_bsd = gem_has_bsd(fd) + gem_has_bsd2(fd);
420*d83cc019SAndroid Build Coastguard Worker 		unsigned int i = 0;
421*d83cc019SAndroid Build Coastguard Worker 
422*d83cc019SAndroid Build Coastguard Worker 		igt_assert(num_bsd);
423*d83cc019SAndroid Build Coastguard Worker 
424*d83cc019SAndroid Build Coastguard Worker 		num = 1 + num_bsd;
425*d83cc019SAndroid Build Coastguard Worker 
426*d83cc019SAndroid Build Coastguard Worker 		if (gem_has_blt(fd))
427*d83cc019SAndroid Build Coastguard Worker 			num++;
428*d83cc019SAndroid Build Coastguard Worker 
429*d83cc019SAndroid Build Coastguard Worker 		if (gem_has_vebox(fd))
430*d83cc019SAndroid Build Coastguard Worker 			num++;
431*d83cc019SAndroid Build Coastguard Worker 
432*d83cc019SAndroid Build Coastguard Worker 		engines = calloc(num,
433*d83cc019SAndroid Build Coastguard Worker 				 sizeof(struct i915_engine_class_instance));
434*d83cc019SAndroid Build Coastguard Worker 		igt_assert(engines);
435*d83cc019SAndroid Build Coastguard Worker 
436*d83cc019SAndroid Build Coastguard Worker 		engines[i].engine_class = I915_ENGINE_CLASS_RENDER;
437*d83cc019SAndroid Build Coastguard Worker 		engines[i].engine_instance = 0;
438*d83cc019SAndroid Build Coastguard Worker 		i++;
439*d83cc019SAndroid Build Coastguard Worker 
440*d83cc019SAndroid Build Coastguard Worker 		if (gem_has_blt(fd)) {
441*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_class = I915_ENGINE_CLASS_COPY;
442*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_instance = 0;
443*d83cc019SAndroid Build Coastguard Worker 			i++;
444*d83cc019SAndroid Build Coastguard Worker 		}
445*d83cc019SAndroid Build Coastguard Worker 
446*d83cc019SAndroid Build Coastguard Worker 		if (gem_has_bsd(fd)) {
447*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_class = I915_ENGINE_CLASS_VIDEO;
448*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_instance = 0;
449*d83cc019SAndroid Build Coastguard Worker 			i++;
450*d83cc019SAndroid Build Coastguard Worker 		}
451*d83cc019SAndroid Build Coastguard Worker 
452*d83cc019SAndroid Build Coastguard Worker 		if (gem_has_bsd2(fd)) {
453*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_class = I915_ENGINE_CLASS_VIDEO;
454*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_instance = 1;
455*d83cc019SAndroid Build Coastguard Worker 			i++;
456*d83cc019SAndroid Build Coastguard Worker 		}
457*d83cc019SAndroid Build Coastguard Worker 
458*d83cc019SAndroid Build Coastguard Worker 		if (gem_has_vebox(fd)) {
459*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_class =
460*d83cc019SAndroid Build Coastguard Worker 				I915_ENGINE_CLASS_VIDEO_ENHANCE;
461*d83cc019SAndroid Build Coastguard Worker 			engines[i].engine_instance = 0;
462*d83cc019SAndroid Build Coastguard Worker 			i++;
463*d83cc019SAndroid Build Coastguard Worker 		}
464*d83cc019SAndroid Build Coastguard Worker 	} else {
465*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_query_engine_info *engine_info;
466*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_query_item item = {
467*d83cc019SAndroid Build Coastguard Worker 			.query_id = DRM_I915_QUERY_ENGINE_INFO,
468*d83cc019SAndroid Build Coastguard Worker 		};
469*d83cc019SAndroid Build Coastguard Worker 		const unsigned int sz = 4096;
470*d83cc019SAndroid Build Coastguard Worker 		unsigned int i;
471*d83cc019SAndroid Build Coastguard Worker 
472*d83cc019SAndroid Build Coastguard Worker 		engine_info = malloc(sz);
473*d83cc019SAndroid Build Coastguard Worker 		igt_assert(engine_info);
474*d83cc019SAndroid Build Coastguard Worker 		memset(engine_info, 0, sz);
475*d83cc019SAndroid Build Coastguard Worker 
476*d83cc019SAndroid Build Coastguard Worker 		item.data_ptr = to_user_pointer(engine_info);
477*d83cc019SAndroid Build Coastguard Worker 		item.length = sz;
478*d83cc019SAndroid Build Coastguard Worker 
479*d83cc019SAndroid Build Coastguard Worker 		i915_query_items(fd, &item, 1);
480*d83cc019SAndroid Build Coastguard Worker 		igt_assert(item.length > 0);
481*d83cc019SAndroid Build Coastguard Worker 		igt_assert(item.length <= sz);
482*d83cc019SAndroid Build Coastguard Worker 
483*d83cc019SAndroid Build Coastguard Worker 		num = engine_info->num_engines;
484*d83cc019SAndroid Build Coastguard Worker 
485*d83cc019SAndroid Build Coastguard Worker 		engines = calloc(num,
486*d83cc019SAndroid Build Coastguard Worker 				 sizeof(struct i915_engine_class_instance));
487*d83cc019SAndroid Build Coastguard Worker 		igt_assert(engines);
488*d83cc019SAndroid Build Coastguard Worker 
489*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < num; i++) {
490*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_engine_info *engine =
491*d83cc019SAndroid Build Coastguard Worker 				(struct drm_i915_engine_info *)&engine_info->engines[i];
492*d83cc019SAndroid Build Coastguard Worker 
493*d83cc019SAndroid Build Coastguard Worker 			engines[i] = engine->engine;
494*d83cc019SAndroid Build Coastguard Worker 		}
495*d83cc019SAndroid Build Coastguard Worker 	}
496*d83cc019SAndroid Build Coastguard Worker 
497*d83cc019SAndroid Build Coastguard Worker 	__engines = engines;
498*d83cc019SAndroid Build Coastguard Worker 	__num_engines = num;
499*d83cc019SAndroid Build Coastguard Worker }
500*d83cc019SAndroid Build Coastguard Worker 
num_engines_in_class(enum intel_engine_id class)501*d83cc019SAndroid Build Coastguard Worker static unsigned int num_engines_in_class(enum intel_engine_id class)
502*d83cc019SAndroid Build Coastguard Worker {
503*d83cc019SAndroid Build Coastguard Worker 	unsigned int i, count = 0;
504*d83cc019SAndroid Build Coastguard Worker 
505*d83cc019SAndroid Build Coastguard Worker 	igt_assert(class == VCS);
506*d83cc019SAndroid Build Coastguard Worker 
507*d83cc019SAndroid Build Coastguard Worker 	query_engines();
508*d83cc019SAndroid Build Coastguard Worker 
509*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < __num_engines; i++) {
510*d83cc019SAndroid Build Coastguard Worker 		if (__engines[i].engine_class == I915_ENGINE_CLASS_VIDEO)
511*d83cc019SAndroid Build Coastguard Worker 			count++;
512*d83cc019SAndroid Build Coastguard Worker 	}
513*d83cc019SAndroid Build Coastguard Worker 
514*d83cc019SAndroid Build Coastguard Worker 	igt_assert(count);
515*d83cc019SAndroid Build Coastguard Worker 	return count;
516*d83cc019SAndroid Build Coastguard Worker }
517*d83cc019SAndroid Build Coastguard Worker 
518*d83cc019SAndroid Build Coastguard Worker static void
fill_engines_class(struct i915_engine_class_instance * ci,enum intel_engine_id class)519*d83cc019SAndroid Build Coastguard Worker fill_engines_class(struct i915_engine_class_instance *ci,
520*d83cc019SAndroid Build Coastguard Worker 		   enum intel_engine_id class)
521*d83cc019SAndroid Build Coastguard Worker {
522*d83cc019SAndroid Build Coastguard Worker 	unsigned int i, j = 0;
523*d83cc019SAndroid Build Coastguard Worker 
524*d83cc019SAndroid Build Coastguard Worker 	igt_assert(class == VCS);
525*d83cc019SAndroid Build Coastguard Worker 
526*d83cc019SAndroid Build Coastguard Worker 	query_engines();
527*d83cc019SAndroid Build Coastguard Worker 
528*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < __num_engines; i++) {
529*d83cc019SAndroid Build Coastguard Worker 		if (__engines[i].engine_class != I915_ENGINE_CLASS_VIDEO)
530*d83cc019SAndroid Build Coastguard Worker 			continue;
531*d83cc019SAndroid Build Coastguard Worker 
532*d83cc019SAndroid Build Coastguard Worker 		ci[j].engine_class = __engines[i].engine_class;
533*d83cc019SAndroid Build Coastguard Worker 		ci[j].engine_instance = __engines[i].engine_instance;
534*d83cc019SAndroid Build Coastguard Worker 		j++;
535*d83cc019SAndroid Build Coastguard Worker 	}
536*d83cc019SAndroid Build Coastguard Worker }
537*d83cc019SAndroid Build Coastguard Worker 
538*d83cc019SAndroid Build Coastguard Worker static void
fill_engines_id_class(enum intel_engine_id * list,enum intel_engine_id class)539*d83cc019SAndroid Build Coastguard Worker fill_engines_id_class(enum intel_engine_id *list,
540*d83cc019SAndroid Build Coastguard Worker 		      enum intel_engine_id class)
541*d83cc019SAndroid Build Coastguard Worker {
542*d83cc019SAndroid Build Coastguard Worker 	enum intel_engine_id engine = VCS1;
543*d83cc019SAndroid Build Coastguard Worker 	unsigned int i, j = 0;
544*d83cc019SAndroid Build Coastguard Worker 
545*d83cc019SAndroid Build Coastguard Worker 	igt_assert(class == VCS);
546*d83cc019SAndroid Build Coastguard Worker 	igt_assert(num_engines_in_class(VCS) <= 2);
547*d83cc019SAndroid Build Coastguard Worker 
548*d83cc019SAndroid Build Coastguard Worker 	query_engines();
549*d83cc019SAndroid Build Coastguard Worker 
550*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < __num_engines; i++) {
551*d83cc019SAndroid Build Coastguard Worker 		if (__engines[i].engine_class != I915_ENGINE_CLASS_VIDEO)
552*d83cc019SAndroid Build Coastguard Worker 			continue;
553*d83cc019SAndroid Build Coastguard Worker 
554*d83cc019SAndroid Build Coastguard Worker 		list[j++] = engine++;
555*d83cc019SAndroid Build Coastguard Worker 	}
556*d83cc019SAndroid Build Coastguard Worker }
557*d83cc019SAndroid Build Coastguard Worker 
558*d83cc019SAndroid Build Coastguard Worker static unsigned int
find_physical_instance(enum intel_engine_id class,unsigned int logical)559*d83cc019SAndroid Build Coastguard Worker find_physical_instance(enum intel_engine_id class, unsigned int logical)
560*d83cc019SAndroid Build Coastguard Worker {
561*d83cc019SAndroid Build Coastguard Worker 	unsigned int i, j = 0;
562*d83cc019SAndroid Build Coastguard Worker 
563*d83cc019SAndroid Build Coastguard Worker 	igt_assert(class == VCS);
564*d83cc019SAndroid Build Coastguard Worker 
565*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < __num_engines; i++) {
566*d83cc019SAndroid Build Coastguard Worker 		if (__engines[i].engine_class != I915_ENGINE_CLASS_VIDEO)
567*d83cc019SAndroid Build Coastguard Worker 			continue;
568*d83cc019SAndroid Build Coastguard Worker 
569*d83cc019SAndroid Build Coastguard Worker 		/* Map logical to physical instances. */
570*d83cc019SAndroid Build Coastguard Worker 		if (logical == j++)
571*d83cc019SAndroid Build Coastguard Worker 			return __engines[i].engine_instance;
572*d83cc019SAndroid Build Coastguard Worker 	}
573*d83cc019SAndroid Build Coastguard Worker 
574*d83cc019SAndroid Build Coastguard Worker 	igt_assert(0);
575*d83cc019SAndroid Build Coastguard Worker 	return 0;
576*d83cc019SAndroid Build Coastguard Worker }
577*d83cc019SAndroid Build Coastguard Worker 
578*d83cc019SAndroid Build Coastguard Worker static struct i915_engine_class_instance
get_engine(enum intel_engine_id engine)579*d83cc019SAndroid Build Coastguard Worker get_engine(enum intel_engine_id engine)
580*d83cc019SAndroid Build Coastguard Worker {
581*d83cc019SAndroid Build Coastguard Worker 	struct i915_engine_class_instance ci;
582*d83cc019SAndroid Build Coastguard Worker 
583*d83cc019SAndroid Build Coastguard Worker 	query_engines();
584*d83cc019SAndroid Build Coastguard Worker 
585*d83cc019SAndroid Build Coastguard Worker 	switch (engine) {
586*d83cc019SAndroid Build Coastguard Worker 	case RCS:
587*d83cc019SAndroid Build Coastguard Worker 		ci.engine_class = I915_ENGINE_CLASS_RENDER;
588*d83cc019SAndroid Build Coastguard Worker 		ci.engine_instance = 0;
589*d83cc019SAndroid Build Coastguard Worker 		break;
590*d83cc019SAndroid Build Coastguard Worker 	case BCS:
591*d83cc019SAndroid Build Coastguard Worker 		ci.engine_class = I915_ENGINE_CLASS_COPY;
592*d83cc019SAndroid Build Coastguard Worker 		ci.engine_instance = 0;
593*d83cc019SAndroid Build Coastguard Worker 		break;
594*d83cc019SAndroid Build Coastguard Worker 	case VCS1:
595*d83cc019SAndroid Build Coastguard Worker 	case VCS2:
596*d83cc019SAndroid Build Coastguard Worker 		ci.engine_class = I915_ENGINE_CLASS_VIDEO;
597*d83cc019SAndroid Build Coastguard Worker 		ci.engine_instance = find_physical_instance(VCS, engine - VCS1);
598*d83cc019SAndroid Build Coastguard Worker 		break;
599*d83cc019SAndroid Build Coastguard Worker 	case VECS:
600*d83cc019SAndroid Build Coastguard Worker 		ci.engine_class = I915_ENGINE_CLASS_VIDEO_ENHANCE;
601*d83cc019SAndroid Build Coastguard Worker 		ci.engine_instance = 0;
602*d83cc019SAndroid Build Coastguard Worker 		break;
603*d83cc019SAndroid Build Coastguard Worker 	default:
604*d83cc019SAndroid Build Coastguard Worker 		igt_assert(0);
605*d83cc019SAndroid Build Coastguard Worker 	};
606*d83cc019SAndroid Build Coastguard Worker 
607*d83cc019SAndroid Build Coastguard Worker 	return ci;
608*d83cc019SAndroid Build Coastguard Worker }
609*d83cc019SAndroid Build Coastguard Worker 
parse_engine_map(struct w_step * step,const char * _str)610*d83cc019SAndroid Build Coastguard Worker static int parse_engine_map(struct w_step *step, const char *_str)
611*d83cc019SAndroid Build Coastguard Worker {
612*d83cc019SAndroid Build Coastguard Worker 	char *token, *tctx = NULL, *tstart = (char *)_str;
613*d83cc019SAndroid Build Coastguard Worker 
614*d83cc019SAndroid Build Coastguard Worker 	while ((token = strtok_r(tstart, "|", &tctx))) {
615*d83cc019SAndroid Build Coastguard Worker 		enum intel_engine_id engine;
616*d83cc019SAndroid Build Coastguard Worker 		unsigned int add;
617*d83cc019SAndroid Build Coastguard Worker 
618*d83cc019SAndroid Build Coastguard Worker 		tstart = NULL;
619*d83cc019SAndroid Build Coastguard Worker 
620*d83cc019SAndroid Build Coastguard Worker 		if (!strcmp(token, "DEFAULT"))
621*d83cc019SAndroid Build Coastguard Worker 			return -1;
622*d83cc019SAndroid Build Coastguard Worker 
623*d83cc019SAndroid Build Coastguard Worker 		engine = str_to_engine(token);
624*d83cc019SAndroid Build Coastguard Worker 		if ((int)engine < 0)
625*d83cc019SAndroid Build Coastguard Worker 			return -1;
626*d83cc019SAndroid Build Coastguard Worker 
627*d83cc019SAndroid Build Coastguard Worker 		if (engine != VCS && engine != VCS1 && engine != VCS2 &&
628*d83cc019SAndroid Build Coastguard Worker 		    engine != RCS)
629*d83cc019SAndroid Build Coastguard Worker 			return -1; /* TODO */
630*d83cc019SAndroid Build Coastguard Worker 
631*d83cc019SAndroid Build Coastguard Worker 		add = engine == VCS ? num_engines_in_class(VCS) : 1;
632*d83cc019SAndroid Build Coastguard Worker 		step->engine_map_count += add;
633*d83cc019SAndroid Build Coastguard Worker 		step->engine_map = realloc(step->engine_map,
634*d83cc019SAndroid Build Coastguard Worker 					   step->engine_map_count *
635*d83cc019SAndroid Build Coastguard Worker 					   sizeof(step->engine_map[0]));
636*d83cc019SAndroid Build Coastguard Worker 
637*d83cc019SAndroid Build Coastguard Worker 		if (engine != VCS)
638*d83cc019SAndroid Build Coastguard Worker 			step->engine_map[step->engine_map_count - add] = engine;
639*d83cc019SAndroid Build Coastguard Worker 		else
640*d83cc019SAndroid Build Coastguard Worker 			fill_engines_id_class(&step->engine_map[step->engine_map_count - add], VCS);
641*d83cc019SAndroid Build Coastguard Worker 	}
642*d83cc019SAndroid Build Coastguard Worker 
643*d83cc019SAndroid Build Coastguard Worker 	return 0;
644*d83cc019SAndroid Build Coastguard Worker }
645*d83cc019SAndroid Build Coastguard Worker 
engine_list_mask(const char * _str)646*d83cc019SAndroid Build Coastguard Worker static uint64_t engine_list_mask(const char *_str)
647*d83cc019SAndroid Build Coastguard Worker {
648*d83cc019SAndroid Build Coastguard Worker 	uint64_t mask = 0;
649*d83cc019SAndroid Build Coastguard Worker 
650*d83cc019SAndroid Build Coastguard Worker 	char *token, *tctx = NULL, *tstart = (char *)_str;
651*d83cc019SAndroid Build Coastguard Worker 
652*d83cc019SAndroid Build Coastguard Worker 	while ((token = strtok_r(tstart, "|", &tctx))) {
653*d83cc019SAndroid Build Coastguard Worker 		enum intel_engine_id engine = str_to_engine(token);
654*d83cc019SAndroid Build Coastguard Worker 
655*d83cc019SAndroid Build Coastguard Worker 		if ((int)engine < 0 || engine == DEFAULT || engine == VCS)
656*d83cc019SAndroid Build Coastguard Worker 			return 0;
657*d83cc019SAndroid Build Coastguard Worker 
658*d83cc019SAndroid Build Coastguard Worker 		mask |= 1 << engine;
659*d83cc019SAndroid Build Coastguard Worker 
660*d83cc019SAndroid Build Coastguard Worker 		tstart = NULL;
661*d83cc019SAndroid Build Coastguard Worker 	}
662*d83cc019SAndroid Build Coastguard Worker 
663*d83cc019SAndroid Build Coastguard Worker 	return mask;
664*d83cc019SAndroid Build Coastguard Worker }
665*d83cc019SAndroid Build Coastguard Worker 
666*d83cc019SAndroid Build Coastguard Worker #define int_field(_STEP_, _FIELD_, _COND_, _ERR_) \
667*d83cc019SAndroid Build Coastguard Worker 	if ((field = strtok_r(fstart, ".", &fctx))) { \
668*d83cc019SAndroid Build Coastguard Worker 		tmp = atoi(field); \
669*d83cc019SAndroid Build Coastguard Worker 		check_arg(_COND_, _ERR_, nr_steps); \
670*d83cc019SAndroid Build Coastguard Worker 		step.type = _STEP_; \
671*d83cc019SAndroid Build Coastguard Worker 		step._FIELD_ = tmp; \
672*d83cc019SAndroid Build Coastguard Worker 		goto add_step; \
673*d83cc019SAndroid Build Coastguard Worker 	} \
674*d83cc019SAndroid Build Coastguard Worker 
675*d83cc019SAndroid Build Coastguard Worker static struct workload *
parse_workload(struct w_arg * arg,unsigned int flags,struct workload * app_w)676*d83cc019SAndroid Build Coastguard Worker parse_workload(struct w_arg *arg, unsigned int flags, struct workload *app_w)
677*d83cc019SAndroid Build Coastguard Worker {
678*d83cc019SAndroid Build Coastguard Worker 	struct workload *wrk;
679*d83cc019SAndroid Build Coastguard Worker 	unsigned int nr_steps = 0;
680*d83cc019SAndroid Build Coastguard Worker 	char *desc = strdup(arg->desc);
681*d83cc019SAndroid Build Coastguard Worker 	char *_token, *token, *tctx = NULL, *tstart = desc;
682*d83cc019SAndroid Build Coastguard Worker 	char *field, *fctx = NULL, *fstart;
683*d83cc019SAndroid Build Coastguard Worker 	struct w_step step, *steps = NULL;
684*d83cc019SAndroid Build Coastguard Worker 	bool bcs_used = false;
685*d83cc019SAndroid Build Coastguard Worker 	unsigned int valid;
686*d83cc019SAndroid Build Coastguard Worker 	int i, j, tmp;
687*d83cc019SAndroid Build Coastguard Worker 
688*d83cc019SAndroid Build Coastguard Worker 	igt_assert(desc);
689*d83cc019SAndroid Build Coastguard Worker 
690*d83cc019SAndroid Build Coastguard Worker 	while ((_token = strtok_r(tstart, ",", &tctx))) {
691*d83cc019SAndroid Build Coastguard Worker 		tstart = NULL;
692*d83cc019SAndroid Build Coastguard Worker 		token = strdup(_token);
693*d83cc019SAndroid Build Coastguard Worker 		igt_assert(token);
694*d83cc019SAndroid Build Coastguard Worker 		fstart = token;
695*d83cc019SAndroid Build Coastguard Worker 		valid = 0;
696*d83cc019SAndroid Build Coastguard Worker 		memset(&step, 0, sizeof(step));
697*d83cc019SAndroid Build Coastguard Worker 
698*d83cc019SAndroid Build Coastguard Worker 		if ((field = strtok_r(fstart, ".", &fctx))) {
699*d83cc019SAndroid Build Coastguard Worker 			fstart = NULL;
700*d83cc019SAndroid Build Coastguard Worker 
701*d83cc019SAndroid Build Coastguard Worker 			if (!strcmp(field, "d")) {
702*d83cc019SAndroid Build Coastguard Worker 				int_field(DELAY, delay, tmp <= 0,
703*d83cc019SAndroid Build Coastguard Worker 					  "Invalid delay at step %u!\n");
704*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "p")) {
705*d83cc019SAndroid Build Coastguard Worker 				int_field(PERIOD, period, tmp <= 0,
706*d83cc019SAndroid Build Coastguard Worker 					  "Invalid period at step %u!\n");
707*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "P")) {
708*d83cc019SAndroid Build Coastguard Worker 				unsigned int nr = 0;
709*d83cc019SAndroid Build Coastguard Worker 				while ((field = strtok_r(fstart, ".", &fctx))) {
710*d83cc019SAndroid Build Coastguard Worker 					tmp = atoi(field);
711*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr == 0 && tmp <= 0,
712*d83cc019SAndroid Build Coastguard Worker 						  "Invalid context at step %u!\n",
713*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
714*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr > 1,
715*d83cc019SAndroid Build Coastguard Worker 						  "Invalid priority format at step %u!\n",
716*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
717*d83cc019SAndroid Build Coastguard Worker 
718*d83cc019SAndroid Build Coastguard Worker 					if (nr == 0)
719*d83cc019SAndroid Build Coastguard Worker 						step.context = tmp;
720*d83cc019SAndroid Build Coastguard Worker 					else
721*d83cc019SAndroid Build Coastguard Worker 						step.priority = tmp;
722*d83cc019SAndroid Build Coastguard Worker 
723*d83cc019SAndroid Build Coastguard Worker 					nr++;
724*d83cc019SAndroid Build Coastguard Worker 				}
725*d83cc019SAndroid Build Coastguard Worker 
726*d83cc019SAndroid Build Coastguard Worker 				step.type = CTX_PRIORITY;
727*d83cc019SAndroid Build Coastguard Worker 				goto add_step;
728*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "s")) {
729*d83cc019SAndroid Build Coastguard Worker 				int_field(SYNC, target,
730*d83cc019SAndroid Build Coastguard Worker 					  tmp >= 0 || ((int)nr_steps + tmp) < 0,
731*d83cc019SAndroid Build Coastguard Worker 					  "Invalid sync target at step %u!\n");
732*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "S")) {
733*d83cc019SAndroid Build Coastguard Worker 				unsigned int nr = 0;
734*d83cc019SAndroid Build Coastguard Worker 				while ((field = strtok_r(fstart, ".", &fctx))) {
735*d83cc019SAndroid Build Coastguard Worker 					tmp = atoi(field);
736*d83cc019SAndroid Build Coastguard Worker 					check_arg(tmp <= 0 && nr == 0,
737*d83cc019SAndroid Build Coastguard Worker 						  "Invalid context at step %u!\n",
738*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
739*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr > 1,
740*d83cc019SAndroid Build Coastguard Worker 						  "Invalid SSEU format at step %u!\n",
741*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
742*d83cc019SAndroid Build Coastguard Worker 
743*d83cc019SAndroid Build Coastguard Worker 					if (nr == 0)
744*d83cc019SAndroid Build Coastguard Worker 						step.context = tmp;
745*d83cc019SAndroid Build Coastguard Worker 					else if (nr == 1)
746*d83cc019SAndroid Build Coastguard Worker 						step.sseu = tmp;
747*d83cc019SAndroid Build Coastguard Worker 
748*d83cc019SAndroid Build Coastguard Worker 					nr++;
749*d83cc019SAndroid Build Coastguard Worker 				}
750*d83cc019SAndroid Build Coastguard Worker 
751*d83cc019SAndroid Build Coastguard Worker 				step.type = SSEU;
752*d83cc019SAndroid Build Coastguard Worker 				goto add_step;
753*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "t")) {
754*d83cc019SAndroid Build Coastguard Worker 				int_field(THROTTLE, throttle,
755*d83cc019SAndroid Build Coastguard Worker 					  tmp < 0,
756*d83cc019SAndroid Build Coastguard Worker 					  "Invalid throttle at step %u!\n");
757*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "q")) {
758*d83cc019SAndroid Build Coastguard Worker 				int_field(QD_THROTTLE, throttle,
759*d83cc019SAndroid Build Coastguard Worker 					  tmp < 0,
760*d83cc019SAndroid Build Coastguard Worker 					  "Invalid qd throttle at step %u!\n");
761*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "a")) {
762*d83cc019SAndroid Build Coastguard Worker 				int_field(SW_FENCE_SIGNAL, target,
763*d83cc019SAndroid Build Coastguard Worker 					  tmp >= 0,
764*d83cc019SAndroid Build Coastguard Worker 					  "Invalid sw fence signal at step %u!\n");
765*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "f")) {
766*d83cc019SAndroid Build Coastguard Worker 				step.type = SW_FENCE;
767*d83cc019SAndroid Build Coastguard Worker 				goto add_step;
768*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "M")) {
769*d83cc019SAndroid Build Coastguard Worker 				unsigned int nr = 0;
770*d83cc019SAndroid Build Coastguard Worker 				while ((field = strtok_r(fstart, ".", &fctx))) {
771*d83cc019SAndroid Build Coastguard Worker 					tmp = atoi(field);
772*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr == 0 && tmp <= 0,
773*d83cc019SAndroid Build Coastguard Worker 						  "Invalid context at step %u!\n",
774*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
775*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr > 1,
776*d83cc019SAndroid Build Coastguard Worker 						  "Invalid engine map format at step %u!\n",
777*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
778*d83cc019SAndroid Build Coastguard Worker 
779*d83cc019SAndroid Build Coastguard Worker 					if (nr == 0) {
780*d83cc019SAndroid Build Coastguard Worker 						step.context = tmp;
781*d83cc019SAndroid Build Coastguard Worker 					} else {
782*d83cc019SAndroid Build Coastguard Worker 						tmp = parse_engine_map(&step,
783*d83cc019SAndroid Build Coastguard Worker 								       field);
784*d83cc019SAndroid Build Coastguard Worker 						check_arg(tmp < 0,
785*d83cc019SAndroid Build Coastguard Worker 							  "Invalid engine map list at step %u!\n",
786*d83cc019SAndroid Build Coastguard Worker 							  nr_steps);
787*d83cc019SAndroid Build Coastguard Worker 					}
788*d83cc019SAndroid Build Coastguard Worker 
789*d83cc019SAndroid Build Coastguard Worker 					nr++;
790*d83cc019SAndroid Build Coastguard Worker 				}
791*d83cc019SAndroid Build Coastguard Worker 
792*d83cc019SAndroid Build Coastguard Worker 				step.type = ENGINE_MAP;
793*d83cc019SAndroid Build Coastguard Worker 				goto add_step;
794*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "T")) {
795*d83cc019SAndroid Build Coastguard Worker 				int_field(TERMINATE, target,
796*d83cc019SAndroid Build Coastguard Worker 					  tmp >= 0 || ((int)nr_steps + tmp) < 0,
797*d83cc019SAndroid Build Coastguard Worker 					  "Invalid terminate target at step %u!\n");
798*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "X")) {
799*d83cc019SAndroid Build Coastguard Worker 				unsigned int nr = 0;
800*d83cc019SAndroid Build Coastguard Worker 				while ((field = strtok_r(fstart, ".", &fctx))) {
801*d83cc019SAndroid Build Coastguard Worker 					tmp = atoi(field);
802*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr == 0 && tmp <= 0,
803*d83cc019SAndroid Build Coastguard Worker 						  "Invalid context at step %u!\n",
804*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
805*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr == 1 && tmp < 0,
806*d83cc019SAndroid Build Coastguard Worker 						  "Invalid preemption period at step %u!\n",
807*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
808*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr > 1,
809*d83cc019SAndroid Build Coastguard Worker 						  "Invalid preemption format at step %u!\n",
810*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
811*d83cc019SAndroid Build Coastguard Worker 
812*d83cc019SAndroid Build Coastguard Worker 					if (nr == 0)
813*d83cc019SAndroid Build Coastguard Worker 						step.context = tmp;
814*d83cc019SAndroid Build Coastguard Worker 					else
815*d83cc019SAndroid Build Coastguard Worker 						step.period = tmp;
816*d83cc019SAndroid Build Coastguard Worker 
817*d83cc019SAndroid Build Coastguard Worker 					nr++;
818*d83cc019SAndroid Build Coastguard Worker 				}
819*d83cc019SAndroid Build Coastguard Worker 
820*d83cc019SAndroid Build Coastguard Worker 				step.type = PREEMPTION;
821*d83cc019SAndroid Build Coastguard Worker 				goto add_step;
822*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "B")) {
823*d83cc019SAndroid Build Coastguard Worker 				unsigned int nr = 0;
824*d83cc019SAndroid Build Coastguard Worker 				while ((field = strtok_r(fstart, ".", &fctx))) {
825*d83cc019SAndroid Build Coastguard Worker 					tmp = atoi(field);
826*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr == 0 && tmp <= 0,
827*d83cc019SAndroid Build Coastguard Worker 						  "Invalid context at step %u!\n",
828*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
829*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr > 0,
830*d83cc019SAndroid Build Coastguard Worker 						  "Invalid load balance format at step %u!\n",
831*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
832*d83cc019SAndroid Build Coastguard Worker 
833*d83cc019SAndroid Build Coastguard Worker 					step.context = tmp;
834*d83cc019SAndroid Build Coastguard Worker 					step.load_balance = true;
835*d83cc019SAndroid Build Coastguard Worker 
836*d83cc019SAndroid Build Coastguard Worker 					nr++;
837*d83cc019SAndroid Build Coastguard Worker 				}
838*d83cc019SAndroid Build Coastguard Worker 
839*d83cc019SAndroid Build Coastguard Worker 				step.type = LOAD_BALANCE;
840*d83cc019SAndroid Build Coastguard Worker 				goto add_step;
841*d83cc019SAndroid Build Coastguard Worker 			} else if (!strcmp(field, "b")) {
842*d83cc019SAndroid Build Coastguard Worker 				unsigned int nr = 0;
843*d83cc019SAndroid Build Coastguard Worker 				while ((field = strtok_r(fstart, ".", &fctx))) {
844*d83cc019SAndroid Build Coastguard Worker 					check_arg(nr > 2,
845*d83cc019SAndroid Build Coastguard Worker 						  "Invalid bond format at step %u!\n",
846*d83cc019SAndroid Build Coastguard Worker 						  nr_steps);
847*d83cc019SAndroid Build Coastguard Worker 
848*d83cc019SAndroid Build Coastguard Worker 					if (nr == 0) {
849*d83cc019SAndroid Build Coastguard Worker 						tmp = atoi(field);
850*d83cc019SAndroid Build Coastguard Worker 						step.context = tmp;
851*d83cc019SAndroid Build Coastguard Worker 						check_arg(tmp <= 0,
852*d83cc019SAndroid Build Coastguard Worker 							  "Invalid context at step %u!\n",
853*d83cc019SAndroid Build Coastguard Worker 							  nr_steps);
854*d83cc019SAndroid Build Coastguard Worker 					} else if (nr == 1) {
855*d83cc019SAndroid Build Coastguard Worker 						step.bond_mask = engine_list_mask(field);
856*d83cc019SAndroid Build Coastguard Worker 						check_arg(step.bond_mask == 0,
857*d83cc019SAndroid Build Coastguard Worker 							"Invalid siblings list at step %u!\n",
858*d83cc019SAndroid Build Coastguard Worker 							nr_steps);
859*d83cc019SAndroid Build Coastguard Worker 					} else if (nr == 2) {
860*d83cc019SAndroid Build Coastguard Worker 						tmp = str_to_engine(field);
861*d83cc019SAndroid Build Coastguard Worker 						check_arg(tmp <= 0 ||
862*d83cc019SAndroid Build Coastguard Worker 							  tmp == VCS ||
863*d83cc019SAndroid Build Coastguard Worker 							  tmp == DEFAULT,
864*d83cc019SAndroid Build Coastguard Worker 							  "Invalid master engine at step %u!\n",
865*d83cc019SAndroid Build Coastguard Worker 							  nr_steps);
866*d83cc019SAndroid Build Coastguard Worker 						step.bond_master = tmp;
867*d83cc019SAndroid Build Coastguard Worker 					}
868*d83cc019SAndroid Build Coastguard Worker 
869*d83cc019SAndroid Build Coastguard Worker 					nr++;
870*d83cc019SAndroid Build Coastguard Worker 				}
871*d83cc019SAndroid Build Coastguard Worker 
872*d83cc019SAndroid Build Coastguard Worker 				step.type = BOND;
873*d83cc019SAndroid Build Coastguard Worker 				goto add_step;
874*d83cc019SAndroid Build Coastguard Worker 			}
875*d83cc019SAndroid Build Coastguard Worker 
876*d83cc019SAndroid Build Coastguard Worker 			if (!field) {
877*d83cc019SAndroid Build Coastguard Worker 				if (verbose)
878*d83cc019SAndroid Build Coastguard Worker 					fprintf(stderr,
879*d83cc019SAndroid Build Coastguard Worker 						"Parse error at step %u!\n",
880*d83cc019SAndroid Build Coastguard Worker 						nr_steps);
881*d83cc019SAndroid Build Coastguard Worker 				return NULL;
882*d83cc019SAndroid Build Coastguard Worker 			}
883*d83cc019SAndroid Build Coastguard Worker 
884*d83cc019SAndroid Build Coastguard Worker 			tmp = atoi(field);
885*d83cc019SAndroid Build Coastguard Worker 			check_arg(tmp < 0, "Invalid ctx id at step %u!\n",
886*d83cc019SAndroid Build Coastguard Worker 				  nr_steps);
887*d83cc019SAndroid Build Coastguard Worker 			step.context = tmp;
888*d83cc019SAndroid Build Coastguard Worker 
889*d83cc019SAndroid Build Coastguard Worker 			valid++;
890*d83cc019SAndroid Build Coastguard Worker 		}
891*d83cc019SAndroid Build Coastguard Worker 
892*d83cc019SAndroid Build Coastguard Worker 		if ((field = strtok_r(fstart, ".", &fctx))) {
893*d83cc019SAndroid Build Coastguard Worker 			fstart = NULL;
894*d83cc019SAndroid Build Coastguard Worker 
895*d83cc019SAndroid Build Coastguard Worker 			i = str_to_engine(field);
896*d83cc019SAndroid Build Coastguard Worker 			check_arg(i < 0,
897*d83cc019SAndroid Build Coastguard Worker 				  "Invalid engine id at step %u!\n", nr_steps);
898*d83cc019SAndroid Build Coastguard Worker 
899*d83cc019SAndroid Build Coastguard Worker 			valid++;
900*d83cc019SAndroid Build Coastguard Worker 
901*d83cc019SAndroid Build Coastguard Worker 			step.engine = i;
902*d83cc019SAndroid Build Coastguard Worker 
903*d83cc019SAndroid Build Coastguard Worker 			if (step.engine == BCS)
904*d83cc019SAndroid Build Coastguard Worker 				bcs_used = true;
905*d83cc019SAndroid Build Coastguard Worker 		}
906*d83cc019SAndroid Build Coastguard Worker 
907*d83cc019SAndroid Build Coastguard Worker 		if ((field = strtok_r(fstart, ".", &fctx))) {
908*d83cc019SAndroid Build Coastguard Worker 			char *sep = NULL;
909*d83cc019SAndroid Build Coastguard Worker 			long int tmpl;
910*d83cc019SAndroid Build Coastguard Worker 
911*d83cc019SAndroid Build Coastguard Worker 			fstart = NULL;
912*d83cc019SAndroid Build Coastguard Worker 
913*d83cc019SAndroid Build Coastguard Worker 			if (field[0] == '*') {
914*d83cc019SAndroid Build Coastguard Worker 				check_arg(intel_gen(intel_get_drm_devid(fd)) < 8,
915*d83cc019SAndroid Build Coastguard Worker 					  "Infinite batch at step %u needs Gen8+!\n",
916*d83cc019SAndroid Build Coastguard Worker 					  nr_steps);
917*d83cc019SAndroid Build Coastguard Worker 				step.unbound_duration = true;
918*d83cc019SAndroid Build Coastguard Worker 			} else {
919*d83cc019SAndroid Build Coastguard Worker 				tmpl = strtol(field, &sep, 10);
920*d83cc019SAndroid Build Coastguard Worker 				check_arg(tmpl <= 0 || tmpl == LONG_MIN ||
921*d83cc019SAndroid Build Coastguard Worker 					  tmpl == LONG_MAX,
922*d83cc019SAndroid Build Coastguard Worker 					  "Invalid duration at step %u!\n",
923*d83cc019SAndroid Build Coastguard Worker 					  nr_steps);
924*d83cc019SAndroid Build Coastguard Worker 				step.duration.min = tmpl;
925*d83cc019SAndroid Build Coastguard Worker 
926*d83cc019SAndroid Build Coastguard Worker 				if (sep && *sep == '-') {
927*d83cc019SAndroid Build Coastguard Worker 					tmpl = strtol(sep + 1, NULL, 10);
928*d83cc019SAndroid Build Coastguard Worker 					check_arg(tmpl <= 0 ||
929*d83cc019SAndroid Build Coastguard Worker 						tmpl <= step.duration.min ||
930*d83cc019SAndroid Build Coastguard Worker 						tmpl == LONG_MIN ||
931*d83cc019SAndroid Build Coastguard Worker 						tmpl == LONG_MAX,
932*d83cc019SAndroid Build Coastguard Worker 						"Invalid duration range at step %u!\n",
933*d83cc019SAndroid Build Coastguard Worker 						nr_steps);
934*d83cc019SAndroid Build Coastguard Worker 					step.duration.max = tmpl;
935*d83cc019SAndroid Build Coastguard Worker 				} else {
936*d83cc019SAndroid Build Coastguard Worker 					step.duration.max = step.duration.min;
937*d83cc019SAndroid Build Coastguard Worker 				}
938*d83cc019SAndroid Build Coastguard Worker 			}
939*d83cc019SAndroid Build Coastguard Worker 
940*d83cc019SAndroid Build Coastguard Worker 			valid++;
941*d83cc019SAndroid Build Coastguard Worker 		}
942*d83cc019SAndroid Build Coastguard Worker 
943*d83cc019SAndroid Build Coastguard Worker 		if ((field = strtok_r(fstart, ".", &fctx))) {
944*d83cc019SAndroid Build Coastguard Worker 			fstart = NULL;
945*d83cc019SAndroid Build Coastguard Worker 
946*d83cc019SAndroid Build Coastguard Worker 			tmp = parse_dependencies(nr_steps, &step, field);
947*d83cc019SAndroid Build Coastguard Worker 			check_arg(tmp < 0,
948*d83cc019SAndroid Build Coastguard Worker 				  "Invalid dependency at step %u!\n", nr_steps);
949*d83cc019SAndroid Build Coastguard Worker 
950*d83cc019SAndroid Build Coastguard Worker 			valid++;
951*d83cc019SAndroid Build Coastguard Worker 		}
952*d83cc019SAndroid Build Coastguard Worker 
953*d83cc019SAndroid Build Coastguard Worker 		if ((field = strtok_r(fstart, ".", &fctx))) {
954*d83cc019SAndroid Build Coastguard Worker 			fstart = NULL;
955*d83cc019SAndroid Build Coastguard Worker 
956*d83cc019SAndroid Build Coastguard Worker 			check_arg(strlen(field) != 1 ||
957*d83cc019SAndroid Build Coastguard Worker 				  (field[0] != '0' && field[0] != '1'),
958*d83cc019SAndroid Build Coastguard Worker 				  "Invalid wait boolean at step %u!\n",
959*d83cc019SAndroid Build Coastguard Worker 				  nr_steps);
960*d83cc019SAndroid Build Coastguard Worker 			step.sync = field[0] - '0';
961*d83cc019SAndroid Build Coastguard Worker 
962*d83cc019SAndroid Build Coastguard Worker 			valid++;
963*d83cc019SAndroid Build Coastguard Worker 		}
964*d83cc019SAndroid Build Coastguard Worker 
965*d83cc019SAndroid Build Coastguard Worker 		check_arg(valid != 5, "Invalid record at step %u!\n", nr_steps);
966*d83cc019SAndroid Build Coastguard Worker 
967*d83cc019SAndroid Build Coastguard Worker 		step.type = BATCH;
968*d83cc019SAndroid Build Coastguard Worker 
969*d83cc019SAndroid Build Coastguard Worker add_step:
970*d83cc019SAndroid Build Coastguard Worker 		step.idx = nr_steps++;
971*d83cc019SAndroid Build Coastguard Worker 		step.request = -1;
972*d83cc019SAndroid Build Coastguard Worker 		steps = realloc(steps, sizeof(step) * nr_steps);
973*d83cc019SAndroid Build Coastguard Worker 		igt_assert(steps);
974*d83cc019SAndroid Build Coastguard Worker 
975*d83cc019SAndroid Build Coastguard Worker 		memcpy(&steps[nr_steps - 1], &step, sizeof(step));
976*d83cc019SAndroid Build Coastguard Worker 
977*d83cc019SAndroid Build Coastguard Worker 		free(token);
978*d83cc019SAndroid Build Coastguard Worker 	}
979*d83cc019SAndroid Build Coastguard Worker 
980*d83cc019SAndroid Build Coastguard Worker 	if (app_w) {
981*d83cc019SAndroid Build Coastguard Worker 		steps = realloc(steps, sizeof(step) *
982*d83cc019SAndroid Build Coastguard Worker 				(nr_steps + app_w->nr_steps));
983*d83cc019SAndroid Build Coastguard Worker 		igt_assert(steps);
984*d83cc019SAndroid Build Coastguard Worker 
985*d83cc019SAndroid Build Coastguard Worker 		memcpy(&steps[nr_steps], app_w->steps,
986*d83cc019SAndroid Build Coastguard Worker 		       sizeof(step) * app_w->nr_steps);
987*d83cc019SAndroid Build Coastguard Worker 
988*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < app_w->nr_steps; i++)
989*d83cc019SAndroid Build Coastguard Worker 			steps[nr_steps + i].idx += nr_steps;
990*d83cc019SAndroid Build Coastguard Worker 
991*d83cc019SAndroid Build Coastguard Worker 		nr_steps += app_w->nr_steps;
992*d83cc019SAndroid Build Coastguard Worker 	}
993*d83cc019SAndroid Build Coastguard Worker 
994*d83cc019SAndroid Build Coastguard Worker 	wrk = malloc(sizeof(*wrk));
995*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk);
996*d83cc019SAndroid Build Coastguard Worker 
997*d83cc019SAndroid Build Coastguard Worker 	wrk->nr_steps = nr_steps;
998*d83cc019SAndroid Build Coastguard Worker 	wrk->steps = steps;
999*d83cc019SAndroid Build Coastguard Worker 	wrk->prio = arg->prio;
1000*d83cc019SAndroid Build Coastguard Worker 	wrk->sseu = arg->sseu;
1001*d83cc019SAndroid Build Coastguard Worker 
1002*d83cc019SAndroid Build Coastguard Worker 	free(desc);
1003*d83cc019SAndroid Build Coastguard Worker 
1004*d83cc019SAndroid Build Coastguard Worker 	/*
1005*d83cc019SAndroid Build Coastguard Worker 	 * Tag all steps which need to emit a sync fence if another step is
1006*d83cc019SAndroid Build Coastguard Worker 	 * referencing them as a sync fence dependency.
1007*d83cc019SAndroid Build Coastguard Worker 	 */
1008*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < nr_steps; i++) {
1009*d83cc019SAndroid Build Coastguard Worker 		for (j = 0; j < steps[i].fence_deps.nr; j++) {
1010*d83cc019SAndroid Build Coastguard Worker 			tmp = steps[i].idx + steps[i].fence_deps.list[j];
1011*d83cc019SAndroid Build Coastguard Worker 			check_arg(tmp < 0 || tmp >= i ||
1012*d83cc019SAndroid Build Coastguard Worker 				  (steps[tmp].type != BATCH &&
1013*d83cc019SAndroid Build Coastguard Worker 				   steps[tmp].type != SW_FENCE),
1014*d83cc019SAndroid Build Coastguard Worker 				  "Invalid dependency target %u!\n", i);
1015*d83cc019SAndroid Build Coastguard Worker 			steps[tmp].emit_fence = -1;
1016*d83cc019SAndroid Build Coastguard Worker 		}
1017*d83cc019SAndroid Build Coastguard Worker 	}
1018*d83cc019SAndroid Build Coastguard Worker 
1019*d83cc019SAndroid Build Coastguard Worker 	/* Validate SW_FENCE_SIGNAL targets. */
1020*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < nr_steps; i++) {
1021*d83cc019SAndroid Build Coastguard Worker 		if (steps[i].type == SW_FENCE_SIGNAL) {
1022*d83cc019SAndroid Build Coastguard Worker 			tmp = steps[i].idx + steps[i].target;
1023*d83cc019SAndroid Build Coastguard Worker 			check_arg(tmp < 0 || tmp >= i ||
1024*d83cc019SAndroid Build Coastguard Worker 				  steps[tmp].type != SW_FENCE,
1025*d83cc019SAndroid Build Coastguard Worker 				  "Invalid sw fence target %u!\n", i);
1026*d83cc019SAndroid Build Coastguard Worker 		}
1027*d83cc019SAndroid Build Coastguard Worker 	}
1028*d83cc019SAndroid Build Coastguard Worker 
1029*d83cc019SAndroid Build Coastguard Worker 	if (bcs_used && (flags & VCS2REMAP) && verbose)
1030*d83cc019SAndroid Build Coastguard Worker 		printf("BCS usage in workload with VCS2 remapping enabled!\n");
1031*d83cc019SAndroid Build Coastguard Worker 
1032*d83cc019SAndroid Build Coastguard Worker 	return wrk;
1033*d83cc019SAndroid Build Coastguard Worker }
1034*d83cc019SAndroid Build Coastguard Worker 
1035*d83cc019SAndroid Build Coastguard Worker static struct workload *
clone_workload(struct workload * _wrk)1036*d83cc019SAndroid Build Coastguard Worker clone_workload(struct workload *_wrk)
1037*d83cc019SAndroid Build Coastguard Worker {
1038*d83cc019SAndroid Build Coastguard Worker 	struct workload *wrk;
1039*d83cc019SAndroid Build Coastguard Worker 	int i;
1040*d83cc019SAndroid Build Coastguard Worker 
1041*d83cc019SAndroid Build Coastguard Worker 	wrk = malloc(sizeof(*wrk));
1042*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk);
1043*d83cc019SAndroid Build Coastguard Worker 	memset(wrk, 0, sizeof(*wrk));
1044*d83cc019SAndroid Build Coastguard Worker 
1045*d83cc019SAndroid Build Coastguard Worker 	wrk->prio = _wrk->prio;
1046*d83cc019SAndroid Build Coastguard Worker 	wrk->sseu = _wrk->sseu;
1047*d83cc019SAndroid Build Coastguard Worker 	wrk->nr_steps = _wrk->nr_steps;
1048*d83cc019SAndroid Build Coastguard Worker 	wrk->steps = calloc(wrk->nr_steps, sizeof(struct w_step));
1049*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk->steps);
1050*d83cc019SAndroid Build Coastguard Worker 
1051*d83cc019SAndroid Build Coastguard Worker 	memcpy(wrk->steps, _wrk->steps, sizeof(struct w_step) * wrk->nr_steps);
1052*d83cc019SAndroid Build Coastguard Worker 
1053*d83cc019SAndroid Build Coastguard Worker 	/* Check if we need a sw sync timeline. */
1054*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < wrk->nr_steps; i++) {
1055*d83cc019SAndroid Build Coastguard Worker 		if (wrk->steps[i].type == SW_FENCE) {
1056*d83cc019SAndroid Build Coastguard Worker 			wrk->sync_timeline = sw_sync_timeline_create();
1057*d83cc019SAndroid Build Coastguard Worker 			igt_assert(wrk->sync_timeline >= 0);
1058*d83cc019SAndroid Build Coastguard Worker 			break;
1059*d83cc019SAndroid Build Coastguard Worker 		}
1060*d83cc019SAndroid Build Coastguard Worker 	}
1061*d83cc019SAndroid Build Coastguard Worker 
1062*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < NUM_ENGINES; i++)
1063*d83cc019SAndroid Build Coastguard Worker 		igt_list_init(&wrk->requests[i]);
1064*d83cc019SAndroid Build Coastguard Worker 
1065*d83cc019SAndroid Build Coastguard Worker 	return wrk;
1066*d83cc019SAndroid Build Coastguard Worker }
1067*d83cc019SAndroid Build Coastguard Worker 
1068*d83cc019SAndroid Build Coastguard Worker #define rounddown(x, y) (x - (x%y))
1069*d83cc019SAndroid Build Coastguard Worker #ifndef PAGE_SIZE
1070*d83cc019SAndroid Build Coastguard Worker #define PAGE_SIZE (4096)
1071*d83cc019SAndroid Build Coastguard Worker #endif
1072*d83cc019SAndroid Build Coastguard Worker 
get_duration(struct workload * wrk,struct w_step * w)1073*d83cc019SAndroid Build Coastguard Worker static unsigned int get_duration(struct workload *wrk, struct w_step *w)
1074*d83cc019SAndroid Build Coastguard Worker {
1075*d83cc019SAndroid Build Coastguard Worker 	struct duration *dur = &w->duration;
1076*d83cc019SAndroid Build Coastguard Worker 
1077*d83cc019SAndroid Build Coastguard Worker 	if (dur->min == dur->max)
1078*d83cc019SAndroid Build Coastguard Worker 		return dur->min;
1079*d83cc019SAndroid Build Coastguard Worker 	else
1080*d83cc019SAndroid Build Coastguard Worker 		return dur->min + hars_petruska_f54_1_random(&wrk->bb_prng) %
1081*d83cc019SAndroid Build Coastguard Worker 		       (dur->max + 1 - dur->min);
1082*d83cc019SAndroid Build Coastguard Worker }
1083*d83cc019SAndroid Build Coastguard Worker 
get_bb_sz(unsigned int duration)1084*d83cc019SAndroid Build Coastguard Worker static unsigned long get_bb_sz(unsigned int duration)
1085*d83cc019SAndroid Build Coastguard Worker {
1086*d83cc019SAndroid Build Coastguard Worker 	return ALIGN(duration * nop_calibration * sizeof(uint32_t) /
1087*d83cc019SAndroid Build Coastguard Worker 		     nop_calibration_us, sizeof(uint32_t));
1088*d83cc019SAndroid Build Coastguard Worker }
1089*d83cc019SAndroid Build Coastguard Worker 
1090*d83cc019SAndroid Build Coastguard Worker static void
init_bb(struct w_step * w,unsigned int flags)1091*d83cc019SAndroid Build Coastguard Worker init_bb(struct w_step *w, unsigned int flags)
1092*d83cc019SAndroid Build Coastguard Worker {
1093*d83cc019SAndroid Build Coastguard Worker 	const unsigned int arb_period =
1094*d83cc019SAndroid Build Coastguard Worker 			get_bb_sz(w->preempt_us) / sizeof(uint32_t);
1095*d83cc019SAndroid Build Coastguard Worker 	const unsigned int mmap_len = ALIGN(w->bb_sz, 4096);
1096*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
1097*d83cc019SAndroid Build Coastguard Worker 	uint32_t *ptr;
1098*d83cc019SAndroid Build Coastguard Worker 
1099*d83cc019SAndroid Build Coastguard Worker 	if (w->unbound_duration || !arb_period)
1100*d83cc019SAndroid Build Coastguard Worker 		return;
1101*d83cc019SAndroid Build Coastguard Worker 
1102*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, w->bb_handle,
1103*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
1104*d83cc019SAndroid Build Coastguard Worker 
1105*d83cc019SAndroid Build Coastguard Worker 	ptr = gem_mmap__wc(fd, w->bb_handle, 0, mmap_len, PROT_WRITE);
1106*d83cc019SAndroid Build Coastguard Worker 
1107*d83cc019SAndroid Build Coastguard Worker 	for (i = arb_period; i < w->bb_sz / sizeof(uint32_t); i += arb_period)
1108*d83cc019SAndroid Build Coastguard Worker 		ptr[i] = 0x5 << 23; /* MI_ARB_CHK */
1109*d83cc019SAndroid Build Coastguard Worker 
1110*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, mmap_len);
1111*d83cc019SAndroid Build Coastguard Worker }
1112*d83cc019SAndroid Build Coastguard Worker 
1113*d83cc019SAndroid Build Coastguard Worker static unsigned int
terminate_bb(struct w_step * w,unsigned int flags)1114*d83cc019SAndroid Build Coastguard Worker terminate_bb(struct w_step *w, unsigned int flags)
1115*d83cc019SAndroid Build Coastguard Worker {
1116*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = 0xa << 23;
1117*d83cc019SAndroid Build Coastguard Worker 	unsigned long mmap_start, mmap_len;
1118*d83cc019SAndroid Build Coastguard Worker 	unsigned long batch_start = w->bb_sz;
1119*d83cc019SAndroid Build Coastguard Worker 	unsigned int r = 0;
1120*d83cc019SAndroid Build Coastguard Worker 	uint32_t *ptr, *cs;
1121*d83cc019SAndroid Build Coastguard Worker 
1122*d83cc019SAndroid Build Coastguard Worker 	igt_assert(((flags & RT) && (flags & SEQNO)) || !(flags & RT));
1123*d83cc019SAndroid Build Coastguard Worker 
1124*d83cc019SAndroid Build Coastguard Worker 	batch_start -= sizeof(uint32_t); /* bbend */
1125*d83cc019SAndroid Build Coastguard Worker 	if (flags & SEQNO)
1126*d83cc019SAndroid Build Coastguard Worker 		batch_start -= 4 * sizeof(uint32_t);
1127*d83cc019SAndroid Build Coastguard Worker 	if (flags & RT)
1128*d83cc019SAndroid Build Coastguard Worker 		batch_start -= 12 * sizeof(uint32_t);
1129*d83cc019SAndroid Build Coastguard Worker 
1130*d83cc019SAndroid Build Coastguard Worker 	if (w->unbound_duration)
1131*d83cc019SAndroid Build Coastguard Worker 		batch_start -= 4 * sizeof(uint32_t); /* MI_ARB_CHK + MI_BATCH_BUFFER_START */
1132*d83cc019SAndroid Build Coastguard Worker 
1133*d83cc019SAndroid Build Coastguard Worker 	mmap_start = rounddown(batch_start, PAGE_SIZE);
1134*d83cc019SAndroid Build Coastguard Worker 	mmap_len = ALIGN(w->bb_sz - mmap_start, PAGE_SIZE);
1135*d83cc019SAndroid Build Coastguard Worker 
1136*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, w->bb_handle,
1137*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
1138*d83cc019SAndroid Build Coastguard Worker 
1139*d83cc019SAndroid Build Coastguard Worker 	ptr = gem_mmap__wc(fd, w->bb_handle, mmap_start, mmap_len, PROT_WRITE);
1140*d83cc019SAndroid Build Coastguard Worker 	cs = (uint32_t *)((char *)ptr + batch_start - mmap_start);
1141*d83cc019SAndroid Build Coastguard Worker 
1142*d83cc019SAndroid Build Coastguard Worker 	if (w->unbound_duration) {
1143*d83cc019SAndroid Build Coastguard Worker 		w->reloc[r++].offset = batch_start + 2 * sizeof(uint32_t);
1144*d83cc019SAndroid Build Coastguard Worker 		batch_start += 4 * sizeof(uint32_t);
1145*d83cc019SAndroid Build Coastguard Worker 
1146*d83cc019SAndroid Build Coastguard Worker 		*cs++ = w->preempt_us ? 0x5 << 23 /* MI_ARB_CHK; */ : MI_NOOP;
1147*d83cc019SAndroid Build Coastguard Worker 		w->recursive_bb_start = cs;
1148*d83cc019SAndroid Build Coastguard Worker 		*cs++ = MI_BATCH_BUFFER_START | 1 << 8 | 1;
1149*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1150*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1151*d83cc019SAndroid Build Coastguard Worker 	}
1152*d83cc019SAndroid Build Coastguard Worker 
1153*d83cc019SAndroid Build Coastguard Worker 	if (flags & SEQNO) {
1154*d83cc019SAndroid Build Coastguard Worker 		w->reloc[r++].offset = batch_start + sizeof(uint32_t);
1155*d83cc019SAndroid Build Coastguard Worker 		batch_start += 4 * sizeof(uint32_t);
1156*d83cc019SAndroid Build Coastguard Worker 
1157*d83cc019SAndroid Build Coastguard Worker 		*cs++ = MI_STORE_DWORD_IMM;
1158*d83cc019SAndroid Build Coastguard Worker 		w->seqno_address = cs;
1159*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1160*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1161*d83cc019SAndroid Build Coastguard Worker 		w->seqno_value = cs;
1162*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1163*d83cc019SAndroid Build Coastguard Worker 	}
1164*d83cc019SAndroid Build Coastguard Worker 
1165*d83cc019SAndroid Build Coastguard Worker 	if (flags & RT) {
1166*d83cc019SAndroid Build Coastguard Worker 		w->reloc[r++].offset = batch_start + sizeof(uint32_t);
1167*d83cc019SAndroid Build Coastguard Worker 		batch_start += 4 * sizeof(uint32_t);
1168*d83cc019SAndroid Build Coastguard Worker 
1169*d83cc019SAndroid Build Coastguard Worker 		*cs++ = MI_STORE_DWORD_IMM;
1170*d83cc019SAndroid Build Coastguard Worker 		w->rt0_address = cs;
1171*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1172*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1173*d83cc019SAndroid Build Coastguard Worker 		w->rt0_value = cs;
1174*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1175*d83cc019SAndroid Build Coastguard Worker 
1176*d83cc019SAndroid Build Coastguard Worker 		w->reloc[r++].offset = batch_start + 2 * sizeof(uint32_t);
1177*d83cc019SAndroid Build Coastguard Worker 		batch_start += 4 * sizeof(uint32_t);
1178*d83cc019SAndroid Build Coastguard Worker 
1179*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0x24 << 23 | 2; /* MI_STORE_REG_MEM */
1180*d83cc019SAndroid Build Coastguard Worker 		*cs++ = RCS_TIMESTAMP;
1181*d83cc019SAndroid Build Coastguard Worker 		w->rt1_address = cs;
1182*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1183*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1184*d83cc019SAndroid Build Coastguard Worker 
1185*d83cc019SAndroid Build Coastguard Worker 		w->reloc[r++].offset = batch_start + sizeof(uint32_t);
1186*d83cc019SAndroid Build Coastguard Worker 		batch_start += 4 * sizeof(uint32_t);
1187*d83cc019SAndroid Build Coastguard Worker 
1188*d83cc019SAndroid Build Coastguard Worker 		*cs++ = MI_STORE_DWORD_IMM;
1189*d83cc019SAndroid Build Coastguard Worker 		w->latch_address = cs;
1190*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1191*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1192*d83cc019SAndroid Build Coastguard Worker 		w->latch_value = cs;
1193*d83cc019SAndroid Build Coastguard Worker 		*cs++ = 0;
1194*d83cc019SAndroid Build Coastguard Worker 	}
1195*d83cc019SAndroid Build Coastguard Worker 
1196*d83cc019SAndroid Build Coastguard Worker 	*cs = bbe;
1197*d83cc019SAndroid Build Coastguard Worker 
1198*d83cc019SAndroid Build Coastguard Worker 	return r;
1199*d83cc019SAndroid Build Coastguard Worker }
1200*d83cc019SAndroid Build Coastguard Worker 
1201*d83cc019SAndroid Build Coastguard Worker static const unsigned int eb_engine_map[NUM_ENGINES] = {
1202*d83cc019SAndroid Build Coastguard Worker 	[DEFAULT] = I915_EXEC_DEFAULT,
1203*d83cc019SAndroid Build Coastguard Worker 	[RCS] = I915_EXEC_RENDER,
1204*d83cc019SAndroid Build Coastguard Worker 	[BCS] = I915_EXEC_BLT,
1205*d83cc019SAndroid Build Coastguard Worker 	[VCS] = I915_EXEC_BSD,
1206*d83cc019SAndroid Build Coastguard Worker 	[VCS1] = I915_EXEC_BSD | I915_EXEC_BSD_RING1,
1207*d83cc019SAndroid Build Coastguard Worker 	[VCS2] = I915_EXEC_BSD | I915_EXEC_BSD_RING2,
1208*d83cc019SAndroid Build Coastguard Worker 	[VECS] = I915_EXEC_VEBOX
1209*d83cc019SAndroid Build Coastguard Worker };
1210*d83cc019SAndroid Build Coastguard Worker 
1211*d83cc019SAndroid Build Coastguard Worker static void
eb_set_engine(struct drm_i915_gem_execbuffer2 * eb,enum intel_engine_id engine,unsigned int flags)1212*d83cc019SAndroid Build Coastguard Worker eb_set_engine(struct drm_i915_gem_execbuffer2 *eb,
1213*d83cc019SAndroid Build Coastguard Worker 	      enum intel_engine_id engine,
1214*d83cc019SAndroid Build Coastguard Worker 	      unsigned int flags)
1215*d83cc019SAndroid Build Coastguard Worker {
1216*d83cc019SAndroid Build Coastguard Worker 	if (engine == VCS2 && (flags & VCS2REMAP))
1217*d83cc019SAndroid Build Coastguard Worker 		engine = BCS;
1218*d83cc019SAndroid Build Coastguard Worker 
1219*d83cc019SAndroid Build Coastguard Worker 	if ((flags & I915) && engine == VCS)
1220*d83cc019SAndroid Build Coastguard Worker 		eb->flags = 0;
1221*d83cc019SAndroid Build Coastguard Worker 	else
1222*d83cc019SAndroid Build Coastguard Worker 		eb->flags = eb_engine_map[engine];
1223*d83cc019SAndroid Build Coastguard Worker }
1224*d83cc019SAndroid Build Coastguard Worker 
1225*d83cc019SAndroid Build Coastguard Worker static unsigned int
find_engine_in_map(struct ctx * ctx,enum intel_engine_id engine)1226*d83cc019SAndroid Build Coastguard Worker find_engine_in_map(struct ctx *ctx, enum intel_engine_id engine)
1227*d83cc019SAndroid Build Coastguard Worker {
1228*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
1229*d83cc019SAndroid Build Coastguard Worker 
1230*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ctx->engine_map_count; i++) {
1231*d83cc019SAndroid Build Coastguard Worker 		if (ctx->engine_map[i] == engine)
1232*d83cc019SAndroid Build Coastguard Worker 			return i + 1;
1233*d83cc019SAndroid Build Coastguard Worker 	}
1234*d83cc019SAndroid Build Coastguard Worker 
1235*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ctx->wants_balance);
1236*d83cc019SAndroid Build Coastguard Worker 	return 0;
1237*d83cc019SAndroid Build Coastguard Worker }
1238*d83cc019SAndroid Build Coastguard Worker 
1239*d83cc019SAndroid Build Coastguard Worker static struct ctx *
__get_ctx(struct workload * wrk,struct w_step * w)1240*d83cc019SAndroid Build Coastguard Worker __get_ctx(struct workload *wrk, struct w_step *w)
1241*d83cc019SAndroid Build Coastguard Worker {
1242*d83cc019SAndroid Build Coastguard Worker 	return &wrk->ctx_list[w->context * 2];
1243*d83cc019SAndroid Build Coastguard Worker }
1244*d83cc019SAndroid Build Coastguard Worker 
1245*d83cc019SAndroid Build Coastguard Worker static void
eb_update_flags(struct workload * wrk,struct w_step * w,enum intel_engine_id engine,unsigned int flags)1246*d83cc019SAndroid Build Coastguard Worker eb_update_flags(struct workload *wrk, struct w_step *w,
1247*d83cc019SAndroid Build Coastguard Worker 		enum intel_engine_id engine, unsigned int flags)
1248*d83cc019SAndroid Build Coastguard Worker {
1249*d83cc019SAndroid Build Coastguard Worker 	struct ctx *ctx = __get_ctx(wrk, w);
1250*d83cc019SAndroid Build Coastguard Worker 
1251*d83cc019SAndroid Build Coastguard Worker 	if (ctx->engine_map)
1252*d83cc019SAndroid Build Coastguard Worker 		w->eb.flags = find_engine_in_map(ctx, engine);
1253*d83cc019SAndroid Build Coastguard Worker 	else
1254*d83cc019SAndroid Build Coastguard Worker 		eb_set_engine(&w->eb, engine, flags);
1255*d83cc019SAndroid Build Coastguard Worker 
1256*d83cc019SAndroid Build Coastguard Worker 	w->eb.flags |= I915_EXEC_HANDLE_LUT;
1257*d83cc019SAndroid Build Coastguard Worker 	w->eb.flags |= I915_EXEC_NO_RELOC;
1258*d83cc019SAndroid Build Coastguard Worker 
1259*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w->emit_fence <= 0);
1260*d83cc019SAndroid Build Coastguard Worker 	if (w->emit_fence)
1261*d83cc019SAndroid Build Coastguard Worker 		w->eb.flags |= I915_EXEC_FENCE_OUT;
1262*d83cc019SAndroid Build Coastguard Worker }
1263*d83cc019SAndroid Build Coastguard Worker 
1264*d83cc019SAndroid Build Coastguard Worker static struct drm_i915_gem_exec_object2 *
get_status_objects(struct workload * wrk)1265*d83cc019SAndroid Build Coastguard Worker get_status_objects(struct workload *wrk)
1266*d83cc019SAndroid Build Coastguard Worker {
1267*d83cc019SAndroid Build Coastguard Worker 	if (wrk->flags & GLOBAL_BALANCE)
1268*d83cc019SAndroid Build Coastguard Worker 		return wrk->global_wrk->status_object;
1269*d83cc019SAndroid Build Coastguard Worker 	else
1270*d83cc019SAndroid Build Coastguard Worker 		return wrk->status_object;
1271*d83cc019SAndroid Build Coastguard Worker }
1272*d83cc019SAndroid Build Coastguard Worker 
1273*d83cc019SAndroid Build Coastguard Worker static uint32_t
get_ctxid(struct workload * wrk,struct w_step * w)1274*d83cc019SAndroid Build Coastguard Worker get_ctxid(struct workload *wrk, struct w_step *w)
1275*d83cc019SAndroid Build Coastguard Worker {
1276*d83cc019SAndroid Build Coastguard Worker 	struct ctx *ctx = __get_ctx(wrk, w);
1277*d83cc019SAndroid Build Coastguard Worker 
1278*d83cc019SAndroid Build Coastguard Worker 	if (ctx->targets_instance && ctx->wants_balance && w->engine == VCS)
1279*d83cc019SAndroid Build Coastguard Worker 		return wrk->ctx_list[w->context * 2 + 1].id;
1280*d83cc019SAndroid Build Coastguard Worker 	else
1281*d83cc019SAndroid Build Coastguard Worker 		return wrk->ctx_list[w->context * 2].id;
1282*d83cc019SAndroid Build Coastguard Worker }
1283*d83cc019SAndroid Build Coastguard Worker 
1284*d83cc019SAndroid Build Coastguard Worker static void
alloc_step_batch(struct workload * wrk,struct w_step * w,unsigned int flags)1285*d83cc019SAndroid Build Coastguard Worker alloc_step_batch(struct workload *wrk, struct w_step *w, unsigned int flags)
1286*d83cc019SAndroid Build Coastguard Worker {
1287*d83cc019SAndroid Build Coastguard Worker 	enum intel_engine_id engine = w->engine;
1288*d83cc019SAndroid Build Coastguard Worker 	unsigned int j = 0;
1289*d83cc019SAndroid Build Coastguard Worker 	unsigned int nr_obj = 3 + w->data_deps.nr;
1290*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
1291*d83cc019SAndroid Build Coastguard Worker 
1292*d83cc019SAndroid Build Coastguard Worker 	w->obj = calloc(nr_obj, sizeof(*w->obj));
1293*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w->obj);
1294*d83cc019SAndroid Build Coastguard Worker 
1295*d83cc019SAndroid Build Coastguard Worker 	w->obj[j].handle = gem_create(fd, 4096);
1296*d83cc019SAndroid Build Coastguard Worker 	w->obj[j].flags = EXEC_OBJECT_WRITE;
1297*d83cc019SAndroid Build Coastguard Worker 	j++;
1298*d83cc019SAndroid Build Coastguard Worker 	igt_assert(j < nr_obj);
1299*d83cc019SAndroid Build Coastguard Worker 
1300*d83cc019SAndroid Build Coastguard Worker 	if (flags & SEQNO) {
1301*d83cc019SAndroid Build Coastguard Worker 		w->obj[j++] = get_status_objects(wrk)[0];
1302*d83cc019SAndroid Build Coastguard Worker 		igt_assert(j < nr_obj);
1303*d83cc019SAndroid Build Coastguard Worker 	}
1304*d83cc019SAndroid Build Coastguard Worker 
1305*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < w->data_deps.nr; i++) {
1306*d83cc019SAndroid Build Coastguard Worker 		igt_assert(w->data_deps.list[i] <= 0);
1307*d83cc019SAndroid Build Coastguard Worker 		if (w->data_deps.list[i]) {
1308*d83cc019SAndroid Build Coastguard Worker 			int dep_idx = w->idx + w->data_deps.list[i];
1309*d83cc019SAndroid Build Coastguard Worker 
1310*d83cc019SAndroid Build Coastguard Worker 			igt_assert(dep_idx >= 0 && dep_idx < w->idx);
1311*d83cc019SAndroid Build Coastguard Worker 			igt_assert(wrk->steps[dep_idx].type == BATCH);
1312*d83cc019SAndroid Build Coastguard Worker 
1313*d83cc019SAndroid Build Coastguard Worker 			w->obj[j].handle = wrk->steps[dep_idx].obj[0].handle;
1314*d83cc019SAndroid Build Coastguard Worker 			j++;
1315*d83cc019SAndroid Build Coastguard Worker 			igt_assert(j < nr_obj);
1316*d83cc019SAndroid Build Coastguard Worker 		}
1317*d83cc019SAndroid Build Coastguard Worker 	}
1318*d83cc019SAndroid Build Coastguard Worker 
1319*d83cc019SAndroid Build Coastguard Worker 	if (w->unbound_duration)
1320*d83cc019SAndroid Build Coastguard Worker 		/* nops + MI_ARB_CHK + MI_BATCH_BUFFER_START */
1321*d83cc019SAndroid Build Coastguard Worker 		w->bb_sz = max(PAGE_SIZE, get_bb_sz(w->preempt_us)) +
1322*d83cc019SAndroid Build Coastguard Worker 			   (1 + 3) * sizeof(uint32_t);
1323*d83cc019SAndroid Build Coastguard Worker 	else
1324*d83cc019SAndroid Build Coastguard Worker 		w->bb_sz = get_bb_sz(w->duration.max);
1325*d83cc019SAndroid Build Coastguard Worker 	w->bb_handle = w->obj[j].handle = gem_create(fd, w->bb_sz + (w->unbound_duration ? 4096 : 0));
1326*d83cc019SAndroid Build Coastguard Worker 	init_bb(w, flags);
1327*d83cc019SAndroid Build Coastguard Worker 	w->obj[j].relocation_count = terminate_bb(w, flags);
1328*d83cc019SAndroid Build Coastguard Worker 
1329*d83cc019SAndroid Build Coastguard Worker 	if (w->obj[j].relocation_count) {
1330*d83cc019SAndroid Build Coastguard Worker 		w->obj[j].relocs_ptr = to_user_pointer(&w->reloc);
1331*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < w->obj[j].relocation_count; i++)
1332*d83cc019SAndroid Build Coastguard Worker 			w->reloc[i].target_handle = 1;
1333*d83cc019SAndroid Build Coastguard Worker 		if (w->unbound_duration)
1334*d83cc019SAndroid Build Coastguard Worker 			w->reloc[0].target_handle = j;
1335*d83cc019SAndroid Build Coastguard Worker 	}
1336*d83cc019SAndroid Build Coastguard Worker 
1337*d83cc019SAndroid Build Coastguard Worker 	w->eb.buffers_ptr = to_user_pointer(w->obj);
1338*d83cc019SAndroid Build Coastguard Worker 	w->eb.buffer_count = j + 1;
1339*d83cc019SAndroid Build Coastguard Worker 	w->eb.rsvd1 = get_ctxid(wrk, w);
1340*d83cc019SAndroid Build Coastguard Worker 
1341*d83cc019SAndroid Build Coastguard Worker 	if (flags & SWAPVCS && engine == VCS1)
1342*d83cc019SAndroid Build Coastguard Worker 		engine = VCS2;
1343*d83cc019SAndroid Build Coastguard Worker 	else if (flags & SWAPVCS && engine == VCS2)
1344*d83cc019SAndroid Build Coastguard Worker 		engine = VCS1;
1345*d83cc019SAndroid Build Coastguard Worker 	eb_update_flags(wrk, w, engine, flags);
1346*d83cc019SAndroid Build Coastguard Worker #ifdef DEBUG
1347*d83cc019SAndroid Build Coastguard Worker 	printf("%u: %u:|", w->idx, w->eb.buffer_count);
1348*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i <= j; i++)
1349*d83cc019SAndroid Build Coastguard Worker 		printf("%x|", w->obj[i].handle);
1350*d83cc019SAndroid Build Coastguard Worker 	printf(" %10lu flags=%llx bb=%x[%u] ctx[%u]=%u\n",
1351*d83cc019SAndroid Build Coastguard Worker 		w->bb_sz, w->eb.flags, w->bb_handle, j, w->context,
1352*d83cc019SAndroid Build Coastguard Worker 		get_ctxid(wrk, w));
1353*d83cc019SAndroid Build Coastguard Worker #endif
1354*d83cc019SAndroid Build Coastguard Worker }
1355*d83cc019SAndroid Build Coastguard Worker 
__ctx_set_prio(uint32_t ctx_id,unsigned int prio)1356*d83cc019SAndroid Build Coastguard Worker static void __ctx_set_prio(uint32_t ctx_id, unsigned int prio)
1357*d83cc019SAndroid Build Coastguard Worker {
1358*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_param param = {
1359*d83cc019SAndroid Build Coastguard Worker 		.ctx_id = ctx_id,
1360*d83cc019SAndroid Build Coastguard Worker 		.param = I915_CONTEXT_PARAM_PRIORITY,
1361*d83cc019SAndroid Build Coastguard Worker 		.value = prio,
1362*d83cc019SAndroid Build Coastguard Worker 	};
1363*d83cc019SAndroid Build Coastguard Worker 
1364*d83cc019SAndroid Build Coastguard Worker 	if (prio)
1365*d83cc019SAndroid Build Coastguard Worker 		gem_context_set_param(fd, &param);
1366*d83cc019SAndroid Build Coastguard Worker }
1367*d83cc019SAndroid Build Coastguard Worker 
__vm_destroy(int i915,uint32_t vm_id)1368*d83cc019SAndroid Build Coastguard Worker static int __vm_destroy(int i915, uint32_t vm_id)
1369*d83cc019SAndroid Build Coastguard Worker {
1370*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_vm_control ctl = { .vm_id = vm_id };
1371*d83cc019SAndroid Build Coastguard Worker 	int err = 0;
1372*d83cc019SAndroid Build Coastguard Worker 
1373*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(i915, DRM_IOCTL_I915_GEM_VM_DESTROY, &ctl)) {
1374*d83cc019SAndroid Build Coastguard Worker 		err = -errno;
1375*d83cc019SAndroid Build Coastguard Worker 		igt_assume(err);
1376*d83cc019SAndroid Build Coastguard Worker 	}
1377*d83cc019SAndroid Build Coastguard Worker 
1378*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
1379*d83cc019SAndroid Build Coastguard Worker 	return err;
1380*d83cc019SAndroid Build Coastguard Worker }
1381*d83cc019SAndroid Build Coastguard Worker 
vm_destroy(int i915,uint32_t vm_id)1382*d83cc019SAndroid Build Coastguard Worker static void vm_destroy(int i915, uint32_t vm_id)
1383*d83cc019SAndroid Build Coastguard Worker {
1384*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(__vm_destroy(i915, vm_id), 0);
1385*d83cc019SAndroid Build Coastguard Worker }
1386*d83cc019SAndroid Build Coastguard Worker 
1387*d83cc019SAndroid Build Coastguard Worker static unsigned int
find_engine(struct i915_engine_class_instance * ci,unsigned int count,enum intel_engine_id engine)1388*d83cc019SAndroid Build Coastguard Worker find_engine(struct i915_engine_class_instance *ci, unsigned int count,
1389*d83cc019SAndroid Build Coastguard Worker 	    enum intel_engine_id engine)
1390*d83cc019SAndroid Build Coastguard Worker {
1391*d83cc019SAndroid Build Coastguard Worker 	struct i915_engine_class_instance e = get_engine(engine);
1392*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
1393*d83cc019SAndroid Build Coastguard Worker 
1394*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < count; i++, ci++) {
1395*d83cc019SAndroid Build Coastguard Worker 		if (!memcmp(&e, ci, sizeof(*ci)))
1396*d83cc019SAndroid Build Coastguard Worker 			return i;
1397*d83cc019SAndroid Build Coastguard Worker 	}
1398*d83cc019SAndroid Build Coastguard Worker 
1399*d83cc019SAndroid Build Coastguard Worker 	igt_assert(0);
1400*d83cc019SAndroid Build Coastguard Worker 	return 0;
1401*d83cc019SAndroid Build Coastguard Worker }
1402*d83cc019SAndroid Build Coastguard Worker 
get_device_sseu(void)1403*d83cc019SAndroid Build Coastguard Worker static struct drm_i915_gem_context_param_sseu get_device_sseu(void)
1404*d83cc019SAndroid Build Coastguard Worker {
1405*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_param param = { };
1406*d83cc019SAndroid Build Coastguard Worker 
1407*d83cc019SAndroid Build Coastguard Worker 	if (device_sseu.slice_mask == -1) {
1408*d83cc019SAndroid Build Coastguard Worker 		param.param = I915_CONTEXT_PARAM_SSEU;
1409*d83cc019SAndroid Build Coastguard Worker 		param.value = (uintptr_t)&device_sseu;
1410*d83cc019SAndroid Build Coastguard Worker 
1411*d83cc019SAndroid Build Coastguard Worker 		gem_context_get_param(fd, &param);
1412*d83cc019SAndroid Build Coastguard Worker 	}
1413*d83cc019SAndroid Build Coastguard Worker 
1414*d83cc019SAndroid Build Coastguard Worker 	return device_sseu;
1415*d83cc019SAndroid Build Coastguard Worker }
1416*d83cc019SAndroid Build Coastguard Worker 
1417*d83cc019SAndroid Build Coastguard Worker static uint64_t
set_ctx_sseu(struct ctx * ctx,uint64_t slice_mask)1418*d83cc019SAndroid Build Coastguard Worker set_ctx_sseu(struct ctx *ctx, uint64_t slice_mask)
1419*d83cc019SAndroid Build Coastguard Worker {
1420*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_param_sseu sseu = get_device_sseu();
1421*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_context_param param = { };
1422*d83cc019SAndroid Build Coastguard Worker 
1423*d83cc019SAndroid Build Coastguard Worker 	if (slice_mask == -1)
1424*d83cc019SAndroid Build Coastguard Worker 		slice_mask = device_sseu.slice_mask;
1425*d83cc019SAndroid Build Coastguard Worker 
1426*d83cc019SAndroid Build Coastguard Worker 	if (ctx->engine_map && ctx->wants_balance) {
1427*d83cc019SAndroid Build Coastguard Worker 		sseu.flags = I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX;
1428*d83cc019SAndroid Build Coastguard Worker 		sseu.engine.engine_class = I915_ENGINE_CLASS_INVALID;
1429*d83cc019SAndroid Build Coastguard Worker 		sseu.engine.engine_instance = 0;
1430*d83cc019SAndroid Build Coastguard Worker 	}
1431*d83cc019SAndroid Build Coastguard Worker 
1432*d83cc019SAndroid Build Coastguard Worker 	sseu.slice_mask = slice_mask;
1433*d83cc019SAndroid Build Coastguard Worker 
1434*d83cc019SAndroid Build Coastguard Worker 	param.ctx_id = ctx->id;
1435*d83cc019SAndroid Build Coastguard Worker 	param.param = I915_CONTEXT_PARAM_SSEU;
1436*d83cc019SAndroid Build Coastguard Worker 	param.size = sizeof(sseu);
1437*d83cc019SAndroid Build Coastguard Worker 	param.value = (uintptr_t)&sseu;
1438*d83cc019SAndroid Build Coastguard Worker 
1439*d83cc019SAndroid Build Coastguard Worker 	gem_context_set_param(fd, &param);
1440*d83cc019SAndroid Build Coastguard Worker 
1441*d83cc019SAndroid Build Coastguard Worker 	return slice_mask;
1442*d83cc019SAndroid Build Coastguard Worker }
1443*d83cc019SAndroid Build Coastguard Worker 
sizeof_load_balance(int count)1444*d83cc019SAndroid Build Coastguard Worker static size_t sizeof_load_balance(int count)
1445*d83cc019SAndroid Build Coastguard Worker {
1446*d83cc019SAndroid Build Coastguard Worker 	return offsetof(struct i915_context_engines_load_balance,
1447*d83cc019SAndroid Build Coastguard Worker 			engines[count]);
1448*d83cc019SAndroid Build Coastguard Worker }
1449*d83cc019SAndroid Build Coastguard Worker 
sizeof_param_engines(int count)1450*d83cc019SAndroid Build Coastguard Worker static size_t sizeof_param_engines(int count)
1451*d83cc019SAndroid Build Coastguard Worker {
1452*d83cc019SAndroid Build Coastguard Worker 	return offsetof(struct i915_context_param_engines,
1453*d83cc019SAndroid Build Coastguard Worker 			engines[count]);
1454*d83cc019SAndroid Build Coastguard Worker }
1455*d83cc019SAndroid Build Coastguard Worker 
sizeof_engines_bond(int count)1456*d83cc019SAndroid Build Coastguard Worker static size_t sizeof_engines_bond(int count)
1457*d83cc019SAndroid Build Coastguard Worker {
1458*d83cc019SAndroid Build Coastguard Worker 	return offsetof(struct i915_context_engines_bond,
1459*d83cc019SAndroid Build Coastguard Worker 			engines[count]);
1460*d83cc019SAndroid Build Coastguard Worker }
1461*d83cc019SAndroid Build Coastguard Worker 
1462*d83cc019SAndroid Build Coastguard Worker #define alloca0(sz) ({ size_t sz__ = (sz); memset(alloca(sz__), 0, sz__); })
1463*d83cc019SAndroid Build Coastguard Worker 
1464*d83cc019SAndroid Build Coastguard Worker static int
prepare_workload(unsigned int id,struct workload * wrk,unsigned int flags)1465*d83cc019SAndroid Build Coastguard Worker prepare_workload(unsigned int id, struct workload *wrk, unsigned int flags)
1466*d83cc019SAndroid Build Coastguard Worker {
1467*d83cc019SAndroid Build Coastguard Worker 	unsigned int ctx_vcs;
1468*d83cc019SAndroid Build Coastguard Worker 	int max_ctx = -1;
1469*d83cc019SAndroid Build Coastguard Worker 	struct w_step *w;
1470*d83cc019SAndroid Build Coastguard Worker 	int i, j;
1471*d83cc019SAndroid Build Coastguard Worker 
1472*d83cc019SAndroid Build Coastguard Worker 	wrk->id = id;
1473*d83cc019SAndroid Build Coastguard Worker 	wrk->prng = rand();
1474*d83cc019SAndroid Build Coastguard Worker 	wrk->bb_prng = (wrk->flags & SYNCEDCLIENTS) ? master_prng : rand();
1475*d83cc019SAndroid Build Coastguard Worker 	wrk->run = true;
1476*d83cc019SAndroid Build Coastguard Worker 
1477*d83cc019SAndroid Build Coastguard Worker 	ctx_vcs =  0;
1478*d83cc019SAndroid Build Coastguard Worker 	if (flags & INITVCSRR)
1479*d83cc019SAndroid Build Coastguard Worker 		ctx_vcs = id & 1;
1480*d83cc019SAndroid Build Coastguard Worker 	wrk->vcs_rr = ctx_vcs;
1481*d83cc019SAndroid Build Coastguard Worker 
1482*d83cc019SAndroid Build Coastguard Worker 	if (flags & GLOBAL_BALANCE) {
1483*d83cc019SAndroid Build Coastguard Worker 		int ret = pthread_mutex_init(&wrk->mutex, NULL);
1484*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ret == 0);
1485*d83cc019SAndroid Build Coastguard Worker 	}
1486*d83cc019SAndroid Build Coastguard Worker 
1487*d83cc019SAndroid Build Coastguard Worker 	if (flags & SEQNO) {
1488*d83cc019SAndroid Build Coastguard Worker 		if (!(flags & GLOBAL_BALANCE) || id == 0) {
1489*d83cc019SAndroid Build Coastguard Worker 			uint32_t handle;
1490*d83cc019SAndroid Build Coastguard Worker 
1491*d83cc019SAndroid Build Coastguard Worker 			handle = gem_create(fd, 4096);
1492*d83cc019SAndroid Build Coastguard Worker 			gem_set_caching(fd, handle, I915_CACHING_CACHED);
1493*d83cc019SAndroid Build Coastguard Worker 			wrk->status_object[0].handle = handle;
1494*d83cc019SAndroid Build Coastguard Worker 			wrk->status_page = gem_mmap__cpu(fd, handle, 0, 4096,
1495*d83cc019SAndroid Build Coastguard Worker 							 PROT_READ);
1496*d83cc019SAndroid Build Coastguard Worker 
1497*d83cc019SAndroid Build Coastguard Worker 			handle = gem_create(fd, 4096);
1498*d83cc019SAndroid Build Coastguard Worker 			wrk->status_object[1].handle = handle;
1499*d83cc019SAndroid Build Coastguard Worker 			wrk->status_cs = gem_mmap__wc(fd, handle,
1500*d83cc019SAndroid Build Coastguard Worker 						      0, 4096, PROT_WRITE);
1501*d83cc019SAndroid Build Coastguard Worker 		}
1502*d83cc019SAndroid Build Coastguard Worker 	}
1503*d83cc019SAndroid Build Coastguard Worker 
1504*d83cc019SAndroid Build Coastguard Worker 	/*
1505*d83cc019SAndroid Build Coastguard Worker 	 * Pre-scan workload steps to allocate context list storage.
1506*d83cc019SAndroid Build Coastguard Worker 	 */
1507*d83cc019SAndroid Build Coastguard Worker 	for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
1508*d83cc019SAndroid Build Coastguard Worker 		int ctx = w->context * 2 + 1; /* Odd slots are special. */
1509*d83cc019SAndroid Build Coastguard Worker 		int delta;
1510*d83cc019SAndroid Build Coastguard Worker 
1511*d83cc019SAndroid Build Coastguard Worker 		if (ctx <= max_ctx)
1512*d83cc019SAndroid Build Coastguard Worker 			continue;
1513*d83cc019SAndroid Build Coastguard Worker 
1514*d83cc019SAndroid Build Coastguard Worker 		delta = ctx + 1 - wrk->nr_ctxs;
1515*d83cc019SAndroid Build Coastguard Worker 
1516*d83cc019SAndroid Build Coastguard Worker 		wrk->nr_ctxs += delta;
1517*d83cc019SAndroid Build Coastguard Worker 		wrk->ctx_list = realloc(wrk->ctx_list,
1518*d83cc019SAndroid Build Coastguard Worker 					wrk->nr_ctxs * sizeof(*wrk->ctx_list));
1519*d83cc019SAndroid Build Coastguard Worker 		memset(&wrk->ctx_list[wrk->nr_ctxs - delta], 0,
1520*d83cc019SAndroid Build Coastguard Worker 			delta * sizeof(*wrk->ctx_list));
1521*d83cc019SAndroid Build Coastguard Worker 
1522*d83cc019SAndroid Build Coastguard Worker 		max_ctx = ctx;
1523*d83cc019SAndroid Build Coastguard Worker 	}
1524*d83cc019SAndroid Build Coastguard Worker 
1525*d83cc019SAndroid Build Coastguard Worker 	/*
1526*d83cc019SAndroid Build Coastguard Worker 	 * Identify if contexts target specific engine instances and if they
1527*d83cc019SAndroid Build Coastguard Worker 	 * want to be balanced.
1528*d83cc019SAndroid Build Coastguard Worker 	 *
1529*d83cc019SAndroid Build Coastguard Worker 	 * Transfer over engine map configuration from the workload step.
1530*d83cc019SAndroid Build Coastguard Worker 	 */
1531*d83cc019SAndroid Build Coastguard Worker 	for (j = 0; j < wrk->nr_ctxs; j += 2) {
1532*d83cc019SAndroid Build Coastguard Worker 		struct ctx *ctx = &wrk->ctx_list[j];
1533*d83cc019SAndroid Build Coastguard Worker 
1534*d83cc019SAndroid Build Coastguard Worker 		bool targets = false;
1535*d83cc019SAndroid Build Coastguard Worker 		bool balance = false;
1536*d83cc019SAndroid Build Coastguard Worker 
1537*d83cc019SAndroid Build Coastguard Worker 		for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
1538*d83cc019SAndroid Build Coastguard Worker 			if (w->context != (j / 2))
1539*d83cc019SAndroid Build Coastguard Worker 				continue;
1540*d83cc019SAndroid Build Coastguard Worker 
1541*d83cc019SAndroid Build Coastguard Worker 			if (w->type == BATCH) {
1542*d83cc019SAndroid Build Coastguard Worker 				if (w->engine == VCS)
1543*d83cc019SAndroid Build Coastguard Worker 					balance = true;
1544*d83cc019SAndroid Build Coastguard Worker 				else
1545*d83cc019SAndroid Build Coastguard Worker 					targets = true;
1546*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == ENGINE_MAP) {
1547*d83cc019SAndroid Build Coastguard Worker 				ctx->engine_map = w->engine_map;
1548*d83cc019SAndroid Build Coastguard Worker 				ctx->engine_map_count = w->engine_map_count;
1549*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == LOAD_BALANCE) {
1550*d83cc019SAndroid Build Coastguard Worker 				if (!ctx->engine_map) {
1551*d83cc019SAndroid Build Coastguard Worker 					wsim_err("Load balancing needs an engine map!\n");
1552*d83cc019SAndroid Build Coastguard Worker 					return 1;
1553*d83cc019SAndroid Build Coastguard Worker 				}
1554*d83cc019SAndroid Build Coastguard Worker 				ctx->wants_balance = w->load_balance;
1555*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == BOND) {
1556*d83cc019SAndroid Build Coastguard Worker 				if (!ctx->wants_balance) {
1557*d83cc019SAndroid Build Coastguard Worker 					wsim_err("Engine bonds need load balancing engine map!\n");
1558*d83cc019SAndroid Build Coastguard Worker 					return 1;
1559*d83cc019SAndroid Build Coastguard Worker 				}
1560*d83cc019SAndroid Build Coastguard Worker 				ctx->bond_count++;
1561*d83cc019SAndroid Build Coastguard Worker 				ctx->bonds = realloc(ctx->bonds,
1562*d83cc019SAndroid Build Coastguard Worker 						     ctx->bond_count *
1563*d83cc019SAndroid Build Coastguard Worker 						     sizeof(struct bond));
1564*d83cc019SAndroid Build Coastguard Worker 				igt_assert(ctx->bonds);
1565*d83cc019SAndroid Build Coastguard Worker 				ctx->bonds[ctx->bond_count - 1].mask =
1566*d83cc019SAndroid Build Coastguard Worker 					w->bond_mask;
1567*d83cc019SAndroid Build Coastguard Worker 				ctx->bonds[ctx->bond_count - 1].master =
1568*d83cc019SAndroid Build Coastguard Worker 					w->bond_master;
1569*d83cc019SAndroid Build Coastguard Worker 			}
1570*d83cc019SAndroid Build Coastguard Worker 		}
1571*d83cc019SAndroid Build Coastguard Worker 
1572*d83cc019SAndroid Build Coastguard Worker 		wrk->ctx_list[j].targets_instance = targets;
1573*d83cc019SAndroid Build Coastguard Worker 		if (flags & I915)
1574*d83cc019SAndroid Build Coastguard Worker 			wrk->ctx_list[j].wants_balance |= balance;
1575*d83cc019SAndroid Build Coastguard Worker 	}
1576*d83cc019SAndroid Build Coastguard Worker 
1577*d83cc019SAndroid Build Coastguard Worker 	/*
1578*d83cc019SAndroid Build Coastguard Worker 	 * Ensure VCS is not allowed with engine map contexts.
1579*d83cc019SAndroid Build Coastguard Worker 	 */
1580*d83cc019SAndroid Build Coastguard Worker 	for (j = 0; j < wrk->nr_ctxs; j += 2) {
1581*d83cc019SAndroid Build Coastguard Worker 		for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
1582*d83cc019SAndroid Build Coastguard Worker 			if (w->context != (j / 2))
1583*d83cc019SAndroid Build Coastguard Worker 				continue;
1584*d83cc019SAndroid Build Coastguard Worker 
1585*d83cc019SAndroid Build Coastguard Worker 			if (w->type != BATCH)
1586*d83cc019SAndroid Build Coastguard Worker 				continue;
1587*d83cc019SAndroid Build Coastguard Worker 
1588*d83cc019SAndroid Build Coastguard Worker 			if (wrk->ctx_list[j].engine_map &&
1589*d83cc019SAndroid Build Coastguard Worker 			    !wrk->ctx_list[j].wants_balance &&
1590*d83cc019SAndroid Build Coastguard Worker 			    (w->engine == VCS || w->engine == DEFAULT)) {
1591*d83cc019SAndroid Build Coastguard Worker 				wsim_err("Batches targetting engine maps must use explicit engines!\n");
1592*d83cc019SAndroid Build Coastguard Worker 				return -1;
1593*d83cc019SAndroid Build Coastguard Worker 			}
1594*d83cc019SAndroid Build Coastguard Worker 		}
1595*d83cc019SAndroid Build Coastguard Worker 	}
1596*d83cc019SAndroid Build Coastguard Worker 
1597*d83cc019SAndroid Build Coastguard Worker 
1598*d83cc019SAndroid Build Coastguard Worker 	/*
1599*d83cc019SAndroid Build Coastguard Worker 	 * Create and configure contexts.
1600*d83cc019SAndroid Build Coastguard Worker 	 */
1601*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < wrk->nr_ctxs; i += 2) {
1602*d83cc019SAndroid Build Coastguard Worker 		struct ctx *ctx = &wrk->ctx_list[i];
1603*d83cc019SAndroid Build Coastguard Worker 		uint32_t ctx_id, share_vm = 0;
1604*d83cc019SAndroid Build Coastguard Worker 
1605*d83cc019SAndroid Build Coastguard Worker 		if (ctx->id)
1606*d83cc019SAndroid Build Coastguard Worker 			continue;
1607*d83cc019SAndroid Build Coastguard Worker 
1608*d83cc019SAndroid Build Coastguard Worker 		if ((flags & I915) || ctx->engine_map) {
1609*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_context_create_ext_setparam ext = {
1610*d83cc019SAndroid Build Coastguard Worker 				.base.name = I915_CONTEXT_CREATE_EXT_SETPARAM,
1611*d83cc019SAndroid Build Coastguard Worker 				.param.param = I915_CONTEXT_PARAM_VM,
1612*d83cc019SAndroid Build Coastguard Worker 			};
1613*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_context_create_ext args = { };
1614*d83cc019SAndroid Build Coastguard Worker 
1615*d83cc019SAndroid Build Coastguard Worker 			/* Find existing context to share ppgtt with. */
1616*d83cc019SAndroid Build Coastguard Worker 			for (j = 0; j < wrk->nr_ctxs; j++) {
1617*d83cc019SAndroid Build Coastguard Worker 				struct drm_i915_gem_context_param param = {
1618*d83cc019SAndroid Build Coastguard Worker 					.param = I915_CONTEXT_PARAM_VM,
1619*d83cc019SAndroid Build Coastguard Worker 				};
1620*d83cc019SAndroid Build Coastguard Worker 
1621*d83cc019SAndroid Build Coastguard Worker 				if (!wrk->ctx_list[j].id)
1622*d83cc019SAndroid Build Coastguard Worker 					continue;
1623*d83cc019SAndroid Build Coastguard Worker 
1624*d83cc019SAndroid Build Coastguard Worker 				param.ctx_id = wrk->ctx_list[j].id;
1625*d83cc019SAndroid Build Coastguard Worker 
1626*d83cc019SAndroid Build Coastguard Worker 				gem_context_get_param(fd, &param);
1627*d83cc019SAndroid Build Coastguard Worker 				igt_assert(param.value);
1628*d83cc019SAndroid Build Coastguard Worker 
1629*d83cc019SAndroid Build Coastguard Worker 				share_vm = param.value;
1630*d83cc019SAndroid Build Coastguard Worker 
1631*d83cc019SAndroid Build Coastguard Worker 				ext.param.value = share_vm;
1632*d83cc019SAndroid Build Coastguard Worker 				args.flags =
1633*d83cc019SAndroid Build Coastguard Worker 				    I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS;
1634*d83cc019SAndroid Build Coastguard Worker 				args.extensions = to_user_pointer(&ext);
1635*d83cc019SAndroid Build Coastguard Worker 				break;
1636*d83cc019SAndroid Build Coastguard Worker 			}
1637*d83cc019SAndroid Build Coastguard Worker 
1638*d83cc019SAndroid Build Coastguard Worker 			if ((!ctx->engine_map && !ctx->targets_instance) ||
1639*d83cc019SAndroid Build Coastguard Worker 			    (ctx->engine_map && ctx->wants_balance))
1640*d83cc019SAndroid Build Coastguard Worker 				args.flags |=
1641*d83cc019SAndroid Build Coastguard Worker 				     I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE;
1642*d83cc019SAndroid Build Coastguard Worker 
1643*d83cc019SAndroid Build Coastguard Worker 			drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT,
1644*d83cc019SAndroid Build Coastguard Worker 				 &args);
1645*d83cc019SAndroid Build Coastguard Worker 
1646*d83cc019SAndroid Build Coastguard Worker 			ctx_id = args.ctx_id;
1647*d83cc019SAndroid Build Coastguard Worker 		} else {
1648*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_context_create args = {};
1649*d83cc019SAndroid Build Coastguard Worker 
1650*d83cc019SAndroid Build Coastguard Worker 			drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &args);
1651*d83cc019SAndroid Build Coastguard Worker 			ctx_id = args.ctx_id;
1652*d83cc019SAndroid Build Coastguard Worker 		}
1653*d83cc019SAndroid Build Coastguard Worker 
1654*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ctx_id);
1655*d83cc019SAndroid Build Coastguard Worker 		ctx->id = ctx_id;
1656*d83cc019SAndroid Build Coastguard Worker 		ctx->sseu = device_sseu.slice_mask;
1657*d83cc019SAndroid Build Coastguard Worker 
1658*d83cc019SAndroid Build Coastguard Worker 		if (flags & GLOBAL_BALANCE) {
1659*d83cc019SAndroid Build Coastguard Worker 			ctx->static_vcs = context_vcs_rr;
1660*d83cc019SAndroid Build Coastguard Worker 			context_vcs_rr ^= 1;
1661*d83cc019SAndroid Build Coastguard Worker 		} else {
1662*d83cc019SAndroid Build Coastguard Worker 			ctx->static_vcs = ctx_vcs;
1663*d83cc019SAndroid Build Coastguard Worker 			ctx_vcs ^= 1;
1664*d83cc019SAndroid Build Coastguard Worker 		}
1665*d83cc019SAndroid Build Coastguard Worker 
1666*d83cc019SAndroid Build Coastguard Worker 		__ctx_set_prio(ctx_id, wrk->prio);
1667*d83cc019SAndroid Build Coastguard Worker 
1668*d83cc019SAndroid Build Coastguard Worker 		/*
1669*d83cc019SAndroid Build Coastguard Worker 		 * Do we need a separate context to satisfy this workloads which
1670*d83cc019SAndroid Build Coastguard Worker 		 * both want to target specific engines and be balanced by i915?
1671*d83cc019SAndroid Build Coastguard Worker 		 */
1672*d83cc019SAndroid Build Coastguard Worker 		if ((flags & I915) && ctx->wants_balance &&
1673*d83cc019SAndroid Build Coastguard Worker 		    ctx->targets_instance && !ctx->engine_map) {
1674*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_context_create_ext_setparam ext = {
1675*d83cc019SAndroid Build Coastguard Worker 				.base.name = I915_CONTEXT_CREATE_EXT_SETPARAM,
1676*d83cc019SAndroid Build Coastguard Worker 				.param.param = I915_CONTEXT_PARAM_VM,
1677*d83cc019SAndroid Build Coastguard Worker 				.param.value = share_vm,
1678*d83cc019SAndroid Build Coastguard Worker 			};
1679*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_context_create_ext args = {
1680*d83cc019SAndroid Build Coastguard Worker 				.extensions = to_user_pointer(&ext),
1681*d83cc019SAndroid Build Coastguard Worker 				.flags =
1682*d83cc019SAndroid Build Coastguard Worker 				    I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS |
1683*d83cc019SAndroid Build Coastguard Worker 				    I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE,
1684*d83cc019SAndroid Build Coastguard Worker 			};
1685*d83cc019SAndroid Build Coastguard Worker 
1686*d83cc019SAndroid Build Coastguard Worker 			igt_assert(share_vm);
1687*d83cc019SAndroid Build Coastguard Worker 
1688*d83cc019SAndroid Build Coastguard Worker 			drmIoctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT,
1689*d83cc019SAndroid Build Coastguard Worker 				 &args);
1690*d83cc019SAndroid Build Coastguard Worker 
1691*d83cc019SAndroid Build Coastguard Worker 			igt_assert(args.ctx_id);
1692*d83cc019SAndroid Build Coastguard Worker 			ctx_id = args.ctx_id;
1693*d83cc019SAndroid Build Coastguard Worker 			wrk->ctx_list[i + 1].id = args.ctx_id;
1694*d83cc019SAndroid Build Coastguard Worker 
1695*d83cc019SAndroid Build Coastguard Worker 			__ctx_set_prio(ctx_id, wrk->prio);
1696*d83cc019SAndroid Build Coastguard Worker 		}
1697*d83cc019SAndroid Build Coastguard Worker 
1698*d83cc019SAndroid Build Coastguard Worker 		if (ctx->engine_map) {
1699*d83cc019SAndroid Build Coastguard Worker 			struct i915_context_param_engines *set_engines =
1700*d83cc019SAndroid Build Coastguard Worker 				alloca0(sizeof_param_engines(ctx->engine_map_count + 1));
1701*d83cc019SAndroid Build Coastguard Worker 			struct i915_context_engines_load_balance *load_balance =
1702*d83cc019SAndroid Build Coastguard Worker 				alloca0(sizeof_load_balance(ctx->engine_map_count));
1703*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_context_param param = {
1704*d83cc019SAndroid Build Coastguard Worker 				.ctx_id = ctx_id,
1705*d83cc019SAndroid Build Coastguard Worker 				.param = I915_CONTEXT_PARAM_ENGINES,
1706*d83cc019SAndroid Build Coastguard Worker 				.size = sizeof_param_engines(ctx->engine_map_count + 1),
1707*d83cc019SAndroid Build Coastguard Worker 				.value = to_user_pointer(set_engines),
1708*d83cc019SAndroid Build Coastguard Worker 			};
1709*d83cc019SAndroid Build Coastguard Worker 			struct i915_context_engines_bond *last = NULL;
1710*d83cc019SAndroid Build Coastguard Worker 
1711*d83cc019SAndroid Build Coastguard Worker 			if (ctx->wants_balance) {
1712*d83cc019SAndroid Build Coastguard Worker 				set_engines->extensions =
1713*d83cc019SAndroid Build Coastguard Worker 					to_user_pointer(load_balance);
1714*d83cc019SAndroid Build Coastguard Worker 
1715*d83cc019SAndroid Build Coastguard Worker 				load_balance->base.name =
1716*d83cc019SAndroid Build Coastguard Worker 					I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE;
1717*d83cc019SAndroid Build Coastguard Worker 				load_balance->num_siblings =
1718*d83cc019SAndroid Build Coastguard Worker 					ctx->engine_map_count;
1719*d83cc019SAndroid Build Coastguard Worker 
1720*d83cc019SAndroid Build Coastguard Worker 				for (j = 0; j < ctx->engine_map_count; j++)
1721*d83cc019SAndroid Build Coastguard Worker 					load_balance->engines[j] =
1722*d83cc019SAndroid Build Coastguard Worker 						get_engine(ctx->engine_map[j]);
1723*d83cc019SAndroid Build Coastguard Worker 			}
1724*d83cc019SAndroid Build Coastguard Worker 
1725*d83cc019SAndroid Build Coastguard Worker 			/* Reserve slot for virtual engine. */
1726*d83cc019SAndroid Build Coastguard Worker 			set_engines->engines[0].engine_class =
1727*d83cc019SAndroid Build Coastguard Worker 				I915_ENGINE_CLASS_INVALID;
1728*d83cc019SAndroid Build Coastguard Worker 			set_engines->engines[0].engine_instance =
1729*d83cc019SAndroid Build Coastguard Worker 				I915_ENGINE_CLASS_INVALID_NONE;
1730*d83cc019SAndroid Build Coastguard Worker 
1731*d83cc019SAndroid Build Coastguard Worker 			for (j = 1; j <= ctx->engine_map_count; j++)
1732*d83cc019SAndroid Build Coastguard Worker 				set_engines->engines[j] =
1733*d83cc019SAndroid Build Coastguard Worker 					get_engine(ctx->engine_map[j - 1]);
1734*d83cc019SAndroid Build Coastguard Worker 
1735*d83cc019SAndroid Build Coastguard Worker 			last = NULL;
1736*d83cc019SAndroid Build Coastguard Worker 			for (j = 0; j < ctx->bond_count; j++) {
1737*d83cc019SAndroid Build Coastguard Worker 				unsigned long mask = ctx->bonds[j].mask;
1738*d83cc019SAndroid Build Coastguard Worker 				struct i915_context_engines_bond *bond =
1739*d83cc019SAndroid Build Coastguard Worker 					alloca0(sizeof_engines_bond(__builtin_popcount(mask)));
1740*d83cc019SAndroid Build Coastguard Worker 				unsigned int b, e;
1741*d83cc019SAndroid Build Coastguard Worker 
1742*d83cc019SAndroid Build Coastguard Worker 				bond->base.next_extension = to_user_pointer(last);
1743*d83cc019SAndroid Build Coastguard Worker 				bond->base.name = I915_CONTEXT_ENGINES_EXT_BOND;
1744*d83cc019SAndroid Build Coastguard Worker 
1745*d83cc019SAndroid Build Coastguard Worker 				bond->virtual_index = 0;
1746*d83cc019SAndroid Build Coastguard Worker 				bond->master = get_engine(ctx->bonds[j].master);
1747*d83cc019SAndroid Build Coastguard Worker 
1748*d83cc019SAndroid Build Coastguard Worker 				for (b = 0, e = 0; mask; e++, mask >>= 1) {
1749*d83cc019SAndroid Build Coastguard Worker 					unsigned int idx;
1750*d83cc019SAndroid Build Coastguard Worker 
1751*d83cc019SAndroid Build Coastguard Worker 					if (!(mask & 1))
1752*d83cc019SAndroid Build Coastguard Worker 						continue;
1753*d83cc019SAndroid Build Coastguard Worker 
1754*d83cc019SAndroid Build Coastguard Worker 					idx = find_engine(&set_engines->engines[1],
1755*d83cc019SAndroid Build Coastguard Worker 							  ctx->engine_map_count,
1756*d83cc019SAndroid Build Coastguard Worker 							  e);
1757*d83cc019SAndroid Build Coastguard Worker 					bond->engines[b++] =
1758*d83cc019SAndroid Build Coastguard Worker 						set_engines->engines[1 + idx];
1759*d83cc019SAndroid Build Coastguard Worker 				}
1760*d83cc019SAndroid Build Coastguard Worker 
1761*d83cc019SAndroid Build Coastguard Worker 				last = bond;
1762*d83cc019SAndroid Build Coastguard Worker 			}
1763*d83cc019SAndroid Build Coastguard Worker 			load_balance->base.next_extension = to_user_pointer(last);
1764*d83cc019SAndroid Build Coastguard Worker 
1765*d83cc019SAndroid Build Coastguard Worker 			gem_context_set_param(fd, &param);
1766*d83cc019SAndroid Build Coastguard Worker 		} else if (ctx->wants_balance) {
1767*d83cc019SAndroid Build Coastguard Worker 			const unsigned int count = num_engines_in_class(VCS);
1768*d83cc019SAndroid Build Coastguard Worker 			struct i915_context_engines_load_balance *load_balance =
1769*d83cc019SAndroid Build Coastguard Worker 				alloca0(sizeof_load_balance(count));
1770*d83cc019SAndroid Build Coastguard Worker 			struct i915_context_param_engines *set_engines =
1771*d83cc019SAndroid Build Coastguard Worker 				alloca0(sizeof_param_engines(count + 1));
1772*d83cc019SAndroid Build Coastguard Worker 			struct drm_i915_gem_context_param param = {
1773*d83cc019SAndroid Build Coastguard Worker 				.ctx_id = ctx_id,
1774*d83cc019SAndroid Build Coastguard Worker 				.param = I915_CONTEXT_PARAM_ENGINES,
1775*d83cc019SAndroid Build Coastguard Worker 				.size = sizeof_param_engines(count + 1),
1776*d83cc019SAndroid Build Coastguard Worker 				.value = to_user_pointer(set_engines),
1777*d83cc019SAndroid Build Coastguard Worker 			};
1778*d83cc019SAndroid Build Coastguard Worker 
1779*d83cc019SAndroid Build Coastguard Worker 			set_engines->extensions = to_user_pointer(load_balance);
1780*d83cc019SAndroid Build Coastguard Worker 
1781*d83cc019SAndroid Build Coastguard Worker 			set_engines->engines[0].engine_class =
1782*d83cc019SAndroid Build Coastguard Worker 				I915_ENGINE_CLASS_INVALID;
1783*d83cc019SAndroid Build Coastguard Worker 			set_engines->engines[0].engine_instance =
1784*d83cc019SAndroid Build Coastguard Worker 				I915_ENGINE_CLASS_INVALID_NONE;
1785*d83cc019SAndroid Build Coastguard Worker 			fill_engines_class(&set_engines->engines[1], VCS);
1786*d83cc019SAndroid Build Coastguard Worker 
1787*d83cc019SAndroid Build Coastguard Worker 			load_balance->base.name =
1788*d83cc019SAndroid Build Coastguard Worker 				I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE;
1789*d83cc019SAndroid Build Coastguard Worker 			load_balance->num_siblings = count;
1790*d83cc019SAndroid Build Coastguard Worker 
1791*d83cc019SAndroid Build Coastguard Worker 			fill_engines_class(&load_balance->engines[0], VCS);
1792*d83cc019SAndroid Build Coastguard Worker 
1793*d83cc019SAndroid Build Coastguard Worker 			gem_context_set_param(fd, &param);
1794*d83cc019SAndroid Build Coastguard Worker 		}
1795*d83cc019SAndroid Build Coastguard Worker 
1796*d83cc019SAndroid Build Coastguard Worker 		if (wrk->sseu) {
1797*d83cc019SAndroid Build Coastguard Worker 			/* Set to slice 0 only, one slice. */
1798*d83cc019SAndroid Build Coastguard Worker 			ctx->sseu = set_ctx_sseu(ctx, 1);
1799*d83cc019SAndroid Build Coastguard Worker 		}
1800*d83cc019SAndroid Build Coastguard Worker 
1801*d83cc019SAndroid Build Coastguard Worker 		if (share_vm)
1802*d83cc019SAndroid Build Coastguard Worker 			vm_destroy(fd, share_vm);
1803*d83cc019SAndroid Build Coastguard Worker 	}
1804*d83cc019SAndroid Build Coastguard Worker 
1805*d83cc019SAndroid Build Coastguard Worker 	/* Record default preemption. */
1806*d83cc019SAndroid Build Coastguard Worker 	for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
1807*d83cc019SAndroid Build Coastguard Worker 		if (w->type == BATCH)
1808*d83cc019SAndroid Build Coastguard Worker 			w->preempt_us = 100;
1809*d83cc019SAndroid Build Coastguard Worker 	}
1810*d83cc019SAndroid Build Coastguard Worker 
1811*d83cc019SAndroid Build Coastguard Worker 	/*
1812*d83cc019SAndroid Build Coastguard Worker 	 * Scan for contexts with modified preemption config and record their
1813*d83cc019SAndroid Build Coastguard Worker 	 * preemption period for the following steps belonging to the same
1814*d83cc019SAndroid Build Coastguard Worker 	 * context.
1815*d83cc019SAndroid Build Coastguard Worker 	 */
1816*d83cc019SAndroid Build Coastguard Worker 	for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
1817*d83cc019SAndroid Build Coastguard Worker 		struct w_step *w2;
1818*d83cc019SAndroid Build Coastguard Worker 
1819*d83cc019SAndroid Build Coastguard Worker 		if (w->type != PREEMPTION)
1820*d83cc019SAndroid Build Coastguard Worker 			continue;
1821*d83cc019SAndroid Build Coastguard Worker 
1822*d83cc019SAndroid Build Coastguard Worker 		for (j = i + 1; j < wrk->nr_steps; j++) {
1823*d83cc019SAndroid Build Coastguard Worker 			w2 = &wrk->steps[j];
1824*d83cc019SAndroid Build Coastguard Worker 
1825*d83cc019SAndroid Build Coastguard Worker 			if (w2->context != w->context)
1826*d83cc019SAndroid Build Coastguard Worker 				continue;
1827*d83cc019SAndroid Build Coastguard Worker 			else if (w2->type == PREEMPTION)
1828*d83cc019SAndroid Build Coastguard Worker 				break;
1829*d83cc019SAndroid Build Coastguard Worker 			else if (w2->type != BATCH)
1830*d83cc019SAndroid Build Coastguard Worker 				continue;
1831*d83cc019SAndroid Build Coastguard Worker 
1832*d83cc019SAndroid Build Coastguard Worker 			w2->preempt_us = w->period;
1833*d83cc019SAndroid Build Coastguard Worker 		}
1834*d83cc019SAndroid Build Coastguard Worker 	}
1835*d83cc019SAndroid Build Coastguard Worker 
1836*d83cc019SAndroid Build Coastguard Worker 	/*
1837*d83cc019SAndroid Build Coastguard Worker 	 * Scan for SSEU control steps.
1838*d83cc019SAndroid Build Coastguard Worker 	 */
1839*d83cc019SAndroid Build Coastguard Worker 	for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
1840*d83cc019SAndroid Build Coastguard Worker 		if (w->type == SSEU) {
1841*d83cc019SAndroid Build Coastguard Worker 			get_device_sseu();
1842*d83cc019SAndroid Build Coastguard Worker 			break;
1843*d83cc019SAndroid Build Coastguard Worker 		}
1844*d83cc019SAndroid Build Coastguard Worker 	}
1845*d83cc019SAndroid Build Coastguard Worker 
1846*d83cc019SAndroid Build Coastguard Worker 	/*
1847*d83cc019SAndroid Build Coastguard Worker 	 * Allocate batch buffers.
1848*d83cc019SAndroid Build Coastguard Worker 	 */
1849*d83cc019SAndroid Build Coastguard Worker 	for (i = 0, w = wrk->steps; i < wrk->nr_steps; i++, w++) {
1850*d83cc019SAndroid Build Coastguard Worker 		unsigned int _flags = flags;
1851*d83cc019SAndroid Build Coastguard Worker 		enum intel_engine_id engine = w->engine;
1852*d83cc019SAndroid Build Coastguard Worker 
1853*d83cc019SAndroid Build Coastguard Worker 		if (w->type != BATCH)
1854*d83cc019SAndroid Build Coastguard Worker 			continue;
1855*d83cc019SAndroid Build Coastguard Worker 
1856*d83cc019SAndroid Build Coastguard Worker 		if (engine == VCS)
1857*d83cc019SAndroid Build Coastguard Worker 			_flags &= ~SWAPVCS;
1858*d83cc019SAndroid Build Coastguard Worker 
1859*d83cc019SAndroid Build Coastguard Worker 		alloc_step_batch(wrk, w, _flags);
1860*d83cc019SAndroid Build Coastguard Worker 	}
1861*d83cc019SAndroid Build Coastguard Worker 
1862*d83cc019SAndroid Build Coastguard Worker 	return 0;
1863*d83cc019SAndroid Build Coastguard Worker }
1864*d83cc019SAndroid Build Coastguard Worker 
elapsed(const struct timespec * start,const struct timespec * end)1865*d83cc019SAndroid Build Coastguard Worker static double elapsed(const struct timespec *start, const struct timespec *end)
1866*d83cc019SAndroid Build Coastguard Worker {
1867*d83cc019SAndroid Build Coastguard Worker 	return (end->tv_sec - start->tv_sec) +
1868*d83cc019SAndroid Build Coastguard Worker 	       (end->tv_nsec - start->tv_nsec) / 1e9;
1869*d83cc019SAndroid Build Coastguard Worker }
1870*d83cc019SAndroid Build Coastguard Worker 
elapsed_us(const struct timespec * start,const struct timespec * end)1871*d83cc019SAndroid Build Coastguard Worker static int elapsed_us(const struct timespec *start, const struct timespec *end)
1872*d83cc019SAndroid Build Coastguard Worker {
1873*d83cc019SAndroid Build Coastguard Worker 	return elapsed(start, end) * 1e6;
1874*d83cc019SAndroid Build Coastguard Worker }
1875*d83cc019SAndroid Build Coastguard Worker 
get_vcs_engine(unsigned int n)1876*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id get_vcs_engine(unsigned int n)
1877*d83cc019SAndroid Build Coastguard Worker {
1878*d83cc019SAndroid Build Coastguard Worker 	const enum intel_engine_id vcs_engines[2] = { VCS1, VCS2 };
1879*d83cc019SAndroid Build Coastguard Worker 
1880*d83cc019SAndroid Build Coastguard Worker 	igt_assert(n < ARRAY_SIZE(vcs_engines));
1881*d83cc019SAndroid Build Coastguard Worker 
1882*d83cc019SAndroid Build Coastguard Worker 	return vcs_engines[n];
1883*d83cc019SAndroid Build Coastguard Worker }
1884*d83cc019SAndroid Build Coastguard Worker 
new_seqno(struct workload * wrk,enum intel_engine_id engine)1885*d83cc019SAndroid Build Coastguard Worker static uint32_t new_seqno(struct workload *wrk, enum intel_engine_id engine)
1886*d83cc019SAndroid Build Coastguard Worker {
1887*d83cc019SAndroid Build Coastguard Worker 	uint32_t seqno;
1888*d83cc019SAndroid Build Coastguard Worker 	int ret;
1889*d83cc019SAndroid Build Coastguard Worker 
1890*d83cc019SAndroid Build Coastguard Worker 	if (wrk->flags & GLOBAL_BALANCE) {
1891*d83cc019SAndroid Build Coastguard Worker 		igt_assert(wrk->global_wrk);
1892*d83cc019SAndroid Build Coastguard Worker 		wrk = wrk->global_wrk;
1893*d83cc019SAndroid Build Coastguard Worker 
1894*d83cc019SAndroid Build Coastguard Worker 		ret = pthread_mutex_lock(&wrk->mutex);
1895*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ret == 0);
1896*d83cc019SAndroid Build Coastguard Worker 	}
1897*d83cc019SAndroid Build Coastguard Worker 
1898*d83cc019SAndroid Build Coastguard Worker 	seqno = ++wrk->seqno[engine];
1899*d83cc019SAndroid Build Coastguard Worker 
1900*d83cc019SAndroid Build Coastguard Worker 	if (wrk->flags & GLOBAL_BALANCE) {
1901*d83cc019SAndroid Build Coastguard Worker 		ret = pthread_mutex_unlock(&wrk->mutex);
1902*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ret == 0);
1903*d83cc019SAndroid Build Coastguard Worker 	}
1904*d83cc019SAndroid Build Coastguard Worker 
1905*d83cc019SAndroid Build Coastguard Worker 	return seqno;
1906*d83cc019SAndroid Build Coastguard Worker }
1907*d83cc019SAndroid Build Coastguard Worker 
1908*d83cc019SAndroid Build Coastguard Worker static uint32_t
current_seqno(struct workload * wrk,enum intel_engine_id engine)1909*d83cc019SAndroid Build Coastguard Worker current_seqno(struct workload *wrk, enum intel_engine_id engine)
1910*d83cc019SAndroid Build Coastguard Worker {
1911*d83cc019SAndroid Build Coastguard Worker 	if (wrk->flags & GLOBAL_BALANCE)
1912*d83cc019SAndroid Build Coastguard Worker 		return wrk->global_wrk->seqno[engine];
1913*d83cc019SAndroid Build Coastguard Worker 	else
1914*d83cc019SAndroid Build Coastguard Worker 		return wrk->seqno[engine];
1915*d83cc019SAndroid Build Coastguard Worker }
1916*d83cc019SAndroid Build Coastguard Worker 
1917*d83cc019SAndroid Build Coastguard Worker static uint32_t
read_status_page(struct workload * wrk,unsigned int idx)1918*d83cc019SAndroid Build Coastguard Worker read_status_page(struct workload *wrk, unsigned int idx)
1919*d83cc019SAndroid Build Coastguard Worker {
1920*d83cc019SAndroid Build Coastguard Worker 	if (wrk->flags & GLOBAL_BALANCE)
1921*d83cc019SAndroid Build Coastguard Worker 		return READ_ONCE(wrk->global_wrk->status_page[idx]);
1922*d83cc019SAndroid Build Coastguard Worker 	else
1923*d83cc019SAndroid Build Coastguard Worker 		return READ_ONCE(wrk->status_page[idx]);
1924*d83cc019SAndroid Build Coastguard Worker }
1925*d83cc019SAndroid Build Coastguard Worker 
1926*d83cc019SAndroid Build Coastguard Worker static uint32_t
current_gpu_seqno(struct workload * wrk,enum intel_engine_id engine)1927*d83cc019SAndroid Build Coastguard Worker current_gpu_seqno(struct workload *wrk, enum intel_engine_id engine)
1928*d83cc019SAndroid Build Coastguard Worker {
1929*d83cc019SAndroid Build Coastguard Worker        return read_status_page(wrk, SEQNO_IDX(engine));
1930*d83cc019SAndroid Build Coastguard Worker }
1931*d83cc019SAndroid Build Coastguard Worker 
1932*d83cc019SAndroid Build Coastguard Worker struct workload_balancer {
1933*d83cc019SAndroid Build Coastguard Worker 	unsigned int id;
1934*d83cc019SAndroid Build Coastguard Worker 	const char *name;
1935*d83cc019SAndroid Build Coastguard Worker 	const char *desc;
1936*d83cc019SAndroid Build Coastguard Worker 	unsigned int flags;
1937*d83cc019SAndroid Build Coastguard Worker 	unsigned int min_gen;
1938*d83cc019SAndroid Build Coastguard Worker 
1939*d83cc019SAndroid Build Coastguard Worker 	int (*init)(const struct workload_balancer *balancer,
1940*d83cc019SAndroid Build Coastguard Worker 		    struct workload *wrk);
1941*d83cc019SAndroid Build Coastguard Worker 	unsigned int (*get_qd)(const struct workload_balancer *balancer,
1942*d83cc019SAndroid Build Coastguard Worker 			       struct workload *wrk,
1943*d83cc019SAndroid Build Coastguard Worker 			       enum intel_engine_id engine);
1944*d83cc019SAndroid Build Coastguard Worker 	enum intel_engine_id (*balance)(const struct workload_balancer *balancer,
1945*d83cc019SAndroid Build Coastguard Worker 					struct workload *wrk, struct w_step *w);
1946*d83cc019SAndroid Build Coastguard Worker };
1947*d83cc019SAndroid Build Coastguard Worker 
1948*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
rr_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)1949*d83cc019SAndroid Build Coastguard Worker rr_balance(const struct workload_balancer *balancer,
1950*d83cc019SAndroid Build Coastguard Worker 	   struct workload *wrk, struct w_step *w)
1951*d83cc019SAndroid Build Coastguard Worker {
1952*d83cc019SAndroid Build Coastguard Worker 	unsigned int engine;
1953*d83cc019SAndroid Build Coastguard Worker 
1954*d83cc019SAndroid Build Coastguard Worker 	engine = get_vcs_engine(wrk->vcs_rr);
1955*d83cc019SAndroid Build Coastguard Worker 	wrk->vcs_rr ^= 1;
1956*d83cc019SAndroid Build Coastguard Worker 
1957*d83cc019SAndroid Build Coastguard Worker 	return engine;
1958*d83cc019SAndroid Build Coastguard Worker }
1959*d83cc019SAndroid Build Coastguard Worker 
1960*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
rand_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)1961*d83cc019SAndroid Build Coastguard Worker rand_balance(const struct workload_balancer *balancer,
1962*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, struct w_step *w)
1963*d83cc019SAndroid Build Coastguard Worker {
1964*d83cc019SAndroid Build Coastguard Worker 	return get_vcs_engine(hars_petruska_f54_1_random(&wrk->prng) & 1);
1965*d83cc019SAndroid Build Coastguard Worker }
1966*d83cc019SAndroid Build Coastguard Worker 
1967*d83cc019SAndroid Build Coastguard Worker static unsigned int
get_qd_depth(const struct workload_balancer * balancer,struct workload * wrk,enum intel_engine_id engine)1968*d83cc019SAndroid Build Coastguard Worker get_qd_depth(const struct workload_balancer *balancer,
1969*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, enum intel_engine_id engine)
1970*d83cc019SAndroid Build Coastguard Worker {
1971*d83cc019SAndroid Build Coastguard Worker 	return current_seqno(wrk, engine) - current_gpu_seqno(wrk, engine);
1972*d83cc019SAndroid Build Coastguard Worker }
1973*d83cc019SAndroid Build Coastguard Worker 
1974*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
__qd_select_engine(struct workload * wrk,const unsigned long * qd,bool random)1975*d83cc019SAndroid Build Coastguard Worker __qd_select_engine(struct workload *wrk, const unsigned long *qd, bool random)
1976*d83cc019SAndroid Build Coastguard Worker {
1977*d83cc019SAndroid Build Coastguard Worker 	unsigned int n;
1978*d83cc019SAndroid Build Coastguard Worker 
1979*d83cc019SAndroid Build Coastguard Worker 	if (qd[VCS1] < qd[VCS2])
1980*d83cc019SAndroid Build Coastguard Worker 		n = 0;
1981*d83cc019SAndroid Build Coastguard Worker 	else if (qd[VCS1] > qd[VCS2])
1982*d83cc019SAndroid Build Coastguard Worker 		n = 1;
1983*d83cc019SAndroid Build Coastguard Worker 	else if (random)
1984*d83cc019SAndroid Build Coastguard Worker 		n = hars_petruska_f54_1_random(&wrk->prng) & 1;
1985*d83cc019SAndroid Build Coastguard Worker 	else
1986*d83cc019SAndroid Build Coastguard Worker 		n = wrk->vcs_rr;
1987*d83cc019SAndroid Build Coastguard Worker 	wrk->vcs_rr = n ^ 1;
1988*d83cc019SAndroid Build Coastguard Worker 
1989*d83cc019SAndroid Build Coastguard Worker 	return get_vcs_engine(n);
1990*d83cc019SAndroid Build Coastguard Worker }
1991*d83cc019SAndroid Build Coastguard Worker 
1992*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
__qd_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w,bool random)1993*d83cc019SAndroid Build Coastguard Worker __qd_balance(const struct workload_balancer *balancer,
1994*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, struct w_step *w, bool random)
1995*d83cc019SAndroid Build Coastguard Worker {
1996*d83cc019SAndroid Build Coastguard Worker 	enum intel_engine_id engine;
1997*d83cc019SAndroid Build Coastguard Worker 	unsigned long qd[NUM_ENGINES];
1998*d83cc019SAndroid Build Coastguard Worker 
1999*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w->engine == VCS);
2000*d83cc019SAndroid Build Coastguard Worker 
2001*d83cc019SAndroid Build Coastguard Worker 	qd[VCS1] = balancer->get_qd(balancer, wrk, VCS1);
2002*d83cc019SAndroid Build Coastguard Worker 	wrk->qd_sum[VCS1] += qd[VCS1];
2003*d83cc019SAndroid Build Coastguard Worker 
2004*d83cc019SAndroid Build Coastguard Worker 	qd[VCS2] = balancer->get_qd(balancer, wrk, VCS2);
2005*d83cc019SAndroid Build Coastguard Worker 	wrk->qd_sum[VCS2] += qd[VCS2];
2006*d83cc019SAndroid Build Coastguard Worker 
2007*d83cc019SAndroid Build Coastguard Worker 	engine = __qd_select_engine(wrk, qd, random);
2008*d83cc019SAndroid Build Coastguard Worker 
2009*d83cc019SAndroid Build Coastguard Worker #ifdef DEBUG
2010*d83cc019SAndroid Build Coastguard Worker 	printf("qd_balance[%u]: 1:%ld 2:%ld rr:%u = %u\t(%u - %u) (%u - %u)\n",
2011*d83cc019SAndroid Build Coastguard Worker 	       wrk->id, qd[VCS1], qd[VCS2], wrk->vcs_rr, engine,
2012*d83cc019SAndroid Build Coastguard Worker 	       current_seqno(wrk, VCS1), current_gpu_seqno(wrk, VCS1),
2013*d83cc019SAndroid Build Coastguard Worker 	       current_seqno(wrk, VCS2), current_gpu_seqno(wrk, VCS2));
2014*d83cc019SAndroid Build Coastguard Worker #endif
2015*d83cc019SAndroid Build Coastguard Worker 	return engine;
2016*d83cc019SAndroid Build Coastguard Worker }
2017*d83cc019SAndroid Build Coastguard Worker 
2018*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
qd_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2019*d83cc019SAndroid Build Coastguard Worker qd_balance(const struct workload_balancer *balancer,
2020*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, struct w_step *w)
2021*d83cc019SAndroid Build Coastguard Worker {
2022*d83cc019SAndroid Build Coastguard Worker 	return __qd_balance(balancer, wrk, w, false);
2023*d83cc019SAndroid Build Coastguard Worker }
2024*d83cc019SAndroid Build Coastguard Worker 
2025*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
qdr_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2026*d83cc019SAndroid Build Coastguard Worker qdr_balance(const struct workload_balancer *balancer,
2027*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, struct w_step *w)
2028*d83cc019SAndroid Build Coastguard Worker {
2029*d83cc019SAndroid Build Coastguard Worker 	return __qd_balance(balancer, wrk, w, true);
2030*d83cc019SAndroid Build Coastguard Worker }
2031*d83cc019SAndroid Build Coastguard Worker 
2032*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
qdavg_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2033*d83cc019SAndroid Build Coastguard Worker qdavg_balance(const struct workload_balancer *balancer,
2034*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, struct w_step *w)
2035*d83cc019SAndroid Build Coastguard Worker {
2036*d83cc019SAndroid Build Coastguard Worker 	unsigned long qd[NUM_ENGINES];
2037*d83cc019SAndroid Build Coastguard Worker 	unsigned int engine;
2038*d83cc019SAndroid Build Coastguard Worker 
2039*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w->engine == VCS);
2040*d83cc019SAndroid Build Coastguard Worker 
2041*d83cc019SAndroid Build Coastguard Worker 	for (engine = VCS1; engine <= VCS2; engine++) {
2042*d83cc019SAndroid Build Coastguard Worker 		qd[engine] = balancer->get_qd(balancer, wrk, engine);
2043*d83cc019SAndroid Build Coastguard Worker 		wrk->qd_sum[engine] += qd[engine];
2044*d83cc019SAndroid Build Coastguard Worker 
2045*d83cc019SAndroid Build Coastguard Worker 		ewma_rt_add(&wrk->rt.avg[engine], qd[engine]);
2046*d83cc019SAndroid Build Coastguard Worker 		qd[engine] = ewma_rt_read(&wrk->rt.avg[engine]);
2047*d83cc019SAndroid Build Coastguard Worker 	}
2048*d83cc019SAndroid Build Coastguard Worker 
2049*d83cc019SAndroid Build Coastguard Worker 	engine = __qd_select_engine(wrk, qd, false);
2050*d83cc019SAndroid Build Coastguard Worker #ifdef DEBUG
2051*d83cc019SAndroid Build Coastguard Worker 	printf("qdavg_balance[%u]: 1:%ld 2:%ld rr:%u = %u\t(%u - %u) (%u - %u)\n",
2052*d83cc019SAndroid Build Coastguard Worker 	       wrk->id, qd[VCS1], qd[VCS2], wrk->vcs_rr, engine,
2053*d83cc019SAndroid Build Coastguard Worker 	       current_seqno(wrk, VCS1), current_gpu_seqno(wrk, VCS1),
2054*d83cc019SAndroid Build Coastguard Worker 	       current_seqno(wrk, VCS2), current_gpu_seqno(wrk, VCS2));
2055*d83cc019SAndroid Build Coastguard Worker #endif
2056*d83cc019SAndroid Build Coastguard Worker 	return engine;
2057*d83cc019SAndroid Build Coastguard Worker }
2058*d83cc019SAndroid Build Coastguard Worker 
2059*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
__rt_select_engine(struct workload * wrk,unsigned long * qd,bool random)2060*d83cc019SAndroid Build Coastguard Worker __rt_select_engine(struct workload *wrk, unsigned long *qd, bool random)
2061*d83cc019SAndroid Build Coastguard Worker {
2062*d83cc019SAndroid Build Coastguard Worker 	qd[VCS1] >>= 10;
2063*d83cc019SAndroid Build Coastguard Worker 	qd[VCS2] >>= 10;
2064*d83cc019SAndroid Build Coastguard Worker 
2065*d83cc019SAndroid Build Coastguard Worker 	return __qd_select_engine(wrk, qd, random);
2066*d83cc019SAndroid Build Coastguard Worker }
2067*d83cc019SAndroid Build Coastguard Worker 
2068*d83cc019SAndroid Build Coastguard Worker struct rt_depth {
2069*d83cc019SAndroid Build Coastguard Worker 	uint32_t seqno;
2070*d83cc019SAndroid Build Coastguard Worker 	uint32_t submitted;
2071*d83cc019SAndroid Build Coastguard Worker 	uint32_t completed;
2072*d83cc019SAndroid Build Coastguard Worker };
2073*d83cc019SAndroid Build Coastguard Worker 
get_rt_depth(struct workload * wrk,unsigned int engine,struct rt_depth * rt)2074*d83cc019SAndroid Build Coastguard Worker static void get_rt_depth(struct workload *wrk,
2075*d83cc019SAndroid Build Coastguard Worker 			 unsigned int engine,
2076*d83cc019SAndroid Build Coastguard Worker 			 struct rt_depth *rt)
2077*d83cc019SAndroid Build Coastguard Worker {
2078*d83cc019SAndroid Build Coastguard Worker 	const unsigned int idx = SEQNO_IDX(engine);
2079*d83cc019SAndroid Build Coastguard Worker 	uint32_t latch;
2080*d83cc019SAndroid Build Coastguard Worker 
2081*d83cc019SAndroid Build Coastguard Worker 	do {
2082*d83cc019SAndroid Build Coastguard Worker 		latch = read_status_page(wrk, idx + 3);
2083*d83cc019SAndroid Build Coastguard Worker 		rt->submitted = read_status_page(wrk, idx + 1);
2084*d83cc019SAndroid Build Coastguard Worker 		rt->completed = read_status_page(wrk, idx + 2);
2085*d83cc019SAndroid Build Coastguard Worker 		rt->seqno = read_status_page(wrk, idx);
2086*d83cc019SAndroid Build Coastguard Worker 	} while (latch != rt->seqno);
2087*d83cc019SAndroid Build Coastguard Worker }
2088*d83cc019SAndroid Build Coastguard Worker 
2089*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
__rt_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w,bool random)2090*d83cc019SAndroid Build Coastguard Worker __rt_balance(const struct workload_balancer *balancer,
2091*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, struct w_step *w, bool random)
2092*d83cc019SAndroid Build Coastguard Worker {
2093*d83cc019SAndroid Build Coastguard Worker 	unsigned long qd[NUM_ENGINES];
2094*d83cc019SAndroid Build Coastguard Worker 	unsigned int engine;
2095*d83cc019SAndroid Build Coastguard Worker 
2096*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w->engine == VCS);
2097*d83cc019SAndroid Build Coastguard Worker 
2098*d83cc019SAndroid Build Coastguard Worker 	/* Estimate the "speed" of the most recent batch
2099*d83cc019SAndroid Build Coastguard Worker 	 *    (finish time - submit time)
2100*d83cc019SAndroid Build Coastguard Worker 	 * and use that as an approximate for the total remaining time for
2101*d83cc019SAndroid Build Coastguard Worker 	 * all batches on that engine, plus the time we expect this batch to
2102*d83cc019SAndroid Build Coastguard Worker 	 * take. We try to keep the total balanced between the engines.
2103*d83cc019SAndroid Build Coastguard Worker 	 */
2104*d83cc019SAndroid Build Coastguard Worker 	for (engine = VCS1; engine <= VCS2; engine++) {
2105*d83cc019SAndroid Build Coastguard Worker 		struct rt_depth rt;
2106*d83cc019SAndroid Build Coastguard Worker 
2107*d83cc019SAndroid Build Coastguard Worker 		get_rt_depth(wrk, engine, &rt);
2108*d83cc019SAndroid Build Coastguard Worker 		qd[engine] = current_seqno(wrk, engine) - rt.seqno;
2109*d83cc019SAndroid Build Coastguard Worker 		wrk->qd_sum[engine] += qd[engine];
2110*d83cc019SAndroid Build Coastguard Worker 		qd[engine] = (qd[engine] + 1) * (rt.completed - rt.submitted);
2111*d83cc019SAndroid Build Coastguard Worker #ifdef DEBUG
2112*d83cc019SAndroid Build Coastguard Worker 		printf("rt[0] = %d (%d - %d) x %d (%d - %d) = %ld\n",
2113*d83cc019SAndroid Build Coastguard Worker 		       current_seqno(wrk, engine) - rt.seqno,
2114*d83cc019SAndroid Build Coastguard Worker 		       current_seqno(wrk, engine), rt.seqno,
2115*d83cc019SAndroid Build Coastguard Worker 		       rt.completed - rt.submitted,
2116*d83cc019SAndroid Build Coastguard Worker 		       rt.completed, rt.submitted,
2117*d83cc019SAndroid Build Coastguard Worker 		       qd[engine]);
2118*d83cc019SAndroid Build Coastguard Worker #endif
2119*d83cc019SAndroid Build Coastguard Worker 	}
2120*d83cc019SAndroid Build Coastguard Worker 
2121*d83cc019SAndroid Build Coastguard Worker 	return __rt_select_engine(wrk, qd, random);
2122*d83cc019SAndroid Build Coastguard Worker }
2123*d83cc019SAndroid Build Coastguard Worker 
2124*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
rt_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2125*d83cc019SAndroid Build Coastguard Worker rt_balance(const struct workload_balancer *balancer,
2126*d83cc019SAndroid Build Coastguard Worker 	   struct workload *wrk, struct w_step *w)
2127*d83cc019SAndroid Build Coastguard Worker {
2128*d83cc019SAndroid Build Coastguard Worker 
2129*d83cc019SAndroid Build Coastguard Worker 	return __rt_balance(balancer, wrk, w, false);
2130*d83cc019SAndroid Build Coastguard Worker }
2131*d83cc019SAndroid Build Coastguard Worker 
2132*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
rtr_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2133*d83cc019SAndroid Build Coastguard Worker rtr_balance(const struct workload_balancer *balancer,
2134*d83cc019SAndroid Build Coastguard Worker 	   struct workload *wrk, struct w_step *w)
2135*d83cc019SAndroid Build Coastguard Worker {
2136*d83cc019SAndroid Build Coastguard Worker 	return __rt_balance(balancer, wrk, w, true);
2137*d83cc019SAndroid Build Coastguard Worker }
2138*d83cc019SAndroid Build Coastguard Worker 
2139*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
rtavg_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2140*d83cc019SAndroid Build Coastguard Worker rtavg_balance(const struct workload_balancer *balancer,
2141*d83cc019SAndroid Build Coastguard Worker 	   struct workload *wrk, struct w_step *w)
2142*d83cc019SAndroid Build Coastguard Worker {
2143*d83cc019SAndroid Build Coastguard Worker 	unsigned long qd[NUM_ENGINES];
2144*d83cc019SAndroid Build Coastguard Worker 	unsigned int engine;
2145*d83cc019SAndroid Build Coastguard Worker 
2146*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w->engine == VCS);
2147*d83cc019SAndroid Build Coastguard Worker 
2148*d83cc019SAndroid Build Coastguard Worker 	/* Estimate the average "speed" of the most recent batches
2149*d83cc019SAndroid Build Coastguard Worker 	 *    (finish time - submit time)
2150*d83cc019SAndroid Build Coastguard Worker 	 * and use that as an approximate for the total remaining time for
2151*d83cc019SAndroid Build Coastguard Worker 	 * all batches on that engine plus the time we expect to execute in.
2152*d83cc019SAndroid Build Coastguard Worker 	 * We try to keep the total remaining balanced between the engines.
2153*d83cc019SAndroid Build Coastguard Worker 	 */
2154*d83cc019SAndroid Build Coastguard Worker 	for (engine = VCS1; engine <= VCS2; engine++) {
2155*d83cc019SAndroid Build Coastguard Worker 		struct rt_depth rt;
2156*d83cc019SAndroid Build Coastguard Worker 
2157*d83cc019SAndroid Build Coastguard Worker 		get_rt_depth(wrk, engine, &rt);
2158*d83cc019SAndroid Build Coastguard Worker 		if (rt.seqno != wrk->rt.last[engine]) {
2159*d83cc019SAndroid Build Coastguard Worker 			igt_assert((long)(rt.completed - rt.submitted) > 0);
2160*d83cc019SAndroid Build Coastguard Worker 			ewma_rt_add(&wrk->rt.avg[engine],
2161*d83cc019SAndroid Build Coastguard Worker 				    rt.completed - rt.submitted);
2162*d83cc019SAndroid Build Coastguard Worker 			wrk->rt.last[engine] = rt.seqno;
2163*d83cc019SAndroid Build Coastguard Worker 		}
2164*d83cc019SAndroid Build Coastguard Worker 		qd[engine] = current_seqno(wrk, engine) - rt.seqno;
2165*d83cc019SAndroid Build Coastguard Worker 		wrk->qd_sum[engine] += qd[engine];
2166*d83cc019SAndroid Build Coastguard Worker 		qd[engine] =
2167*d83cc019SAndroid Build Coastguard Worker 			(qd[engine] + 1) * ewma_rt_read(&wrk->rt.avg[engine]);
2168*d83cc019SAndroid Build Coastguard Worker 
2169*d83cc019SAndroid Build Coastguard Worker #ifdef DEBUG
2170*d83cc019SAndroid Build Coastguard Worker 		printf("rtavg[%d] = %d (%d - %d) x %ld (%d) = %ld\n",
2171*d83cc019SAndroid Build Coastguard Worker 		       engine,
2172*d83cc019SAndroid Build Coastguard Worker 		       current_seqno(wrk, engine) - rt.seqno,
2173*d83cc019SAndroid Build Coastguard Worker 		       current_seqno(wrk, engine), rt.seqno,
2174*d83cc019SAndroid Build Coastguard Worker 		       ewma_rt_read(&wrk->rt.avg[engine]),
2175*d83cc019SAndroid Build Coastguard Worker 		       rt.completed - rt.submitted,
2176*d83cc019SAndroid Build Coastguard Worker 		       qd[engine]);
2177*d83cc019SAndroid Build Coastguard Worker #endif
2178*d83cc019SAndroid Build Coastguard Worker 	}
2179*d83cc019SAndroid Build Coastguard Worker 
2180*d83cc019SAndroid Build Coastguard Worker 	return __rt_select_engine(wrk, qd, false);
2181*d83cc019SAndroid Build Coastguard Worker }
2182*d83cc019SAndroid Build Coastguard Worker 
2183*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
context_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2184*d83cc019SAndroid Build Coastguard Worker context_balance(const struct workload_balancer *balancer,
2185*d83cc019SAndroid Build Coastguard Worker 		struct workload *wrk, struct w_step *w)
2186*d83cc019SAndroid Build Coastguard Worker {
2187*d83cc019SAndroid Build Coastguard Worker 	return get_vcs_engine(__get_ctx(wrk, w)->static_vcs);
2188*d83cc019SAndroid Build Coastguard Worker }
2189*d83cc019SAndroid Build Coastguard Worker 
2190*d83cc019SAndroid Build Coastguard Worker static unsigned int
get_engine_busy(const struct workload_balancer * balancer,struct workload * wrk,enum intel_engine_id engine)2191*d83cc019SAndroid Build Coastguard Worker get_engine_busy(const struct workload_balancer *balancer,
2192*d83cc019SAndroid Build Coastguard Worker 		struct workload *wrk, enum intel_engine_id engine)
2193*d83cc019SAndroid Build Coastguard Worker {
2194*d83cc019SAndroid Build Coastguard Worker 	struct busy_balancer *bb = &wrk->busy_balancer;
2195*d83cc019SAndroid Build Coastguard Worker 
2196*d83cc019SAndroid Build Coastguard Worker 	if (engine == VCS2 && (wrk->flags & VCS2REMAP))
2197*d83cc019SAndroid Build Coastguard Worker 		engine = BCS;
2198*d83cc019SAndroid Build Coastguard Worker 
2199*d83cc019SAndroid Build Coastguard Worker 	return bb->busy[bb->engine_map[engine]];
2200*d83cc019SAndroid Build Coastguard Worker }
2201*d83cc019SAndroid Build Coastguard Worker 
2202*d83cc019SAndroid Build Coastguard Worker static void
get_pmu_stats(const struct workload_balancer * b,struct workload * wrk)2203*d83cc019SAndroid Build Coastguard Worker get_pmu_stats(const struct workload_balancer *b, struct workload *wrk)
2204*d83cc019SAndroid Build Coastguard Worker {
2205*d83cc019SAndroid Build Coastguard Worker 	struct busy_balancer *bb = &wrk->busy_balancer;
2206*d83cc019SAndroid Build Coastguard Worker 	uint64_t val[7];
2207*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
2208*d83cc019SAndroid Build Coastguard Worker 
2209*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(read(bb->fd, val, sizeof(val)),
2210*d83cc019SAndroid Build Coastguard Worker 		      (2 + bb->num_engines) * sizeof(uint64_t));
2211*d83cc019SAndroid Build Coastguard Worker 
2212*d83cc019SAndroid Build Coastguard Worker 	if (!bb->first) {
2213*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < bb->num_engines; i++) {
2214*d83cc019SAndroid Build Coastguard Worker 			double d;
2215*d83cc019SAndroid Build Coastguard Worker 
2216*d83cc019SAndroid Build Coastguard Worker 			d = (val[2 + i] - bb->prev[i]) * 100;
2217*d83cc019SAndroid Build Coastguard Worker 			d /= val[1] - bb->t_prev;
2218*d83cc019SAndroid Build Coastguard Worker 			bb->busy[i] = d;
2219*d83cc019SAndroid Build Coastguard Worker 		}
2220*d83cc019SAndroid Build Coastguard Worker 	}
2221*d83cc019SAndroid Build Coastguard Worker 
2222*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < bb->num_engines; i++)
2223*d83cc019SAndroid Build Coastguard Worker 		bb->prev[i] = val[2 + i];
2224*d83cc019SAndroid Build Coastguard Worker 
2225*d83cc019SAndroid Build Coastguard Worker 	bb->t_prev = val[1];
2226*d83cc019SAndroid Build Coastguard Worker 	bb->first = false;
2227*d83cc019SAndroid Build Coastguard Worker }
2228*d83cc019SAndroid Build Coastguard Worker 
2229*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
busy_avg_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2230*d83cc019SAndroid Build Coastguard Worker busy_avg_balance(const struct workload_balancer *balancer,
2231*d83cc019SAndroid Build Coastguard Worker 		 struct workload *wrk, struct w_step *w)
2232*d83cc019SAndroid Build Coastguard Worker {
2233*d83cc019SAndroid Build Coastguard Worker 	get_pmu_stats(balancer, wrk);
2234*d83cc019SAndroid Build Coastguard Worker 
2235*d83cc019SAndroid Build Coastguard Worker 	return qdavg_balance(balancer, wrk, w);
2236*d83cc019SAndroid Build Coastguard Worker }
2237*d83cc019SAndroid Build Coastguard Worker 
2238*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
busy_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2239*d83cc019SAndroid Build Coastguard Worker busy_balance(const struct workload_balancer *balancer,
2240*d83cc019SAndroid Build Coastguard Worker 	     struct workload *wrk, struct w_step *w)
2241*d83cc019SAndroid Build Coastguard Worker {
2242*d83cc019SAndroid Build Coastguard Worker 	get_pmu_stats(balancer, wrk);
2243*d83cc019SAndroid Build Coastguard Worker 
2244*d83cc019SAndroid Build Coastguard Worker 	return qd_balance(balancer, wrk, w);
2245*d83cc019SAndroid Build Coastguard Worker }
2246*d83cc019SAndroid Build Coastguard Worker 
2247*d83cc019SAndroid Build Coastguard Worker static int
busy_init(const struct workload_balancer * balancer,struct workload * wrk)2248*d83cc019SAndroid Build Coastguard Worker busy_init(const struct workload_balancer *balancer, struct workload *wrk)
2249*d83cc019SAndroid Build Coastguard Worker {
2250*d83cc019SAndroid Build Coastguard Worker 	struct busy_balancer *bb = &wrk->busy_balancer;
2251*d83cc019SAndroid Build Coastguard Worker 	struct engine_desc {
2252*d83cc019SAndroid Build Coastguard Worker 		unsigned class, inst;
2253*d83cc019SAndroid Build Coastguard Worker 		enum intel_engine_id id;
2254*d83cc019SAndroid Build Coastguard Worker 	} *d, engines[] = {
2255*d83cc019SAndroid Build Coastguard Worker 		{ I915_ENGINE_CLASS_RENDER, 0, RCS },
2256*d83cc019SAndroid Build Coastguard Worker 		{ I915_ENGINE_CLASS_COPY, 0, BCS },
2257*d83cc019SAndroid Build Coastguard Worker 		{ I915_ENGINE_CLASS_VIDEO, 0, VCS1 },
2258*d83cc019SAndroid Build Coastguard Worker 		{ I915_ENGINE_CLASS_VIDEO, 1, VCS2 },
2259*d83cc019SAndroid Build Coastguard Worker 		{ I915_ENGINE_CLASS_VIDEO_ENHANCE, 0, VECS },
2260*d83cc019SAndroid Build Coastguard Worker 		{ 0, 0, VCS }
2261*d83cc019SAndroid Build Coastguard Worker 	};
2262*d83cc019SAndroid Build Coastguard Worker 
2263*d83cc019SAndroid Build Coastguard Worker 	bb->num_engines = 0;
2264*d83cc019SAndroid Build Coastguard Worker 	bb->first = true;
2265*d83cc019SAndroid Build Coastguard Worker 	bb->fd = -1;
2266*d83cc019SAndroid Build Coastguard Worker 
2267*d83cc019SAndroid Build Coastguard Worker 	for (d = &engines[0]; d->id != VCS; d++) {
2268*d83cc019SAndroid Build Coastguard Worker 		int pfd;
2269*d83cc019SAndroid Build Coastguard Worker 
2270*d83cc019SAndroid Build Coastguard Worker 		pfd = perf_i915_open_group(I915_PMU_ENGINE_BUSY(d->class,
2271*d83cc019SAndroid Build Coastguard Worker 							        d->inst),
2272*d83cc019SAndroid Build Coastguard Worker 					   bb->fd);
2273*d83cc019SAndroid Build Coastguard Worker 		if (pfd < 0) {
2274*d83cc019SAndroid Build Coastguard Worker 			if (d->id != VCS2)
2275*d83cc019SAndroid Build Coastguard Worker 				return -(10 + bb->num_engines);
2276*d83cc019SAndroid Build Coastguard Worker 			else
2277*d83cc019SAndroid Build Coastguard Worker 				continue;
2278*d83cc019SAndroid Build Coastguard Worker 		}
2279*d83cc019SAndroid Build Coastguard Worker 
2280*d83cc019SAndroid Build Coastguard Worker 		if (bb->num_engines == 0)
2281*d83cc019SAndroid Build Coastguard Worker 			bb->fd = pfd;
2282*d83cc019SAndroid Build Coastguard Worker 
2283*d83cc019SAndroid Build Coastguard Worker 		bb->engine_map[d->id] = bb->num_engines++;
2284*d83cc019SAndroid Build Coastguard Worker 	}
2285*d83cc019SAndroid Build Coastguard Worker 
2286*d83cc019SAndroid Build Coastguard Worker 	if (bb->num_engines < 5 && !(wrk->flags & VCS2REMAP))
2287*d83cc019SAndroid Build Coastguard Worker 		return -1;
2288*d83cc019SAndroid Build Coastguard Worker 
2289*d83cc019SAndroid Build Coastguard Worker 	return 0;
2290*d83cc019SAndroid Build Coastguard Worker }
2291*d83cc019SAndroid Build Coastguard Worker 
2292*d83cc019SAndroid Build Coastguard Worker static const struct workload_balancer all_balancers[] = {
2293*d83cc019SAndroid Build Coastguard Worker 	{
2294*d83cc019SAndroid Build Coastguard Worker 		.id = 0,
2295*d83cc019SAndroid Build Coastguard Worker 		.name = "rr",
2296*d83cc019SAndroid Build Coastguard Worker 		.desc = "Simple round-robin.",
2297*d83cc019SAndroid Build Coastguard Worker 		.balance = rr_balance,
2298*d83cc019SAndroid Build Coastguard Worker 	},
2299*d83cc019SAndroid Build Coastguard Worker 	{
2300*d83cc019SAndroid Build Coastguard Worker 		.id = 6,
2301*d83cc019SAndroid Build Coastguard Worker 		.name = "rand",
2302*d83cc019SAndroid Build Coastguard Worker 		.desc = "Random selection.",
2303*d83cc019SAndroid Build Coastguard Worker 		.balance = rand_balance,
2304*d83cc019SAndroid Build Coastguard Worker 	},
2305*d83cc019SAndroid Build Coastguard Worker 	{
2306*d83cc019SAndroid Build Coastguard Worker 		.id = 1,
2307*d83cc019SAndroid Build Coastguard Worker 		.name = "qd",
2308*d83cc019SAndroid Build Coastguard Worker 		.desc = "Queue depth estimation with round-robin on equal depth.",
2309*d83cc019SAndroid Build Coastguard Worker 		.flags = SEQNO,
2310*d83cc019SAndroid Build Coastguard Worker 		.min_gen = 8,
2311*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_qd_depth,
2312*d83cc019SAndroid Build Coastguard Worker 		.balance = qd_balance,
2313*d83cc019SAndroid Build Coastguard Worker 	},
2314*d83cc019SAndroid Build Coastguard Worker 	{
2315*d83cc019SAndroid Build Coastguard Worker 		.id = 5,
2316*d83cc019SAndroid Build Coastguard Worker 		.name = "qdr",
2317*d83cc019SAndroid Build Coastguard Worker 		.desc = "Queue depth estimation with random selection on equal depth.",
2318*d83cc019SAndroid Build Coastguard Worker 		.flags = SEQNO,
2319*d83cc019SAndroid Build Coastguard Worker 		.min_gen = 8,
2320*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_qd_depth,
2321*d83cc019SAndroid Build Coastguard Worker 		.balance = qdr_balance,
2322*d83cc019SAndroid Build Coastguard Worker 	},
2323*d83cc019SAndroid Build Coastguard Worker 	{
2324*d83cc019SAndroid Build Coastguard Worker 		.id = 7,
2325*d83cc019SAndroid Build Coastguard Worker 		.name = "qdavg",
2326*d83cc019SAndroid Build Coastguard Worker 		.desc = "Like qd, but using an average queue depth estimator.",
2327*d83cc019SAndroid Build Coastguard Worker 		.flags = SEQNO,
2328*d83cc019SAndroid Build Coastguard Worker 		.min_gen = 8,
2329*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_qd_depth,
2330*d83cc019SAndroid Build Coastguard Worker 		.balance = qdavg_balance,
2331*d83cc019SAndroid Build Coastguard Worker 	},
2332*d83cc019SAndroid Build Coastguard Worker 	{
2333*d83cc019SAndroid Build Coastguard Worker 		.id = 2,
2334*d83cc019SAndroid Build Coastguard Worker 		.name = "rt",
2335*d83cc019SAndroid Build Coastguard Worker 		.desc = "Queue depth plus last runtime estimation.",
2336*d83cc019SAndroid Build Coastguard Worker 		.flags = SEQNO | RT,
2337*d83cc019SAndroid Build Coastguard Worker 		.min_gen = 8,
2338*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_qd_depth,
2339*d83cc019SAndroid Build Coastguard Worker 		.balance = rt_balance,
2340*d83cc019SAndroid Build Coastguard Worker 	},
2341*d83cc019SAndroid Build Coastguard Worker 	{
2342*d83cc019SAndroid Build Coastguard Worker 		.id = 3,
2343*d83cc019SAndroid Build Coastguard Worker 		.name = "rtr",
2344*d83cc019SAndroid Build Coastguard Worker 		.desc = "Like rt but with random engine selection on equal depth.",
2345*d83cc019SAndroid Build Coastguard Worker 		.flags = SEQNO | RT,
2346*d83cc019SAndroid Build Coastguard Worker 		.min_gen = 8,
2347*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_qd_depth,
2348*d83cc019SAndroid Build Coastguard Worker 		.balance = rtr_balance,
2349*d83cc019SAndroid Build Coastguard Worker 	},
2350*d83cc019SAndroid Build Coastguard Worker 	{
2351*d83cc019SAndroid Build Coastguard Worker 		.id = 4,
2352*d83cc019SAndroid Build Coastguard Worker 		.name = "rtavg",
2353*d83cc019SAndroid Build Coastguard Worker 		.desc = "Improved version rt tracking average execution speed per engine.",
2354*d83cc019SAndroid Build Coastguard Worker 		.flags = SEQNO | RT,
2355*d83cc019SAndroid Build Coastguard Worker 		.min_gen = 8,
2356*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_qd_depth,
2357*d83cc019SAndroid Build Coastguard Worker 		.balance = rtavg_balance,
2358*d83cc019SAndroid Build Coastguard Worker 	},
2359*d83cc019SAndroid Build Coastguard Worker 	{
2360*d83cc019SAndroid Build Coastguard Worker 		.id = 8,
2361*d83cc019SAndroid Build Coastguard Worker 		.name = "context",
2362*d83cc019SAndroid Build Coastguard Worker 		.desc = "Static round-robin VCS assignment at context creation.",
2363*d83cc019SAndroid Build Coastguard Worker 		.balance = context_balance,
2364*d83cc019SAndroid Build Coastguard Worker 	},
2365*d83cc019SAndroid Build Coastguard Worker 	{
2366*d83cc019SAndroid Build Coastguard Worker 		.id = 9,
2367*d83cc019SAndroid Build Coastguard Worker 		.name = "busy",
2368*d83cc019SAndroid Build Coastguard Worker 		.desc = "Engine busyness based balancing.",
2369*d83cc019SAndroid Build Coastguard Worker 		.init = busy_init,
2370*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_engine_busy,
2371*d83cc019SAndroid Build Coastguard Worker 		.balance = busy_balance,
2372*d83cc019SAndroid Build Coastguard Worker 	},
2373*d83cc019SAndroid Build Coastguard Worker 	{
2374*d83cc019SAndroid Build Coastguard Worker 		.id = 10,
2375*d83cc019SAndroid Build Coastguard Worker 		.name = "busy-avg",
2376*d83cc019SAndroid Build Coastguard Worker 		.desc = "Average engine busyness based balancing.",
2377*d83cc019SAndroid Build Coastguard Worker 		.init = busy_init,
2378*d83cc019SAndroid Build Coastguard Worker 		.get_qd = get_engine_busy,
2379*d83cc019SAndroid Build Coastguard Worker 		.balance = busy_avg_balance,
2380*d83cc019SAndroid Build Coastguard Worker 	},
2381*d83cc019SAndroid Build Coastguard Worker 	{
2382*d83cc019SAndroid Build Coastguard Worker 		.id = 11,
2383*d83cc019SAndroid Build Coastguard Worker 		.name = "i915",
2384*d83cc019SAndroid Build Coastguard Worker 		.desc = "i915 balancing.",
2385*d83cc019SAndroid Build Coastguard Worker 		.flags = I915,
2386*d83cc019SAndroid Build Coastguard Worker 	},
2387*d83cc019SAndroid Build Coastguard Worker };
2388*d83cc019SAndroid Build Coastguard Worker 
2389*d83cc019SAndroid Build Coastguard Worker static unsigned int
global_get_qd(const struct workload_balancer * balancer,struct workload * wrk,enum intel_engine_id engine)2390*d83cc019SAndroid Build Coastguard Worker global_get_qd(const struct workload_balancer *balancer,
2391*d83cc019SAndroid Build Coastguard Worker 	      struct workload *wrk, enum intel_engine_id engine)
2392*d83cc019SAndroid Build Coastguard Worker {
2393*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk->global_wrk);
2394*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk->global_balancer);
2395*d83cc019SAndroid Build Coastguard Worker 
2396*d83cc019SAndroid Build Coastguard Worker 	return wrk->global_balancer->get_qd(wrk->global_balancer,
2397*d83cc019SAndroid Build Coastguard Worker 					    wrk->global_wrk, engine);
2398*d83cc019SAndroid Build Coastguard Worker }
2399*d83cc019SAndroid Build Coastguard Worker 
2400*d83cc019SAndroid Build Coastguard Worker static enum intel_engine_id
global_balance(const struct workload_balancer * balancer,struct workload * wrk,struct w_step * w)2401*d83cc019SAndroid Build Coastguard Worker global_balance(const struct workload_balancer *balancer,
2402*d83cc019SAndroid Build Coastguard Worker 	       struct workload *wrk, struct w_step *w)
2403*d83cc019SAndroid Build Coastguard Worker {
2404*d83cc019SAndroid Build Coastguard Worker 	enum intel_engine_id engine;
2405*d83cc019SAndroid Build Coastguard Worker 	int ret;
2406*d83cc019SAndroid Build Coastguard Worker 
2407*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk->global_wrk);
2408*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk->global_balancer);
2409*d83cc019SAndroid Build Coastguard Worker 
2410*d83cc019SAndroid Build Coastguard Worker 	wrk = wrk->global_wrk;
2411*d83cc019SAndroid Build Coastguard Worker 
2412*d83cc019SAndroid Build Coastguard Worker 	ret = pthread_mutex_lock(&wrk->mutex);
2413*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret == 0);
2414*d83cc019SAndroid Build Coastguard Worker 
2415*d83cc019SAndroid Build Coastguard Worker 	engine = wrk->global_balancer->balance(wrk->global_balancer, wrk, w);
2416*d83cc019SAndroid Build Coastguard Worker 
2417*d83cc019SAndroid Build Coastguard Worker 	ret = pthread_mutex_unlock(&wrk->mutex);
2418*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ret == 0);
2419*d83cc019SAndroid Build Coastguard Worker 
2420*d83cc019SAndroid Build Coastguard Worker 	return engine;
2421*d83cc019SAndroid Build Coastguard Worker }
2422*d83cc019SAndroid Build Coastguard Worker 
2423*d83cc019SAndroid Build Coastguard Worker static const struct workload_balancer global_balancer = {
2424*d83cc019SAndroid Build Coastguard Worker 		.id = ~0,
2425*d83cc019SAndroid Build Coastguard Worker 		.name = "global",
2426*d83cc019SAndroid Build Coastguard Worker 		.desc = "Global balancer",
2427*d83cc019SAndroid Build Coastguard Worker 		.get_qd = global_get_qd,
2428*d83cc019SAndroid Build Coastguard Worker 		.balance = global_balance,
2429*d83cc019SAndroid Build Coastguard Worker 	};
2430*d83cc019SAndroid Build Coastguard Worker 
2431*d83cc019SAndroid Build Coastguard Worker static void
update_bb_seqno(struct w_step * w,enum intel_engine_id engine,uint32_t seqno)2432*d83cc019SAndroid Build Coastguard Worker update_bb_seqno(struct w_step *w, enum intel_engine_id engine, uint32_t seqno)
2433*d83cc019SAndroid Build Coastguard Worker {
2434*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, w->bb_handle,
2435*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
2436*d83cc019SAndroid Build Coastguard Worker 
2437*d83cc019SAndroid Build Coastguard Worker 	w->reloc[0].delta = SEQNO_OFFSET(engine);
2438*d83cc019SAndroid Build Coastguard Worker 
2439*d83cc019SAndroid Build Coastguard Worker 	*w->seqno_value = seqno;
2440*d83cc019SAndroid Build Coastguard Worker 	*w->seqno_address = w->reloc[0].presumed_offset + w->reloc[0].delta;
2441*d83cc019SAndroid Build Coastguard Worker 
2442*d83cc019SAndroid Build Coastguard Worker 	/* If not using NO_RELOC, force the relocations */
2443*d83cc019SAndroid Build Coastguard Worker 	if (!(w->eb.flags & I915_EXEC_NO_RELOC))
2444*d83cc019SAndroid Build Coastguard Worker 		w->reloc[0].presumed_offset = -1;
2445*d83cc019SAndroid Build Coastguard Worker }
2446*d83cc019SAndroid Build Coastguard Worker 
2447*d83cc019SAndroid Build Coastguard Worker static void
update_bb_rt(struct w_step * w,enum intel_engine_id engine,uint32_t seqno)2448*d83cc019SAndroid Build Coastguard Worker update_bb_rt(struct w_step *w, enum intel_engine_id engine, uint32_t seqno)
2449*d83cc019SAndroid Build Coastguard Worker {
2450*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, w->bb_handle,
2451*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
2452*d83cc019SAndroid Build Coastguard Worker 
2453*d83cc019SAndroid Build Coastguard Worker 	w->reloc[1].delta = SEQNO_OFFSET(engine) + sizeof(uint32_t);
2454*d83cc019SAndroid Build Coastguard Worker 	w->reloc[2].delta = SEQNO_OFFSET(engine) + 2 * sizeof(uint32_t);
2455*d83cc019SAndroid Build Coastguard Worker 	w->reloc[3].delta = SEQNO_OFFSET(engine) + 3 * sizeof(uint32_t);
2456*d83cc019SAndroid Build Coastguard Worker 
2457*d83cc019SAndroid Build Coastguard Worker 	*w->latch_value = seqno;
2458*d83cc019SAndroid Build Coastguard Worker 	*w->latch_address = w->reloc[3].presumed_offset + w->reloc[3].delta;
2459*d83cc019SAndroid Build Coastguard Worker 
2460*d83cc019SAndroid Build Coastguard Worker 	*w->rt0_value = *REG(RCS_TIMESTAMP);
2461*d83cc019SAndroid Build Coastguard Worker 	*w->rt0_address = w->reloc[1].presumed_offset + w->reloc[1].delta;
2462*d83cc019SAndroid Build Coastguard Worker 	*w->rt1_address = w->reloc[2].presumed_offset + w->reloc[2].delta;
2463*d83cc019SAndroid Build Coastguard Worker 
2464*d83cc019SAndroid Build Coastguard Worker 	/* If not using NO_RELOC, force the relocations */
2465*d83cc019SAndroid Build Coastguard Worker 	if (!(w->eb.flags & I915_EXEC_NO_RELOC)) {
2466*d83cc019SAndroid Build Coastguard Worker 		w->reloc[1].presumed_offset = -1;
2467*d83cc019SAndroid Build Coastguard Worker 		w->reloc[2].presumed_offset = -1;
2468*d83cc019SAndroid Build Coastguard Worker 		w->reloc[3].presumed_offset = -1;
2469*d83cc019SAndroid Build Coastguard Worker 	}
2470*d83cc019SAndroid Build Coastguard Worker }
2471*d83cc019SAndroid Build Coastguard Worker 
2472*d83cc019SAndroid Build Coastguard Worker static void
update_bb_start(struct w_step * w)2473*d83cc019SAndroid Build Coastguard Worker update_bb_start(struct w_step *w)
2474*d83cc019SAndroid Build Coastguard Worker {
2475*d83cc019SAndroid Build Coastguard Worker 	if (!w->unbound_duration)
2476*d83cc019SAndroid Build Coastguard Worker 		return;
2477*d83cc019SAndroid Build Coastguard Worker 
2478*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, w->bb_handle,
2479*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
2480*d83cc019SAndroid Build Coastguard Worker 
2481*d83cc019SAndroid Build Coastguard Worker 	*w->recursive_bb_start = MI_BATCH_BUFFER_START | (1 << 8) | 1;
2482*d83cc019SAndroid Build Coastguard Worker }
2483*d83cc019SAndroid Build Coastguard Worker 
w_sync_to(struct workload * wrk,struct w_step * w,int target)2484*d83cc019SAndroid Build Coastguard Worker static void w_sync_to(struct workload *wrk, struct w_step *w, int target)
2485*d83cc019SAndroid Build Coastguard Worker {
2486*d83cc019SAndroid Build Coastguard Worker 	if (target < 0)
2487*d83cc019SAndroid Build Coastguard Worker 		target = wrk->nr_steps + target;
2488*d83cc019SAndroid Build Coastguard Worker 
2489*d83cc019SAndroid Build Coastguard Worker 	igt_assert(target < wrk->nr_steps);
2490*d83cc019SAndroid Build Coastguard Worker 
2491*d83cc019SAndroid Build Coastguard Worker 	while (wrk->steps[target].type != BATCH) {
2492*d83cc019SAndroid Build Coastguard Worker 		if (--target < 0)
2493*d83cc019SAndroid Build Coastguard Worker 			target = wrk->nr_steps + target;
2494*d83cc019SAndroid Build Coastguard Worker 	}
2495*d83cc019SAndroid Build Coastguard Worker 
2496*d83cc019SAndroid Build Coastguard Worker 	igt_assert(target < wrk->nr_steps);
2497*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk->steps[target].type == BATCH);
2498*d83cc019SAndroid Build Coastguard Worker 
2499*d83cc019SAndroid Build Coastguard Worker 	gem_sync(fd, wrk->steps[target].obj[0].handle);
2500*d83cc019SAndroid Build Coastguard Worker }
2501*d83cc019SAndroid Build Coastguard Worker 
get_status_cs(struct workload * wrk)2502*d83cc019SAndroid Build Coastguard Worker static uint32_t *get_status_cs(struct workload *wrk)
2503*d83cc019SAndroid Build Coastguard Worker {
2504*d83cc019SAndroid Build Coastguard Worker 	return wrk->status_cs;
2505*d83cc019SAndroid Build Coastguard Worker }
2506*d83cc019SAndroid Build Coastguard Worker 
2507*d83cc019SAndroid Build Coastguard Worker #define INIT_CLOCKS 0x1
2508*d83cc019SAndroid Build Coastguard Worker #define INIT_ALL (INIT_CLOCKS)
init_status_page(struct workload * wrk,unsigned int flags)2509*d83cc019SAndroid Build Coastguard Worker static void init_status_page(struct workload *wrk, unsigned int flags)
2510*d83cc019SAndroid Build Coastguard Worker {
2511*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_relocation_entry reloc[4] = {};
2512*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 *status_object =
2513*d83cc019SAndroid Build Coastguard Worker 						get_status_objects(wrk);
2514*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 eb = {
2515*d83cc019SAndroid Build Coastguard Worker 		.buffer_count = ARRAY_SIZE(wrk->status_object),
2516*d83cc019SAndroid Build Coastguard Worker 		.buffers_ptr = to_user_pointer(status_object)
2517*d83cc019SAndroid Build Coastguard Worker 	};
2518*d83cc019SAndroid Build Coastguard Worker 	uint32_t *base = get_status_cs(wrk);
2519*d83cc019SAndroid Build Coastguard Worker 
2520*d83cc019SAndroid Build Coastguard Worker 	/* Want to make sure that the balancer has a reasonable view of
2521*d83cc019SAndroid Build Coastguard Worker 	 * the background busyness of each engine. To do that we occasionally
2522*d83cc019SAndroid Build Coastguard Worker 	 * send a dummy batch down the pipeline.
2523*d83cc019SAndroid Build Coastguard Worker 	 */
2524*d83cc019SAndroid Build Coastguard Worker 
2525*d83cc019SAndroid Build Coastguard Worker 	if (!base)
2526*d83cc019SAndroid Build Coastguard Worker 		return;
2527*d83cc019SAndroid Build Coastguard Worker 
2528*d83cc019SAndroid Build Coastguard Worker 	gem_set_domain(fd, status_object[1].handle,
2529*d83cc019SAndroid Build Coastguard Worker 		       I915_GEM_DOMAIN_WC, I915_GEM_DOMAIN_WC);
2530*d83cc019SAndroid Build Coastguard Worker 
2531*d83cc019SAndroid Build Coastguard Worker 	status_object[1].relocs_ptr = to_user_pointer(reloc);
2532*d83cc019SAndroid Build Coastguard Worker 	status_object[1].relocation_count = 2;
2533*d83cc019SAndroid Build Coastguard Worker 	if (flags & INIT_CLOCKS)
2534*d83cc019SAndroid Build Coastguard Worker 		status_object[1].relocation_count += 2;
2535*d83cc019SAndroid Build Coastguard Worker 
2536*d83cc019SAndroid Build Coastguard Worker 	for (int engine = 0; engine < NUM_ENGINES; engine++) {
2537*d83cc019SAndroid Build Coastguard Worker 		struct drm_i915_gem_relocation_entry *r = reloc;
2538*d83cc019SAndroid Build Coastguard Worker 		uint64_t presumed_offset = status_object[0].offset;
2539*d83cc019SAndroid Build Coastguard Worker 		uint32_t offset = engine * 128;
2540*d83cc019SAndroid Build Coastguard Worker 		uint32_t *cs = base + offset / sizeof(*cs);
2541*d83cc019SAndroid Build Coastguard Worker 		uint64_t addr;
2542*d83cc019SAndroid Build Coastguard Worker 
2543*d83cc019SAndroid Build Coastguard Worker 		r->offset = offset + sizeof(uint32_t);
2544*d83cc019SAndroid Build Coastguard Worker 		r->delta = SEQNO_OFFSET(engine);
2545*d83cc019SAndroid Build Coastguard Worker 		r->presumed_offset = presumed_offset;
2546*d83cc019SAndroid Build Coastguard Worker 		addr = presumed_offset + r->delta;
2547*d83cc019SAndroid Build Coastguard Worker 		r++;
2548*d83cc019SAndroid Build Coastguard Worker 		*cs++ = MI_STORE_DWORD_IMM;
2549*d83cc019SAndroid Build Coastguard Worker 		*cs++ = addr;
2550*d83cc019SAndroid Build Coastguard Worker 		*cs++ = addr >> 32;
2551*d83cc019SAndroid Build Coastguard Worker 		*cs++ = new_seqno(wrk, engine);
2552*d83cc019SAndroid Build Coastguard Worker 		offset += 4 * sizeof(uint32_t);
2553*d83cc019SAndroid Build Coastguard Worker 
2554*d83cc019SAndroid Build Coastguard Worker 		/* When we are busy, we can just reuse the last set of timings.
2555*d83cc019SAndroid Build Coastguard Worker 		 * If we have been idle for a while, we want to resample the
2556*d83cc019SAndroid Build Coastguard Worker 		 * latency on each engine (to measure external load).
2557*d83cc019SAndroid Build Coastguard Worker 		 */
2558*d83cc019SAndroid Build Coastguard Worker 		if (flags & INIT_CLOCKS) {
2559*d83cc019SAndroid Build Coastguard Worker 			r->offset = offset + sizeof(uint32_t);
2560*d83cc019SAndroid Build Coastguard Worker 			r->delta = SEQNO_OFFSET(engine) + sizeof(uint32_t);
2561*d83cc019SAndroid Build Coastguard Worker 			r->presumed_offset = presumed_offset;
2562*d83cc019SAndroid Build Coastguard Worker 			addr = presumed_offset + r->delta;
2563*d83cc019SAndroid Build Coastguard Worker 			r++;
2564*d83cc019SAndroid Build Coastguard Worker 			*cs++ = MI_STORE_DWORD_IMM;
2565*d83cc019SAndroid Build Coastguard Worker 			*cs++ = addr;
2566*d83cc019SAndroid Build Coastguard Worker 			*cs++ = addr >> 32;
2567*d83cc019SAndroid Build Coastguard Worker 			*cs++ = *REG(RCS_TIMESTAMP);
2568*d83cc019SAndroid Build Coastguard Worker 			offset += 4 * sizeof(uint32_t);
2569*d83cc019SAndroid Build Coastguard Worker 
2570*d83cc019SAndroid Build Coastguard Worker 			r->offset = offset + 2 * sizeof(uint32_t);
2571*d83cc019SAndroid Build Coastguard Worker 			r->delta = SEQNO_OFFSET(engine) + 2*sizeof(uint32_t);
2572*d83cc019SAndroid Build Coastguard Worker 			r->presumed_offset = presumed_offset;
2573*d83cc019SAndroid Build Coastguard Worker 			addr = presumed_offset + r->delta;
2574*d83cc019SAndroid Build Coastguard Worker 			r++;
2575*d83cc019SAndroid Build Coastguard Worker 			*cs++ = 0x24 << 23 | 2; /* MI_STORE_REG_MEM */
2576*d83cc019SAndroid Build Coastguard Worker 			*cs++ = RCS_TIMESTAMP;
2577*d83cc019SAndroid Build Coastguard Worker 			*cs++ = addr;
2578*d83cc019SAndroid Build Coastguard Worker 			*cs++ = addr >> 32;
2579*d83cc019SAndroid Build Coastguard Worker 			offset += 4 * sizeof(uint32_t);
2580*d83cc019SAndroid Build Coastguard Worker 		}
2581*d83cc019SAndroid Build Coastguard Worker 
2582*d83cc019SAndroid Build Coastguard Worker 		r->offset = offset + sizeof(uint32_t);
2583*d83cc019SAndroid Build Coastguard Worker 		r->delta = SEQNO_OFFSET(engine) + 3*sizeof(uint32_t);
2584*d83cc019SAndroid Build Coastguard Worker 		r->presumed_offset = presumed_offset;
2585*d83cc019SAndroid Build Coastguard Worker 		addr = presumed_offset + r->delta;
2586*d83cc019SAndroid Build Coastguard Worker 		r++;
2587*d83cc019SAndroid Build Coastguard Worker 		*cs++ = MI_STORE_DWORD_IMM;
2588*d83cc019SAndroid Build Coastguard Worker 		*cs++ = addr;
2589*d83cc019SAndroid Build Coastguard Worker 		*cs++ = addr >> 32;
2590*d83cc019SAndroid Build Coastguard Worker 		*cs++ = current_seqno(wrk, engine);
2591*d83cc019SAndroid Build Coastguard Worker 		offset += 4 * sizeof(uint32_t);
2592*d83cc019SAndroid Build Coastguard Worker 
2593*d83cc019SAndroid Build Coastguard Worker 		*cs++ = MI_BATCH_BUFFER_END;
2594*d83cc019SAndroid Build Coastguard Worker 
2595*d83cc019SAndroid Build Coastguard Worker 		eb_set_engine(&eb, engine, wrk->flags);
2596*d83cc019SAndroid Build Coastguard Worker 		eb.flags |= I915_EXEC_HANDLE_LUT;
2597*d83cc019SAndroid Build Coastguard Worker 		eb.flags |= I915_EXEC_NO_RELOC;
2598*d83cc019SAndroid Build Coastguard Worker 
2599*d83cc019SAndroid Build Coastguard Worker 		eb.batch_start_offset = 128 * engine;
2600*d83cc019SAndroid Build Coastguard Worker 
2601*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &eb);
2602*d83cc019SAndroid Build Coastguard Worker 	}
2603*d83cc019SAndroid Build Coastguard Worker }
2604*d83cc019SAndroid Build Coastguard Worker 
2605*d83cc019SAndroid Build Coastguard Worker static void
do_eb(struct workload * wrk,struct w_step * w,enum intel_engine_id engine,unsigned int flags)2606*d83cc019SAndroid Build Coastguard Worker do_eb(struct workload *wrk, struct w_step *w, enum intel_engine_id engine,
2607*d83cc019SAndroid Build Coastguard Worker       unsigned int flags)
2608*d83cc019SAndroid Build Coastguard Worker {
2609*d83cc019SAndroid Build Coastguard Worker 	uint32_t seqno = new_seqno(wrk, engine);
2610*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
2611*d83cc019SAndroid Build Coastguard Worker 
2612*d83cc019SAndroid Build Coastguard Worker 	eb_update_flags(wrk, w, engine, flags);
2613*d83cc019SAndroid Build Coastguard Worker 
2614*d83cc019SAndroid Build Coastguard Worker 	if (flags & SEQNO)
2615*d83cc019SAndroid Build Coastguard Worker 		update_bb_seqno(w, engine, seqno);
2616*d83cc019SAndroid Build Coastguard Worker 	if (flags & RT)
2617*d83cc019SAndroid Build Coastguard Worker 		update_bb_rt(w, engine, seqno);
2618*d83cc019SAndroid Build Coastguard Worker 
2619*d83cc019SAndroid Build Coastguard Worker 	update_bb_start(w);
2620*d83cc019SAndroid Build Coastguard Worker 
2621*d83cc019SAndroid Build Coastguard Worker 	w->eb.batch_start_offset =
2622*d83cc019SAndroid Build Coastguard Worker 		w->unbound_duration ?
2623*d83cc019SAndroid Build Coastguard Worker 		0 :
2624*d83cc019SAndroid Build Coastguard Worker 		ALIGN(w->bb_sz - get_bb_sz(get_duration(wrk, w)),
2625*d83cc019SAndroid Build Coastguard Worker 		      2 * sizeof(uint32_t));
2626*d83cc019SAndroid Build Coastguard Worker 
2627*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < w->fence_deps.nr; i++) {
2628*d83cc019SAndroid Build Coastguard Worker 		int tgt = w->idx + w->fence_deps.list[i];
2629*d83cc019SAndroid Build Coastguard Worker 
2630*d83cc019SAndroid Build Coastguard Worker 		/* TODO: fence merging needed to support multiple inputs */
2631*d83cc019SAndroid Build Coastguard Worker 		igt_assert(i == 0);
2632*d83cc019SAndroid Build Coastguard Worker 		igt_assert(tgt >= 0 && tgt < w->idx);
2633*d83cc019SAndroid Build Coastguard Worker 		igt_assert(wrk->steps[tgt].emit_fence > 0);
2634*d83cc019SAndroid Build Coastguard Worker 
2635*d83cc019SAndroid Build Coastguard Worker 		if (w->fence_deps.submit_fence)
2636*d83cc019SAndroid Build Coastguard Worker 			w->eb.flags |= I915_EXEC_FENCE_SUBMIT;
2637*d83cc019SAndroid Build Coastguard Worker 		else
2638*d83cc019SAndroid Build Coastguard Worker 			w->eb.flags |= I915_EXEC_FENCE_IN;
2639*d83cc019SAndroid Build Coastguard Worker 
2640*d83cc019SAndroid Build Coastguard Worker 		w->eb.rsvd2 = wrk->steps[tgt].emit_fence;
2641*d83cc019SAndroid Build Coastguard Worker 	}
2642*d83cc019SAndroid Build Coastguard Worker 
2643*d83cc019SAndroid Build Coastguard Worker 	if (w->eb.flags & I915_EXEC_FENCE_OUT)
2644*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf_wr(fd, &w->eb);
2645*d83cc019SAndroid Build Coastguard Worker 	else
2646*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &w->eb);
2647*d83cc019SAndroid Build Coastguard Worker 
2648*d83cc019SAndroid Build Coastguard Worker 	if (w->eb.flags & I915_EXEC_FENCE_OUT) {
2649*d83cc019SAndroid Build Coastguard Worker 		w->emit_fence = w->eb.rsvd2 >> 32;
2650*d83cc019SAndroid Build Coastguard Worker 		igt_assert(w->emit_fence > 0);
2651*d83cc019SAndroid Build Coastguard Worker 	}
2652*d83cc019SAndroid Build Coastguard Worker }
2653*d83cc019SAndroid Build Coastguard Worker 
sync_deps(struct workload * wrk,struct w_step * w)2654*d83cc019SAndroid Build Coastguard Worker static bool sync_deps(struct workload *wrk, struct w_step *w)
2655*d83cc019SAndroid Build Coastguard Worker {
2656*d83cc019SAndroid Build Coastguard Worker 	bool synced = false;
2657*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
2658*d83cc019SAndroid Build Coastguard Worker 
2659*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < w->data_deps.nr; i++) {
2660*d83cc019SAndroid Build Coastguard Worker 		int dep_idx;
2661*d83cc019SAndroid Build Coastguard Worker 
2662*d83cc019SAndroid Build Coastguard Worker 		igt_assert(w->data_deps.list[i] <= 0);
2663*d83cc019SAndroid Build Coastguard Worker 
2664*d83cc019SAndroid Build Coastguard Worker 		if (!w->data_deps.list[i])
2665*d83cc019SAndroid Build Coastguard Worker 			continue;
2666*d83cc019SAndroid Build Coastguard Worker 
2667*d83cc019SAndroid Build Coastguard Worker 		dep_idx = w->idx + w->data_deps.list[i];
2668*d83cc019SAndroid Build Coastguard Worker 
2669*d83cc019SAndroid Build Coastguard Worker 		igt_assert(dep_idx >= 0 && dep_idx < w->idx);
2670*d83cc019SAndroid Build Coastguard Worker 		igt_assert(wrk->steps[dep_idx].type == BATCH);
2671*d83cc019SAndroid Build Coastguard Worker 
2672*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, wrk->steps[dep_idx].obj[0].handle);
2673*d83cc019SAndroid Build Coastguard Worker 
2674*d83cc019SAndroid Build Coastguard Worker 		synced = true;
2675*d83cc019SAndroid Build Coastguard Worker 	}
2676*d83cc019SAndroid Build Coastguard Worker 
2677*d83cc019SAndroid Build Coastguard Worker 	return synced;
2678*d83cc019SAndroid Build Coastguard Worker }
2679*d83cc019SAndroid Build Coastguard Worker 
run_workload(void * data)2680*d83cc019SAndroid Build Coastguard Worker static void *run_workload(void *data)
2681*d83cc019SAndroid Build Coastguard Worker {
2682*d83cc019SAndroid Build Coastguard Worker 	struct workload *wrk = (struct workload *)data;
2683*d83cc019SAndroid Build Coastguard Worker 	struct timespec t_start, t_end;
2684*d83cc019SAndroid Build Coastguard Worker 	struct w_step *w;
2685*d83cc019SAndroid Build Coastguard Worker 	bool last_sync = false;
2686*d83cc019SAndroid Build Coastguard Worker 	int throttle = -1;
2687*d83cc019SAndroid Build Coastguard Worker 	int qd_throttle = -1;
2688*d83cc019SAndroid Build Coastguard Worker 	int count;
2689*d83cc019SAndroid Build Coastguard Worker 	int i;
2690*d83cc019SAndroid Build Coastguard Worker 
2691*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_start);
2692*d83cc019SAndroid Build Coastguard Worker 
2693*d83cc019SAndroid Build Coastguard Worker 	init_status_page(wrk, INIT_ALL);
2694*d83cc019SAndroid Build Coastguard Worker 	for (count = 0; wrk->run && (wrk->background || count < wrk->repeat);
2695*d83cc019SAndroid Build Coastguard Worker 	     count++) {
2696*d83cc019SAndroid Build Coastguard Worker 		unsigned int cur_seqno = wrk->sync_seqno;
2697*d83cc019SAndroid Build Coastguard Worker 
2698*d83cc019SAndroid Build Coastguard Worker 		clock_gettime(CLOCK_MONOTONIC, &wrk->repeat_start);
2699*d83cc019SAndroid Build Coastguard Worker 
2700*d83cc019SAndroid Build Coastguard Worker 		for (i = 0, w = wrk->steps; wrk->run && (i < wrk->nr_steps);
2701*d83cc019SAndroid Build Coastguard Worker 		     i++, w++) {
2702*d83cc019SAndroid Build Coastguard Worker 			enum intel_engine_id engine = w->engine;
2703*d83cc019SAndroid Build Coastguard Worker 			int do_sleep = 0;
2704*d83cc019SAndroid Build Coastguard Worker 
2705*d83cc019SAndroid Build Coastguard Worker 			if (w->type == DELAY) {
2706*d83cc019SAndroid Build Coastguard Worker 				do_sleep = w->delay;
2707*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == PERIOD) {
2708*d83cc019SAndroid Build Coastguard Worker 				struct timespec now;
2709*d83cc019SAndroid Build Coastguard Worker 
2710*d83cc019SAndroid Build Coastguard Worker 				clock_gettime(CLOCK_MONOTONIC, &now);
2711*d83cc019SAndroid Build Coastguard Worker 				do_sleep = w->period -
2712*d83cc019SAndroid Build Coastguard Worker 					   elapsed_us(&wrk->repeat_start, &now);
2713*d83cc019SAndroid Build Coastguard Worker 				if (do_sleep < 0) {
2714*d83cc019SAndroid Build Coastguard Worker 					if (verbose > 1)
2715*d83cc019SAndroid Build Coastguard Worker 						printf("%u: Dropped period @ %u/%u (%dus late)!\n",
2716*d83cc019SAndroid Build Coastguard Worker 						       wrk->id, count, i, do_sleep);
2717*d83cc019SAndroid Build Coastguard Worker 					continue;
2718*d83cc019SAndroid Build Coastguard Worker 				}
2719*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == SYNC) {
2720*d83cc019SAndroid Build Coastguard Worker 				unsigned int s_idx = i + w->target;
2721*d83cc019SAndroid Build Coastguard Worker 
2722*d83cc019SAndroid Build Coastguard Worker 				igt_assert(s_idx >= 0 && s_idx < i);
2723*d83cc019SAndroid Build Coastguard Worker 				igt_assert(wrk->steps[s_idx].type == BATCH);
2724*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, wrk->steps[s_idx].obj[0].handle);
2725*d83cc019SAndroid Build Coastguard Worker 				continue;
2726*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == THROTTLE) {
2727*d83cc019SAndroid Build Coastguard Worker 				throttle = w->throttle;
2728*d83cc019SAndroid Build Coastguard Worker 				continue;
2729*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == QD_THROTTLE) {
2730*d83cc019SAndroid Build Coastguard Worker 				qd_throttle = w->throttle;
2731*d83cc019SAndroid Build Coastguard Worker 				continue;
2732*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == SW_FENCE) {
2733*d83cc019SAndroid Build Coastguard Worker 				igt_assert(w->emit_fence < 0);
2734*d83cc019SAndroid Build Coastguard Worker 				w->emit_fence =
2735*d83cc019SAndroid Build Coastguard Worker 					sw_sync_timeline_create_fence(wrk->sync_timeline,
2736*d83cc019SAndroid Build Coastguard Worker 								      cur_seqno + w->idx);
2737*d83cc019SAndroid Build Coastguard Worker 				igt_assert(w->emit_fence > 0);
2738*d83cc019SAndroid Build Coastguard Worker 				continue;
2739*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == SW_FENCE_SIGNAL) {
2740*d83cc019SAndroid Build Coastguard Worker 				int tgt = w->idx + w->target;
2741*d83cc019SAndroid Build Coastguard Worker 				int inc;
2742*d83cc019SAndroid Build Coastguard Worker 
2743*d83cc019SAndroid Build Coastguard Worker 				igt_assert(tgt >= 0 && tgt < i);
2744*d83cc019SAndroid Build Coastguard Worker 				igt_assert(wrk->steps[tgt].type == SW_FENCE);
2745*d83cc019SAndroid Build Coastguard Worker 				cur_seqno += wrk->steps[tgt].idx;
2746*d83cc019SAndroid Build Coastguard Worker 				inc = cur_seqno - wrk->sync_seqno;
2747*d83cc019SAndroid Build Coastguard Worker 				sw_sync_timeline_inc(wrk->sync_timeline, inc);
2748*d83cc019SAndroid Build Coastguard Worker 				continue;
2749*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == CTX_PRIORITY) {
2750*d83cc019SAndroid Build Coastguard Worker 				if (w->priority != wrk->ctx_list[w->context].priority) {
2751*d83cc019SAndroid Build Coastguard Worker 					struct drm_i915_gem_context_param param = {
2752*d83cc019SAndroid Build Coastguard Worker 						.ctx_id = wrk->ctx_list[w->context].id,
2753*d83cc019SAndroid Build Coastguard Worker 						.param = I915_CONTEXT_PARAM_PRIORITY,
2754*d83cc019SAndroid Build Coastguard Worker 						.value = w->priority,
2755*d83cc019SAndroid Build Coastguard Worker 					};
2756*d83cc019SAndroid Build Coastguard Worker 
2757*d83cc019SAndroid Build Coastguard Worker 					gem_context_set_param(fd, &param);
2758*d83cc019SAndroid Build Coastguard Worker 					wrk->ctx_list[w->context].priority =
2759*d83cc019SAndroid Build Coastguard Worker 								    w->priority;
2760*d83cc019SAndroid Build Coastguard Worker 				}
2761*d83cc019SAndroid Build Coastguard Worker 				continue;
2762*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == TERMINATE) {
2763*d83cc019SAndroid Build Coastguard Worker 				unsigned int t_idx = i + w->target;
2764*d83cc019SAndroid Build Coastguard Worker 
2765*d83cc019SAndroid Build Coastguard Worker 				igt_assert(t_idx >= 0 && t_idx < i);
2766*d83cc019SAndroid Build Coastguard Worker 				igt_assert(wrk->steps[t_idx].type == BATCH);
2767*d83cc019SAndroid Build Coastguard Worker 				igt_assert(wrk->steps[t_idx].unbound_duration);
2768*d83cc019SAndroid Build Coastguard Worker 
2769*d83cc019SAndroid Build Coastguard Worker 				*wrk->steps[t_idx].recursive_bb_start =
2770*d83cc019SAndroid Build Coastguard Worker 					MI_BATCH_BUFFER_END;
2771*d83cc019SAndroid Build Coastguard Worker 				__sync_synchronize();
2772*d83cc019SAndroid Build Coastguard Worker 				continue;
2773*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == PREEMPTION ||
2774*d83cc019SAndroid Build Coastguard Worker 				   w->type == ENGINE_MAP ||
2775*d83cc019SAndroid Build Coastguard Worker 				   w->type == LOAD_BALANCE ||
2776*d83cc019SAndroid Build Coastguard Worker 				   w->type == BOND) {
2777*d83cc019SAndroid Build Coastguard Worker 				continue;
2778*d83cc019SAndroid Build Coastguard Worker 			} else if (w->type == SSEU) {
2779*d83cc019SAndroid Build Coastguard Worker 				if (w->sseu != wrk->ctx_list[w->context * 2].sseu) {
2780*d83cc019SAndroid Build Coastguard Worker 					wrk->ctx_list[w->context * 2].sseu =
2781*d83cc019SAndroid Build Coastguard Worker 						set_ctx_sseu(&wrk->ctx_list[w->context * 2],
2782*d83cc019SAndroid Build Coastguard Worker 							     w->sseu);
2783*d83cc019SAndroid Build Coastguard Worker 				}
2784*d83cc019SAndroid Build Coastguard Worker 				continue;
2785*d83cc019SAndroid Build Coastguard Worker 			}
2786*d83cc019SAndroid Build Coastguard Worker 
2787*d83cc019SAndroid Build Coastguard Worker 			if (do_sleep || w->type == PERIOD) {
2788*d83cc019SAndroid Build Coastguard Worker 				usleep(do_sleep);
2789*d83cc019SAndroid Build Coastguard Worker 				continue;
2790*d83cc019SAndroid Build Coastguard Worker 			}
2791*d83cc019SAndroid Build Coastguard Worker 
2792*d83cc019SAndroid Build Coastguard Worker 			igt_assert(w->type == BATCH);
2793*d83cc019SAndroid Build Coastguard Worker 
2794*d83cc019SAndroid Build Coastguard Worker 			if ((wrk->flags & DEPSYNC) && engine == VCS)
2795*d83cc019SAndroid Build Coastguard Worker 				last_sync = sync_deps(wrk, w);
2796*d83cc019SAndroid Build Coastguard Worker 
2797*d83cc019SAndroid Build Coastguard Worker 			if (last_sync && (wrk->flags & HEARTBEAT))
2798*d83cc019SAndroid Build Coastguard Worker 				init_status_page(wrk, 0);
2799*d83cc019SAndroid Build Coastguard Worker 
2800*d83cc019SAndroid Build Coastguard Worker 			last_sync = false;
2801*d83cc019SAndroid Build Coastguard Worker 
2802*d83cc019SAndroid Build Coastguard Worker 			wrk->nr_bb[engine]++;
2803*d83cc019SAndroid Build Coastguard Worker 			if (engine == VCS && wrk->balancer &&
2804*d83cc019SAndroid Build Coastguard Worker 			    wrk->balancer->balance) {
2805*d83cc019SAndroid Build Coastguard Worker 				engine = wrk->balancer->balance(wrk->balancer,
2806*d83cc019SAndroid Build Coastguard Worker 								wrk, w);
2807*d83cc019SAndroid Build Coastguard Worker 				wrk->nr_bb[engine]++;
2808*d83cc019SAndroid Build Coastguard Worker 			}
2809*d83cc019SAndroid Build Coastguard Worker 
2810*d83cc019SAndroid Build Coastguard Worker 			if (throttle > 0)
2811*d83cc019SAndroid Build Coastguard Worker 				w_sync_to(wrk, w, i - throttle);
2812*d83cc019SAndroid Build Coastguard Worker 
2813*d83cc019SAndroid Build Coastguard Worker 			do_eb(wrk, w, engine, wrk->flags);
2814*d83cc019SAndroid Build Coastguard Worker 
2815*d83cc019SAndroid Build Coastguard Worker 			if (w->request != -1) {
2816*d83cc019SAndroid Build Coastguard Worker 				igt_list_del(&w->rq_link);
2817*d83cc019SAndroid Build Coastguard Worker 				wrk->nrequest[w->request]--;
2818*d83cc019SAndroid Build Coastguard Worker 			}
2819*d83cc019SAndroid Build Coastguard Worker 			w->request = engine;
2820*d83cc019SAndroid Build Coastguard Worker 			igt_list_add_tail(&w->rq_link, &wrk->requests[engine]);
2821*d83cc019SAndroid Build Coastguard Worker 			wrk->nrequest[engine]++;
2822*d83cc019SAndroid Build Coastguard Worker 
2823*d83cc019SAndroid Build Coastguard Worker 			if (!wrk->run)
2824*d83cc019SAndroid Build Coastguard Worker 				break;
2825*d83cc019SAndroid Build Coastguard Worker 
2826*d83cc019SAndroid Build Coastguard Worker 			if (w->sync) {
2827*d83cc019SAndroid Build Coastguard Worker 				gem_sync(fd, w->obj[0].handle);
2828*d83cc019SAndroid Build Coastguard Worker 				last_sync = true;
2829*d83cc019SAndroid Build Coastguard Worker 			}
2830*d83cc019SAndroid Build Coastguard Worker 
2831*d83cc019SAndroid Build Coastguard Worker 			if (qd_throttle > 0) {
2832*d83cc019SAndroid Build Coastguard Worker 				while (wrk->nrequest[engine] > qd_throttle) {
2833*d83cc019SAndroid Build Coastguard Worker 					struct w_step *s;
2834*d83cc019SAndroid Build Coastguard Worker 
2835*d83cc019SAndroid Build Coastguard Worker 					s = igt_list_first_entry(&wrk->requests[engine],
2836*d83cc019SAndroid Build Coastguard Worker 								 s, rq_link);
2837*d83cc019SAndroid Build Coastguard Worker 
2838*d83cc019SAndroid Build Coastguard Worker 					gem_sync(fd, s->obj[0].handle);
2839*d83cc019SAndroid Build Coastguard Worker 					last_sync = true;
2840*d83cc019SAndroid Build Coastguard Worker 
2841*d83cc019SAndroid Build Coastguard Worker 					s->request = -1;
2842*d83cc019SAndroid Build Coastguard Worker 					igt_list_del(&s->rq_link);
2843*d83cc019SAndroid Build Coastguard Worker 					wrk->nrequest[engine]--;
2844*d83cc019SAndroid Build Coastguard Worker 				}
2845*d83cc019SAndroid Build Coastguard Worker 			}
2846*d83cc019SAndroid Build Coastguard Worker 		}
2847*d83cc019SAndroid Build Coastguard Worker 
2848*d83cc019SAndroid Build Coastguard Worker 		if (wrk->sync_timeline) {
2849*d83cc019SAndroid Build Coastguard Worker 			int inc;
2850*d83cc019SAndroid Build Coastguard Worker 
2851*d83cc019SAndroid Build Coastguard Worker 			inc = wrk->nr_steps - (cur_seqno - wrk->sync_seqno);
2852*d83cc019SAndroid Build Coastguard Worker 			sw_sync_timeline_inc(wrk->sync_timeline, inc);
2853*d83cc019SAndroid Build Coastguard Worker 			wrk->sync_seqno += wrk->nr_steps;
2854*d83cc019SAndroid Build Coastguard Worker 		}
2855*d83cc019SAndroid Build Coastguard Worker 
2856*d83cc019SAndroid Build Coastguard Worker 		/* Cleanup all fences instantiated in this iteration. */
2857*d83cc019SAndroid Build Coastguard Worker 		for (i = 0, w = wrk->steps; wrk->run && (i < wrk->nr_steps);
2858*d83cc019SAndroid Build Coastguard Worker 		     i++, w++) {
2859*d83cc019SAndroid Build Coastguard Worker 			if (w->emit_fence > 0) {
2860*d83cc019SAndroid Build Coastguard Worker 				close(w->emit_fence);
2861*d83cc019SAndroid Build Coastguard Worker 				w->emit_fence = -1;
2862*d83cc019SAndroid Build Coastguard Worker 			}
2863*d83cc019SAndroid Build Coastguard Worker 		}
2864*d83cc019SAndroid Build Coastguard Worker 	}
2865*d83cc019SAndroid Build Coastguard Worker 
2866*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < NUM_ENGINES; i++) {
2867*d83cc019SAndroid Build Coastguard Worker 		if (!wrk->nrequest[i])
2868*d83cc019SAndroid Build Coastguard Worker 			continue;
2869*d83cc019SAndroid Build Coastguard Worker 
2870*d83cc019SAndroid Build Coastguard Worker 		w = igt_list_last_entry(&wrk->requests[i], w, rq_link);
2871*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, w->obj[0].handle);
2872*d83cc019SAndroid Build Coastguard Worker 	}
2873*d83cc019SAndroid Build Coastguard Worker 
2874*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_end);
2875*d83cc019SAndroid Build Coastguard Worker 
2876*d83cc019SAndroid Build Coastguard Worker 	if (wrk->print_stats) {
2877*d83cc019SAndroid Build Coastguard Worker 		double t = elapsed(&t_start, &t_end);
2878*d83cc019SAndroid Build Coastguard Worker 
2879*d83cc019SAndroid Build Coastguard Worker 		printf("%c%u: %.3fs elapsed (%d cycles, %.3f workloads/s).",
2880*d83cc019SAndroid Build Coastguard Worker 		       wrk->background ? ' ' : '*', wrk->id,
2881*d83cc019SAndroid Build Coastguard Worker 		       t, count, count / t);
2882*d83cc019SAndroid Build Coastguard Worker 		if (wrk->balancer)
2883*d83cc019SAndroid Build Coastguard Worker 			printf(" %lu (%lu + %lu) total VCS batches.",
2884*d83cc019SAndroid Build Coastguard Worker 			       wrk->nr_bb[VCS], wrk->nr_bb[VCS1], wrk->nr_bb[VCS2]);
2885*d83cc019SAndroid Build Coastguard Worker 		if (wrk->balancer && wrk->balancer->get_qd)
2886*d83cc019SAndroid Build Coastguard Worker 			printf(" Average queue depths %.3f, %.3f.",
2887*d83cc019SAndroid Build Coastguard Worker 			       (double)wrk->qd_sum[VCS1] / wrk->nr_bb[VCS],
2888*d83cc019SAndroid Build Coastguard Worker 			       (double)wrk->qd_sum[VCS2] / wrk->nr_bb[VCS]);
2889*d83cc019SAndroid Build Coastguard Worker 		putchar('\n');
2890*d83cc019SAndroid Build Coastguard Worker 	}
2891*d83cc019SAndroid Build Coastguard Worker 
2892*d83cc019SAndroid Build Coastguard Worker 	return NULL;
2893*d83cc019SAndroid Build Coastguard Worker }
2894*d83cc019SAndroid Build Coastguard Worker 
fini_workload(struct workload * wrk)2895*d83cc019SAndroid Build Coastguard Worker static void fini_workload(struct workload *wrk)
2896*d83cc019SAndroid Build Coastguard Worker {
2897*d83cc019SAndroid Build Coastguard Worker 	free(wrk->steps);
2898*d83cc019SAndroid Build Coastguard Worker 	free(wrk);
2899*d83cc019SAndroid Build Coastguard Worker }
2900*d83cc019SAndroid Build Coastguard Worker 
calibrate_nop(unsigned int tolerance_pct)2901*d83cc019SAndroid Build Coastguard Worker static unsigned long calibrate_nop(unsigned int tolerance_pct)
2902*d83cc019SAndroid Build Coastguard Worker {
2903*d83cc019SAndroid Build Coastguard Worker 	const uint32_t bbe = 0xa << 23;
2904*d83cc019SAndroid Build Coastguard Worker 	unsigned int loops = 17;
2905*d83cc019SAndroid Build Coastguard Worker 	unsigned int usecs = nop_calibration_us;
2906*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_exec_object2 obj = {};
2907*d83cc019SAndroid Build Coastguard Worker 	struct drm_i915_gem_execbuffer2 eb =
2908*d83cc019SAndroid Build Coastguard Worker 		{ .buffer_count = 1, .buffers_ptr = (uintptr_t)&obj};
2909*d83cc019SAndroid Build Coastguard Worker 	long size, last_size;
2910*d83cc019SAndroid Build Coastguard Worker 	struct timespec t_0, t_end;
2911*d83cc019SAndroid Build Coastguard Worker 
2912*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_0);
2913*d83cc019SAndroid Build Coastguard Worker 
2914*d83cc019SAndroid Build Coastguard Worker 	size = 256 * 1024;
2915*d83cc019SAndroid Build Coastguard Worker 	do {
2916*d83cc019SAndroid Build Coastguard Worker 		struct timespec t_start;
2917*d83cc019SAndroid Build Coastguard Worker 
2918*d83cc019SAndroid Build Coastguard Worker 		obj.handle = gem_create(fd, size);
2919*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, obj.handle, size - sizeof(bbe), &bbe,
2920*d83cc019SAndroid Build Coastguard Worker 			  sizeof(bbe));
2921*d83cc019SAndroid Build Coastguard Worker 		gem_execbuf(fd, &eb);
2922*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, obj.handle);
2923*d83cc019SAndroid Build Coastguard Worker 
2924*d83cc019SAndroid Build Coastguard Worker 		clock_gettime(CLOCK_MONOTONIC, &t_start);
2925*d83cc019SAndroid Build Coastguard Worker 		for (int loop = 0; loop < loops; loop++)
2926*d83cc019SAndroid Build Coastguard Worker 			gem_execbuf(fd, &eb);
2927*d83cc019SAndroid Build Coastguard Worker 		gem_sync(fd, obj.handle);
2928*d83cc019SAndroid Build Coastguard Worker 		clock_gettime(CLOCK_MONOTONIC, &t_end);
2929*d83cc019SAndroid Build Coastguard Worker 
2930*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, obj.handle);
2931*d83cc019SAndroid Build Coastguard Worker 
2932*d83cc019SAndroid Build Coastguard Worker 		last_size = size;
2933*d83cc019SAndroid Build Coastguard Worker 		size = loops * size / elapsed(&t_start, &t_end) / 1e6 * usecs;
2934*d83cc019SAndroid Build Coastguard Worker 		size = ALIGN(size, sizeof(uint32_t));
2935*d83cc019SAndroid Build Coastguard Worker 	} while (elapsed(&t_0, &t_end) < 5 ||
2936*d83cc019SAndroid Build Coastguard Worker 		 abs(size - last_size) > (size * tolerance_pct / 100));
2937*d83cc019SAndroid Build Coastguard Worker 
2938*d83cc019SAndroid Build Coastguard Worker 	return size / sizeof(uint32_t);
2939*d83cc019SAndroid Build Coastguard Worker }
2940*d83cc019SAndroid Build Coastguard Worker 
print_help(void)2941*d83cc019SAndroid Build Coastguard Worker static void print_help(void)
2942*d83cc019SAndroid Build Coastguard Worker {
2943*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
2944*d83cc019SAndroid Build Coastguard Worker 
2945*d83cc019SAndroid Build Coastguard Worker 	puts(
2946*d83cc019SAndroid Build Coastguard Worker "Usage: gem_wsim [OPTIONS]\n"
2947*d83cc019SAndroid Build Coastguard Worker "\n"
2948*d83cc019SAndroid Build Coastguard Worker "Runs a simulated workload on the GPU.\n"
2949*d83cc019SAndroid Build Coastguard Worker "When ran without arguments performs a GPU calibration result of which needs to\n"
2950*d83cc019SAndroid Build Coastguard Worker "be provided when running the simulation in subsequent invocations.\n"
2951*d83cc019SAndroid Build Coastguard Worker "\n"
2952*d83cc019SAndroid Build Coastguard Worker "Options:\n"
2953*d83cc019SAndroid Build Coastguard Worker "  -h              This text.\n"
2954*d83cc019SAndroid Build Coastguard Worker "  -q              Be quiet - do not output anything to stdout.\n"
2955*d83cc019SAndroid Build Coastguard Worker "  -n <n>          Nop calibration value.\n"
2956*d83cc019SAndroid Build Coastguard Worker "  -t <n>          Nop calibration tolerance percentage.\n"
2957*d83cc019SAndroid Build Coastguard Worker "                  Use when there is a difficulty obtaining calibration with the\n"
2958*d83cc019SAndroid Build Coastguard Worker "                  default settings.\n"
2959*d83cc019SAndroid Build Coastguard Worker "  -I <n>          Initial randomness seed.\n"
2960*d83cc019SAndroid Build Coastguard Worker "  -p <n>          Context priority to use for the following workload on the\n"
2961*d83cc019SAndroid Build Coastguard Worker "                  command line.\n"
2962*d83cc019SAndroid Build Coastguard Worker "  -w <desc|path>  Filename or a workload descriptor.\n"
2963*d83cc019SAndroid Build Coastguard Worker "                  Can be given multiple times.\n"
2964*d83cc019SAndroid Build Coastguard Worker "  -W <desc|path>  Filename or a master workload descriptor.\n"
2965*d83cc019SAndroid Build Coastguard Worker "                  Only one master workload can be optinally specified in which\n"
2966*d83cc019SAndroid Build Coastguard Worker "                  case all other workloads become background ones and run as\n"
2967*d83cc019SAndroid Build Coastguard Worker "                  long as the master.\n"
2968*d83cc019SAndroid Build Coastguard Worker "  -a <desc|path>  Append a workload to all other workloads.\n"
2969*d83cc019SAndroid Build Coastguard Worker "  -r <n>          How many times to emit the workload.\n"
2970*d83cc019SAndroid Build Coastguard Worker "  -c <n>          Fork N clients emitting the workload simultaneously.\n"
2971*d83cc019SAndroid Build Coastguard Worker "  -x              Swap VCS1 and VCS2 engines in every other client.\n"
2972*d83cc019SAndroid Build Coastguard Worker "  -b <n>          Load balancing to use.\n"
2973*d83cc019SAndroid Build Coastguard Worker "                  Available load balancers are:"
2974*d83cc019SAndroid Build Coastguard Worker 	);
2975*d83cc019SAndroid Build Coastguard Worker 
2976*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(all_balancers); i++) {
2977*d83cc019SAndroid Build Coastguard Worker 		igt_assert(all_balancers[i].desc);
2978*d83cc019SAndroid Build Coastguard Worker 		printf(
2979*d83cc019SAndroid Build Coastguard Worker "                     %s (%u): %s\n",
2980*d83cc019SAndroid Build Coastguard Worker 		       all_balancers[i].name, all_balancers[i].id,
2981*d83cc019SAndroid Build Coastguard Worker 		       all_balancers[i].desc);
2982*d83cc019SAndroid Build Coastguard Worker 	}
2983*d83cc019SAndroid Build Coastguard Worker 	puts(
2984*d83cc019SAndroid Build Coastguard Worker "                  Balancers can be specified either as names or as their id\n"
2985*d83cc019SAndroid Build Coastguard Worker "                  number as listed above.\n"
2986*d83cc019SAndroid Build Coastguard Worker "  -2              Remap VCS2 to BCS.\n"
2987*d83cc019SAndroid Build Coastguard Worker "  -R              Round-robin initial VCS assignment per client.\n"
2988*d83cc019SAndroid Build Coastguard Worker "  -H              Send heartbeat on synchronisation points with seqno based\n"
2989*d83cc019SAndroid Build Coastguard Worker "                  balancers. Gives better engine busyness view in some cases.\n"
2990*d83cc019SAndroid Build Coastguard Worker "  -s              Turn on small SSEU config for the next workload on the\n"
2991*d83cc019SAndroid Build Coastguard Worker "                  command line. Subsequent -s switches it off.\n"
2992*d83cc019SAndroid Build Coastguard Worker "  -S              Synchronize the sequence of random batch durations between\n"
2993*d83cc019SAndroid Build Coastguard Worker "                  clients.\n"
2994*d83cc019SAndroid Build Coastguard Worker "  -G              Global load balancing - a single load balancer will be shared\n"
2995*d83cc019SAndroid Build Coastguard Worker "                  between all clients and there will be a single seqno domain.\n"
2996*d83cc019SAndroid Build Coastguard Worker "  -d              Sync between data dependencies in userspace."
2997*d83cc019SAndroid Build Coastguard Worker 	);
2998*d83cc019SAndroid Build Coastguard Worker }
2999*d83cc019SAndroid Build Coastguard Worker 
load_workload_descriptor(char * filename)3000*d83cc019SAndroid Build Coastguard Worker static char *load_workload_descriptor(char *filename)
3001*d83cc019SAndroid Build Coastguard Worker {
3002*d83cc019SAndroid Build Coastguard Worker 	struct stat sbuf;
3003*d83cc019SAndroid Build Coastguard Worker 	char *buf;
3004*d83cc019SAndroid Build Coastguard Worker 	int infd, ret, i;
3005*d83cc019SAndroid Build Coastguard Worker 	ssize_t len;
3006*d83cc019SAndroid Build Coastguard Worker 
3007*d83cc019SAndroid Build Coastguard Worker 	ret = stat(filename, &sbuf);
3008*d83cc019SAndroid Build Coastguard Worker 	if (ret || !S_ISREG(sbuf.st_mode))
3009*d83cc019SAndroid Build Coastguard Worker 		return filename;
3010*d83cc019SAndroid Build Coastguard Worker 
3011*d83cc019SAndroid Build Coastguard Worker 	igt_assert(sbuf.st_size < 1024 * 1024); /* Just so. */
3012*d83cc019SAndroid Build Coastguard Worker 	buf = malloc(sbuf.st_size);
3013*d83cc019SAndroid Build Coastguard Worker 	igt_assert(buf);
3014*d83cc019SAndroid Build Coastguard Worker 
3015*d83cc019SAndroid Build Coastguard Worker 	infd = open(filename, O_RDONLY);
3016*d83cc019SAndroid Build Coastguard Worker 	igt_assert(infd >= 0);
3017*d83cc019SAndroid Build Coastguard Worker 	len = read(infd, buf, sbuf.st_size);
3018*d83cc019SAndroid Build Coastguard Worker 	igt_assert(len == sbuf.st_size);
3019*d83cc019SAndroid Build Coastguard Worker 	close(infd);
3020*d83cc019SAndroid Build Coastguard Worker 
3021*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < len; i++) {
3022*d83cc019SAndroid Build Coastguard Worker 		if (buf[i] == '\n')
3023*d83cc019SAndroid Build Coastguard Worker 			buf[i] = ',';
3024*d83cc019SAndroid Build Coastguard Worker 	}
3025*d83cc019SAndroid Build Coastguard Worker 
3026*d83cc019SAndroid Build Coastguard Worker 	len--;
3027*d83cc019SAndroid Build Coastguard Worker 	while (buf[len] == ',')
3028*d83cc019SAndroid Build Coastguard Worker 		buf[len--] = 0;
3029*d83cc019SAndroid Build Coastguard Worker 
3030*d83cc019SAndroid Build Coastguard Worker 	return buf;
3031*d83cc019SAndroid Build Coastguard Worker }
3032*d83cc019SAndroid Build Coastguard Worker 
3033*d83cc019SAndroid Build Coastguard Worker static struct w_arg *
add_workload_arg(struct w_arg * w_args,unsigned int nr_args,char * w_arg,int prio,bool sseu)3034*d83cc019SAndroid Build Coastguard Worker add_workload_arg(struct w_arg *w_args, unsigned int nr_args, char *w_arg,
3035*d83cc019SAndroid Build Coastguard Worker 		 int prio, bool sseu)
3036*d83cc019SAndroid Build Coastguard Worker {
3037*d83cc019SAndroid Build Coastguard Worker 	w_args = realloc(w_args, sizeof(*w_args) * nr_args);
3038*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w_args);
3039*d83cc019SAndroid Build Coastguard Worker 	w_args[nr_args - 1] = (struct w_arg) { w_arg, NULL, prio, sseu };
3040*d83cc019SAndroid Build Coastguard Worker 
3041*d83cc019SAndroid Build Coastguard Worker 	return w_args;
3042*d83cc019SAndroid Build Coastguard Worker }
3043*d83cc019SAndroid Build Coastguard Worker 
find_balancer_by_name(char * name)3044*d83cc019SAndroid Build Coastguard Worker static int find_balancer_by_name(char *name)
3045*d83cc019SAndroid Build Coastguard Worker {
3046*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
3047*d83cc019SAndroid Build Coastguard Worker 
3048*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(all_balancers); i++) {
3049*d83cc019SAndroid Build Coastguard Worker 		if (!strcasecmp(name, all_balancers[i].name))
3050*d83cc019SAndroid Build Coastguard Worker 			return all_balancers[i].id;
3051*d83cc019SAndroid Build Coastguard Worker 	}
3052*d83cc019SAndroid Build Coastguard Worker 
3053*d83cc019SAndroid Build Coastguard Worker 	return -1;
3054*d83cc019SAndroid Build Coastguard Worker }
3055*d83cc019SAndroid Build Coastguard Worker 
find_balancer_by_id(unsigned int id)3056*d83cc019SAndroid Build Coastguard Worker static const struct workload_balancer *find_balancer_by_id(unsigned int id)
3057*d83cc019SAndroid Build Coastguard Worker {
3058*d83cc019SAndroid Build Coastguard Worker 	unsigned int i;
3059*d83cc019SAndroid Build Coastguard Worker 
3060*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(all_balancers); i++) {
3061*d83cc019SAndroid Build Coastguard Worker 		if (id == all_balancers[i].id)
3062*d83cc019SAndroid Build Coastguard Worker 			return &all_balancers[i];
3063*d83cc019SAndroid Build Coastguard Worker 	}
3064*d83cc019SAndroid Build Coastguard Worker 
3065*d83cc019SAndroid Build Coastguard Worker 	return NULL;
3066*d83cc019SAndroid Build Coastguard Worker }
3067*d83cc019SAndroid Build Coastguard Worker 
init_clocks(void)3068*d83cc019SAndroid Build Coastguard Worker static void init_clocks(void)
3069*d83cc019SAndroid Build Coastguard Worker {
3070*d83cc019SAndroid Build Coastguard Worker 	struct timespec t_start, t_end;
3071*d83cc019SAndroid Build Coastguard Worker 	uint32_t rcs_start, rcs_end;
3072*d83cc019SAndroid Build Coastguard Worker 	double overhead, t;
3073*d83cc019SAndroid Build Coastguard Worker 
3074*d83cc019SAndroid Build Coastguard Worker 	intel_register_access_init(intel_get_pci_device(), false, fd);
3075*d83cc019SAndroid Build Coastguard Worker 
3076*d83cc019SAndroid Build Coastguard Worker 	if (verbose <= 1)
3077*d83cc019SAndroid Build Coastguard Worker 		return;
3078*d83cc019SAndroid Build Coastguard Worker 
3079*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_start);
3080*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < 100; i++)
3081*d83cc019SAndroid Build Coastguard Worker 		rcs_start = *REG(RCS_TIMESTAMP);
3082*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_end);
3083*d83cc019SAndroid Build Coastguard Worker 	overhead = 2 * elapsed(&t_start, &t_end) / 100;
3084*d83cc019SAndroid Build Coastguard Worker 
3085*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_start);
3086*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < 100; i++)
3087*d83cc019SAndroid Build Coastguard Worker 		clock_gettime(CLOCK_MONOTONIC, &t_end);
3088*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_end);
3089*d83cc019SAndroid Build Coastguard Worker 	overhead += elapsed(&t_start, &t_end) / 100;
3090*d83cc019SAndroid Build Coastguard Worker 
3091*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_start);
3092*d83cc019SAndroid Build Coastguard Worker 	rcs_start = *REG(RCS_TIMESTAMP);
3093*d83cc019SAndroid Build Coastguard Worker 	usleep(100);
3094*d83cc019SAndroid Build Coastguard Worker 	rcs_end = *REG(RCS_TIMESTAMP);
3095*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_end);
3096*d83cc019SAndroid Build Coastguard Worker 
3097*d83cc019SAndroid Build Coastguard Worker 	t = elapsed(&t_start, &t_end) - overhead;
3098*d83cc019SAndroid Build Coastguard Worker 	printf("%d cycles in %.1fus, i.e. 1024 cycles takes %1.fus\n",
3099*d83cc019SAndroid Build Coastguard Worker 	       rcs_end - rcs_start, 1e6*t, 1024e6 * t / (rcs_end - rcs_start));
3100*d83cc019SAndroid Build Coastguard Worker }
3101*d83cc019SAndroid Build Coastguard Worker 
main(int argc,char ** argv)3102*d83cc019SAndroid Build Coastguard Worker int main(int argc, char **argv)
3103*d83cc019SAndroid Build Coastguard Worker {
3104*d83cc019SAndroid Build Coastguard Worker 	unsigned int repeat = 1;
3105*d83cc019SAndroid Build Coastguard Worker 	unsigned int clients = 1;
3106*d83cc019SAndroid Build Coastguard Worker 	unsigned int flags = 0;
3107*d83cc019SAndroid Build Coastguard Worker 	struct timespec t_start, t_end;
3108*d83cc019SAndroid Build Coastguard Worker 	struct workload **w, **wrk = NULL;
3109*d83cc019SAndroid Build Coastguard Worker 	struct workload *app_w = NULL;
3110*d83cc019SAndroid Build Coastguard Worker 	unsigned int nr_w_args = 0;
3111*d83cc019SAndroid Build Coastguard Worker 	int master_workload = -1;
3112*d83cc019SAndroid Build Coastguard Worker 	char *append_workload_arg = NULL;
3113*d83cc019SAndroid Build Coastguard Worker 	struct w_arg *w_args = NULL;
3114*d83cc019SAndroid Build Coastguard Worker 	unsigned int tolerance_pct = 1;
3115*d83cc019SAndroid Build Coastguard Worker 	const struct workload_balancer *balancer = NULL;
3116*d83cc019SAndroid Build Coastguard Worker 	char *endptr = NULL;
3117*d83cc019SAndroid Build Coastguard Worker 	int prio = 0;
3118*d83cc019SAndroid Build Coastguard Worker 	double t;
3119*d83cc019SAndroid Build Coastguard Worker 	int i, c;
3120*d83cc019SAndroid Build Coastguard Worker 
3121*d83cc019SAndroid Build Coastguard Worker 	/*
3122*d83cc019SAndroid Build Coastguard Worker 	 * Open the device via the low-level API so we can do the GPU quiesce
3123*d83cc019SAndroid Build Coastguard Worker 	 * manually as close as possible in time to the start of the workload.
3124*d83cc019SAndroid Build Coastguard Worker 	 * This minimizes the gap in engine utilization tracking when observed
3125*d83cc019SAndroid Build Coastguard Worker 	 * via external tools like trace.pl.
3126*d83cc019SAndroid Build Coastguard Worker 	 */
3127*d83cc019SAndroid Build Coastguard Worker 	fd = __drm_open_driver(DRIVER_INTEL);
3128*d83cc019SAndroid Build Coastguard Worker 	igt_require(fd);
3129*d83cc019SAndroid Build Coastguard Worker 
3130*d83cc019SAndroid Build Coastguard Worker 	init_clocks();
3131*d83cc019SAndroid Build Coastguard Worker 
3132*d83cc019SAndroid Build Coastguard Worker 	master_prng = time(NULL);
3133*d83cc019SAndroid Build Coastguard Worker 
3134*d83cc019SAndroid Build Coastguard Worker 	while ((c = getopt(argc, argv,
3135*d83cc019SAndroid Build Coastguard Worker 			   "hqv2RsSHxGdc:n:r:w:W:a:t:b:p:I:")) != -1) {
3136*d83cc019SAndroid Build Coastguard Worker 		switch (c) {
3137*d83cc019SAndroid Build Coastguard Worker 		case 'W':
3138*d83cc019SAndroid Build Coastguard Worker 			if (master_workload >= 0) {
3139*d83cc019SAndroid Build Coastguard Worker 				wsim_err("Only one master workload can be given!\n");
3140*d83cc019SAndroid Build Coastguard Worker 				return 1;
3141*d83cc019SAndroid Build Coastguard Worker 			}
3142*d83cc019SAndroid Build Coastguard Worker 			master_workload = nr_w_args;
3143*d83cc019SAndroid Build Coastguard Worker 			/* Fall through */
3144*d83cc019SAndroid Build Coastguard Worker 		case 'w':
3145*d83cc019SAndroid Build Coastguard Worker 			w_args = add_workload_arg(w_args, ++nr_w_args, optarg,
3146*d83cc019SAndroid Build Coastguard Worker 						  prio, flags & SSEU);
3147*d83cc019SAndroid Build Coastguard Worker 			break;
3148*d83cc019SAndroid Build Coastguard Worker 		case 'p':
3149*d83cc019SAndroid Build Coastguard Worker 			prio = atoi(optarg);
3150*d83cc019SAndroid Build Coastguard Worker 			break;
3151*d83cc019SAndroid Build Coastguard Worker 		case 'a':
3152*d83cc019SAndroid Build Coastguard Worker 			if (append_workload_arg) {
3153*d83cc019SAndroid Build Coastguard Worker 				wsim_err("Only one append workload can be given!\n");
3154*d83cc019SAndroid Build Coastguard Worker 				return 1;
3155*d83cc019SAndroid Build Coastguard Worker 			}
3156*d83cc019SAndroid Build Coastguard Worker 			append_workload_arg = optarg;
3157*d83cc019SAndroid Build Coastguard Worker 			break;
3158*d83cc019SAndroid Build Coastguard Worker 		case 'c':
3159*d83cc019SAndroid Build Coastguard Worker 			clients = strtol(optarg, NULL, 0);
3160*d83cc019SAndroid Build Coastguard Worker 			break;
3161*d83cc019SAndroid Build Coastguard Worker 		case 't':
3162*d83cc019SAndroid Build Coastguard Worker 			tolerance_pct = strtol(optarg, NULL, 0);
3163*d83cc019SAndroid Build Coastguard Worker 			break;
3164*d83cc019SAndroid Build Coastguard Worker 		case 'n':
3165*d83cc019SAndroid Build Coastguard Worker 			nop_calibration = strtol(optarg, NULL, 0);
3166*d83cc019SAndroid Build Coastguard Worker 			break;
3167*d83cc019SAndroid Build Coastguard Worker 		case 'r':
3168*d83cc019SAndroid Build Coastguard Worker 			repeat = strtol(optarg, NULL, 0);
3169*d83cc019SAndroid Build Coastguard Worker 			break;
3170*d83cc019SAndroid Build Coastguard Worker 		case 'q':
3171*d83cc019SAndroid Build Coastguard Worker 			verbose = 0;
3172*d83cc019SAndroid Build Coastguard Worker 			break;
3173*d83cc019SAndroid Build Coastguard Worker 		case 'v':
3174*d83cc019SAndroid Build Coastguard Worker 			verbose++;
3175*d83cc019SAndroid Build Coastguard Worker 			break;
3176*d83cc019SAndroid Build Coastguard Worker 		case 'x':
3177*d83cc019SAndroid Build Coastguard Worker 			flags |= SWAPVCS;
3178*d83cc019SAndroid Build Coastguard Worker 			break;
3179*d83cc019SAndroid Build Coastguard Worker 		case '2':
3180*d83cc019SAndroid Build Coastguard Worker 			flags |= VCS2REMAP;
3181*d83cc019SAndroid Build Coastguard Worker 			break;
3182*d83cc019SAndroid Build Coastguard Worker 		case 'R':
3183*d83cc019SAndroid Build Coastguard Worker 			flags |= INITVCSRR;
3184*d83cc019SAndroid Build Coastguard Worker 			break;
3185*d83cc019SAndroid Build Coastguard Worker 		case 'S':
3186*d83cc019SAndroid Build Coastguard Worker 			flags |= SYNCEDCLIENTS;
3187*d83cc019SAndroid Build Coastguard Worker 			break;
3188*d83cc019SAndroid Build Coastguard Worker 		case 's':
3189*d83cc019SAndroid Build Coastguard Worker 			flags ^= SSEU;
3190*d83cc019SAndroid Build Coastguard Worker 			break;
3191*d83cc019SAndroid Build Coastguard Worker 		case 'H':
3192*d83cc019SAndroid Build Coastguard Worker 			flags |= HEARTBEAT;
3193*d83cc019SAndroid Build Coastguard Worker 			break;
3194*d83cc019SAndroid Build Coastguard Worker 		case 'G':
3195*d83cc019SAndroid Build Coastguard Worker 			flags |= GLOBAL_BALANCE;
3196*d83cc019SAndroid Build Coastguard Worker 			break;
3197*d83cc019SAndroid Build Coastguard Worker 		case 'd':
3198*d83cc019SAndroid Build Coastguard Worker 			flags |= DEPSYNC;
3199*d83cc019SAndroid Build Coastguard Worker 			break;
3200*d83cc019SAndroid Build Coastguard Worker 		case 'b':
3201*d83cc019SAndroid Build Coastguard Worker 			i = find_balancer_by_name(optarg);
3202*d83cc019SAndroid Build Coastguard Worker 			if (i < 0) {
3203*d83cc019SAndroid Build Coastguard Worker 				i = strtol(optarg, &endptr, 0);
3204*d83cc019SAndroid Build Coastguard Worker 				if (endptr && *endptr)
3205*d83cc019SAndroid Build Coastguard Worker 					i = -1;
3206*d83cc019SAndroid Build Coastguard Worker 			}
3207*d83cc019SAndroid Build Coastguard Worker 
3208*d83cc019SAndroid Build Coastguard Worker 			if (i >= 0) {
3209*d83cc019SAndroid Build Coastguard Worker 				balancer = find_balancer_by_id(i);
3210*d83cc019SAndroid Build Coastguard Worker 				if (balancer) {
3211*d83cc019SAndroid Build Coastguard Worker 					igt_assert(intel_gen(intel_get_drm_devid(fd)) >= balancer->min_gen);
3212*d83cc019SAndroid Build Coastguard Worker 					flags |= BALANCE | balancer->flags;
3213*d83cc019SAndroid Build Coastguard Worker 				}
3214*d83cc019SAndroid Build Coastguard Worker 			}
3215*d83cc019SAndroid Build Coastguard Worker 
3216*d83cc019SAndroid Build Coastguard Worker 			if (!balancer) {
3217*d83cc019SAndroid Build Coastguard Worker 				wsim_err("Unknown balancing mode '%s'!\n",
3218*d83cc019SAndroid Build Coastguard Worker 					 optarg);
3219*d83cc019SAndroid Build Coastguard Worker 				return 1;
3220*d83cc019SAndroid Build Coastguard Worker 			}
3221*d83cc019SAndroid Build Coastguard Worker 			break;
3222*d83cc019SAndroid Build Coastguard Worker 		case 'I':
3223*d83cc019SAndroid Build Coastguard Worker 			master_prng = strtol(optarg, NULL, 0);
3224*d83cc019SAndroid Build Coastguard Worker 			break;
3225*d83cc019SAndroid Build Coastguard Worker 		case 'h':
3226*d83cc019SAndroid Build Coastguard Worker 			print_help();
3227*d83cc019SAndroid Build Coastguard Worker 			return 0;
3228*d83cc019SAndroid Build Coastguard Worker 		default:
3229*d83cc019SAndroid Build Coastguard Worker 			return 1;
3230*d83cc019SAndroid Build Coastguard Worker 		}
3231*d83cc019SAndroid Build Coastguard Worker 	}
3232*d83cc019SAndroid Build Coastguard Worker 
3233*d83cc019SAndroid Build Coastguard Worker 	if ((flags & HEARTBEAT) && !(flags & SEQNO)) {
3234*d83cc019SAndroid Build Coastguard Worker 		wsim_err("Heartbeat needs a seqno based balancer!\n");
3235*d83cc019SAndroid Build Coastguard Worker 		return 1;
3236*d83cc019SAndroid Build Coastguard Worker 	}
3237*d83cc019SAndroid Build Coastguard Worker 
3238*d83cc019SAndroid Build Coastguard Worker 	if ((flags & VCS2REMAP) && (flags & I915)) {
3239*d83cc019SAndroid Build Coastguard Worker 		wsim_err("VCS remapping not supported with i915 balancing!\n");
3240*d83cc019SAndroid Build Coastguard Worker 		return 1;
3241*d83cc019SAndroid Build Coastguard Worker 	}
3242*d83cc019SAndroid Build Coastguard Worker 
3243*d83cc019SAndroid Build Coastguard Worker 	if (!nop_calibration) {
3244*d83cc019SAndroid Build Coastguard Worker 		if (verbose > 1)
3245*d83cc019SAndroid Build Coastguard Worker 			printf("Calibrating nop delay with %u%% tolerance...\n",
3246*d83cc019SAndroid Build Coastguard Worker 				tolerance_pct);
3247*d83cc019SAndroid Build Coastguard Worker 		nop_calibration = calibrate_nop(tolerance_pct);
3248*d83cc019SAndroid Build Coastguard Worker 		if (verbose)
3249*d83cc019SAndroid Build Coastguard Worker 			printf("Nop calibration for %uus delay is %lu.\n",
3250*d83cc019SAndroid Build Coastguard Worker 			       nop_calibration_us, nop_calibration);
3251*d83cc019SAndroid Build Coastguard Worker 
3252*d83cc019SAndroid Build Coastguard Worker 		return 0;
3253*d83cc019SAndroid Build Coastguard Worker 	}
3254*d83cc019SAndroid Build Coastguard Worker 
3255*d83cc019SAndroid Build Coastguard Worker 	if (!nr_w_args) {
3256*d83cc019SAndroid Build Coastguard Worker 		wsim_err("No workload descriptor(s)!\n");
3257*d83cc019SAndroid Build Coastguard Worker 		return 1;
3258*d83cc019SAndroid Build Coastguard Worker 	}
3259*d83cc019SAndroid Build Coastguard Worker 
3260*d83cc019SAndroid Build Coastguard Worker 	if (nr_w_args > 1 && clients > 1) {
3261*d83cc019SAndroid Build Coastguard Worker 		wsim_err("Cloned clients cannot be combined with multiple workloads!\n");
3262*d83cc019SAndroid Build Coastguard Worker 		return 1;
3263*d83cc019SAndroid Build Coastguard Worker 	}
3264*d83cc019SAndroid Build Coastguard Worker 
3265*d83cc019SAndroid Build Coastguard Worker 	if ((flags & GLOBAL_BALANCE) && !balancer) {
3266*d83cc019SAndroid Build Coastguard Worker 		wsim_err("Balancer not specified in global balancing mode!\n");
3267*d83cc019SAndroid Build Coastguard Worker 		return 1;
3268*d83cc019SAndroid Build Coastguard Worker 	}
3269*d83cc019SAndroid Build Coastguard Worker 
3270*d83cc019SAndroid Build Coastguard Worker 	if (append_workload_arg) {
3271*d83cc019SAndroid Build Coastguard Worker 		append_workload_arg = load_workload_descriptor(append_workload_arg);
3272*d83cc019SAndroid Build Coastguard Worker 		if (!append_workload_arg) {
3273*d83cc019SAndroid Build Coastguard Worker 			wsim_err("Failed to load append workload descriptor!\n");
3274*d83cc019SAndroid Build Coastguard Worker 			return 1;
3275*d83cc019SAndroid Build Coastguard Worker 		}
3276*d83cc019SAndroid Build Coastguard Worker 	}
3277*d83cc019SAndroid Build Coastguard Worker 
3278*d83cc019SAndroid Build Coastguard Worker 	if (append_workload_arg) {
3279*d83cc019SAndroid Build Coastguard Worker 		struct w_arg arg = { NULL, append_workload_arg, 0 };
3280*d83cc019SAndroid Build Coastguard Worker 		app_w = parse_workload(&arg, flags, NULL);
3281*d83cc019SAndroid Build Coastguard Worker 		if (!app_w) {
3282*d83cc019SAndroid Build Coastguard Worker 			wsim_err("Failed to parse append workload!\n");
3283*d83cc019SAndroid Build Coastguard Worker 			return 1;
3284*d83cc019SAndroid Build Coastguard Worker 		}
3285*d83cc019SAndroid Build Coastguard Worker 	}
3286*d83cc019SAndroid Build Coastguard Worker 
3287*d83cc019SAndroid Build Coastguard Worker 	wrk = calloc(nr_w_args, sizeof(*wrk));
3288*d83cc019SAndroid Build Coastguard Worker 	igt_assert(wrk);
3289*d83cc019SAndroid Build Coastguard Worker 
3290*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < nr_w_args; i++) {
3291*d83cc019SAndroid Build Coastguard Worker 		w_args[i].desc = load_workload_descriptor(w_args[i].filename);
3292*d83cc019SAndroid Build Coastguard Worker 
3293*d83cc019SAndroid Build Coastguard Worker 		if (!w_args[i].desc) {
3294*d83cc019SAndroid Build Coastguard Worker 			wsim_err("Failed to load workload descriptor %u!\n", i);
3295*d83cc019SAndroid Build Coastguard Worker 			return 1;
3296*d83cc019SAndroid Build Coastguard Worker 		}
3297*d83cc019SAndroid Build Coastguard Worker 
3298*d83cc019SAndroid Build Coastguard Worker 		wrk[i] = parse_workload(&w_args[i], flags, app_w);
3299*d83cc019SAndroid Build Coastguard Worker 		if (!wrk[i]) {
3300*d83cc019SAndroid Build Coastguard Worker 			wsim_err("Failed to parse workload %u!\n", i);
3301*d83cc019SAndroid Build Coastguard Worker 			return 1;
3302*d83cc019SAndroid Build Coastguard Worker 		}
3303*d83cc019SAndroid Build Coastguard Worker 	}
3304*d83cc019SAndroid Build Coastguard Worker 
3305*d83cc019SAndroid Build Coastguard Worker 	if (nr_w_args > 1)
3306*d83cc019SAndroid Build Coastguard Worker 		clients = nr_w_args;
3307*d83cc019SAndroid Build Coastguard Worker 
3308*d83cc019SAndroid Build Coastguard Worker 	if (verbose > 1) {
3309*d83cc019SAndroid Build Coastguard Worker 		printf("Random seed is %u.\n", master_prng);
3310*d83cc019SAndroid Build Coastguard Worker 		printf("Using %lu nop calibration for %uus delay.\n",
3311*d83cc019SAndroid Build Coastguard Worker 		       nop_calibration, nop_calibration_us);
3312*d83cc019SAndroid Build Coastguard Worker 		printf("%u client%s.\n", clients, clients > 1 ? "s" : "");
3313*d83cc019SAndroid Build Coastguard Worker 		if (flags & SWAPVCS)
3314*d83cc019SAndroid Build Coastguard Worker 			printf("Swapping VCS rings between clients.\n");
3315*d83cc019SAndroid Build Coastguard Worker 		if (flags & GLOBAL_BALANCE) {
3316*d83cc019SAndroid Build Coastguard Worker 			if (flags & I915) {
3317*d83cc019SAndroid Build Coastguard Worker 				printf("Ignoring global balancing with i915!\n");
3318*d83cc019SAndroid Build Coastguard Worker 				flags &= ~GLOBAL_BALANCE;
3319*d83cc019SAndroid Build Coastguard Worker 			} else {
3320*d83cc019SAndroid Build Coastguard Worker 				printf("Using %s balancer in global mode.\n",
3321*d83cc019SAndroid Build Coastguard Worker 				       balancer->name);
3322*d83cc019SAndroid Build Coastguard Worker 			}
3323*d83cc019SAndroid Build Coastguard Worker 		} else if (balancer) {
3324*d83cc019SAndroid Build Coastguard Worker 			printf("Using %s balancer.\n", balancer->name);
3325*d83cc019SAndroid Build Coastguard Worker 		}
3326*d83cc019SAndroid Build Coastguard Worker 	}
3327*d83cc019SAndroid Build Coastguard Worker 
3328*d83cc019SAndroid Build Coastguard Worker 	srand(master_prng);
3329*d83cc019SAndroid Build Coastguard Worker 	master_prng = rand();
3330*d83cc019SAndroid Build Coastguard Worker 
3331*d83cc019SAndroid Build Coastguard Worker 	if (master_workload >= 0 && clients == 1)
3332*d83cc019SAndroid Build Coastguard Worker 		master_workload = -1;
3333*d83cc019SAndroid Build Coastguard Worker 
3334*d83cc019SAndroid Build Coastguard Worker 	w = calloc(clients, sizeof(struct workload *));
3335*d83cc019SAndroid Build Coastguard Worker 	igt_assert(w);
3336*d83cc019SAndroid Build Coastguard Worker 
3337*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < clients; i++) {
3338*d83cc019SAndroid Build Coastguard Worker 		unsigned int flags_ = flags;
3339*d83cc019SAndroid Build Coastguard Worker 
3340*d83cc019SAndroid Build Coastguard Worker 		w[i] = clone_workload(wrk[nr_w_args > 1 ? i : 0]);
3341*d83cc019SAndroid Build Coastguard Worker 
3342*d83cc019SAndroid Build Coastguard Worker 		if (flags & SWAPVCS && i & 1)
3343*d83cc019SAndroid Build Coastguard Worker 			flags_ &= ~SWAPVCS;
3344*d83cc019SAndroid Build Coastguard Worker 
3345*d83cc019SAndroid Build Coastguard Worker 		if ((flags & GLOBAL_BALANCE) && !(flags & I915)) {
3346*d83cc019SAndroid Build Coastguard Worker 			w[i]->balancer = &global_balancer;
3347*d83cc019SAndroid Build Coastguard Worker 			w[i]->global_wrk = w[0];
3348*d83cc019SAndroid Build Coastguard Worker 			w[i]->global_balancer = balancer;
3349*d83cc019SAndroid Build Coastguard Worker 		} else {
3350*d83cc019SAndroid Build Coastguard Worker 			w[i]->balancer = balancer;
3351*d83cc019SAndroid Build Coastguard Worker 		}
3352*d83cc019SAndroid Build Coastguard Worker 
3353*d83cc019SAndroid Build Coastguard Worker 		w[i]->flags = flags;
3354*d83cc019SAndroid Build Coastguard Worker 		w[i]->repeat = repeat;
3355*d83cc019SAndroid Build Coastguard Worker 		w[i]->background = master_workload >= 0 && i != master_workload;
3356*d83cc019SAndroid Build Coastguard Worker 		w[i]->print_stats = verbose > 1 ||
3357*d83cc019SAndroid Build Coastguard Worker 				    (verbose > 0 && master_workload == i);
3358*d83cc019SAndroid Build Coastguard Worker 
3359*d83cc019SAndroid Build Coastguard Worker 		if (prepare_workload(i, w[i], flags_)) {
3360*d83cc019SAndroid Build Coastguard Worker 			wsim_err("Failed to prepare workload %u!\n", i);
3361*d83cc019SAndroid Build Coastguard Worker 			return 1;
3362*d83cc019SAndroid Build Coastguard Worker 		}
3363*d83cc019SAndroid Build Coastguard Worker 
3364*d83cc019SAndroid Build Coastguard Worker 
3365*d83cc019SAndroid Build Coastguard Worker 		if (balancer && balancer->init) {
3366*d83cc019SAndroid Build Coastguard Worker 			int ret = balancer->init(balancer, w[i]);
3367*d83cc019SAndroid Build Coastguard Worker 			if (ret) {
3368*d83cc019SAndroid Build Coastguard Worker 				wsim_err("Failed to initialize balancing! (%u=%d)\n",
3369*d83cc019SAndroid Build Coastguard Worker 					 i, ret);
3370*d83cc019SAndroid Build Coastguard Worker 				return 1;
3371*d83cc019SAndroid Build Coastguard Worker 			}
3372*d83cc019SAndroid Build Coastguard Worker 		}
3373*d83cc019SAndroid Build Coastguard Worker 	}
3374*d83cc019SAndroid Build Coastguard Worker 
3375*d83cc019SAndroid Build Coastguard Worker 	gem_quiescent_gpu(fd);
3376*d83cc019SAndroid Build Coastguard Worker 
3377*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_start);
3378*d83cc019SAndroid Build Coastguard Worker 
3379*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < clients; i++) {
3380*d83cc019SAndroid Build Coastguard Worker 		int ret;
3381*d83cc019SAndroid Build Coastguard Worker 
3382*d83cc019SAndroid Build Coastguard Worker 		ret = pthread_create(&w[i]->thread, NULL, run_workload, w[i]);
3383*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(ret, 0);
3384*d83cc019SAndroid Build Coastguard Worker 	}
3385*d83cc019SAndroid Build Coastguard Worker 
3386*d83cc019SAndroid Build Coastguard Worker 	if (master_workload >= 0) {
3387*d83cc019SAndroid Build Coastguard Worker 		int ret = pthread_join(w[master_workload]->thread, NULL);
3388*d83cc019SAndroid Build Coastguard Worker 
3389*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ret == 0);
3390*d83cc019SAndroid Build Coastguard Worker 
3391*d83cc019SAndroid Build Coastguard Worker 		for (i = 0; i < clients; i++)
3392*d83cc019SAndroid Build Coastguard Worker 			w[i]->run = false;
3393*d83cc019SAndroid Build Coastguard Worker 	}
3394*d83cc019SAndroid Build Coastguard Worker 
3395*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < clients; i++) {
3396*d83cc019SAndroid Build Coastguard Worker 		if (master_workload != i) {
3397*d83cc019SAndroid Build Coastguard Worker 			int ret = pthread_join(w[i]->thread, NULL);
3398*d83cc019SAndroid Build Coastguard Worker 			igt_assert(ret == 0);
3399*d83cc019SAndroid Build Coastguard Worker 		}
3400*d83cc019SAndroid Build Coastguard Worker 	}
3401*d83cc019SAndroid Build Coastguard Worker 
3402*d83cc019SAndroid Build Coastguard Worker 	clock_gettime(CLOCK_MONOTONIC, &t_end);
3403*d83cc019SAndroid Build Coastguard Worker 
3404*d83cc019SAndroid Build Coastguard Worker 	t = elapsed(&t_start, &t_end);
3405*d83cc019SAndroid Build Coastguard Worker 	if (verbose)
3406*d83cc019SAndroid Build Coastguard Worker 		printf("%.3fs elapsed (%.3f workloads/s)\n",
3407*d83cc019SAndroid Build Coastguard Worker 		       t, clients * repeat / t);
3408*d83cc019SAndroid Build Coastguard Worker 
3409*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < clients; i++)
3410*d83cc019SAndroid Build Coastguard Worker 		fini_workload(w[i]);
3411*d83cc019SAndroid Build Coastguard Worker 	free(w);
3412*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < nr_w_args; i++)
3413*d83cc019SAndroid Build Coastguard Worker 		fini_workload(wrk[i]);
3414*d83cc019SAndroid Build Coastguard Worker 	free(w_args);
3415*d83cc019SAndroid Build Coastguard Worker 
3416*d83cc019SAndroid Build Coastguard Worker 	return 0;
3417*d83cc019SAndroid Build Coastguard Worker }
3418