blob: 22a5b704a77d942988f64ba85a2ff58cd8d8c89f [file] [log] [blame]
Chris Wilson721d8742016-10-27 11:32:47 +01001/*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include <sys/poll.h>
Chris Wilsona19ef052017-07-31 14:15:59 +010025#include <sys/ioctl.h>
Chris Wilson721d8742016-10-27 11:32:47 +010026
27#include "igt.h"
28#include "igt_vgem.h"
29
Chris Wilson49f44c72016-11-14 21:24:52 +000030#define LOCAL_PARAM_HAS_SCHEDULER 41
Chris Wilsonaf0e1c52017-02-21 18:25:58 +000031#define LOCAL_CONTEXT_PARAM_PRIORITY 6
Chris Wilson721d8742016-10-27 11:32:47 +010032
33#define LO 0
34#define HI 1
35#define NOISE 2
36
37#define MAX_PRIO 1023
38
39#define BUSY_QLEN 8
40
41IGT_TEST_DESCRIPTION("Check that we can control the order of execution");
42
Chris Wilsonaf0e1c52017-02-21 18:25:58 +000043static int __ctx_set_priority(int fd, uint32_t ctx, int prio)
Chris Wilson721d8742016-10-27 11:32:47 +010044{
45 struct local_i915_gem_context_param param;
46
47 memset(&param, 0, sizeof(param));
48 param.context = ctx;
49 param.size = 0;
50 param.param = LOCAL_CONTEXT_PARAM_PRIORITY;
51 param.value = prio;
52
Chris Wilsonaf0e1c52017-02-21 18:25:58 +000053 return __gem_context_set_param(fd, &param);
54}
55
56static void ctx_set_priority(int fd, uint32_t ctx, int prio)
57{
58 igt_assert_eq(__ctx_set_priority(fd, ctx, prio), 0);
59}
60
61static void ctx_has_priority(int fd)
62{
63 igt_require(__ctx_set_priority(fd, 0, MAX_PRIO) == 0);
Chris Wilson721d8742016-10-27 11:32:47 +010064}
65
66static void store_dword(int fd, uint32_t ctx, unsigned ring,
67 uint32_t target, uint32_t offset, uint32_t value,
68 uint32_t cork, unsigned write_domain)
69{
70 const int gen = intel_gen(intel_get_drm_devid(fd));
71 struct drm_i915_gem_exec_object2 obj[3];
72 struct drm_i915_gem_relocation_entry reloc;
73 struct drm_i915_gem_execbuffer2 execbuf;
74 uint32_t batch[16];
75 int i;
76
77 memset(&execbuf, 0, sizeof(execbuf));
Chris Wilson4de67b22017-01-02 11:05:21 +000078 execbuf.buffers_ptr = to_user_pointer(obj + !cork);
Chris Wilson721d8742016-10-27 11:32:47 +010079 execbuf.buffer_count = 2 + !!cork;
80 execbuf.flags = ring;
81 if (gen < 6)
82 execbuf.flags |= I915_EXEC_SECURE;
83 execbuf.rsvd1 = ctx;
84
85 memset(obj, 0, sizeof(obj));
86 obj[0].handle = cork;
87 obj[1].handle = target;
88 obj[2].handle = gem_create(fd, 4096);
89
90 memset(&reloc, 0, sizeof(reloc));
91 reloc.target_handle = obj[1].handle;
92 reloc.presumed_offset = 0;
93 reloc.offset = sizeof(uint32_t);
94 reloc.delta = offset;
95 reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
96 reloc.write_domain = write_domain;
Chris Wilson4de67b22017-01-02 11:05:21 +000097 obj[2].relocs_ptr = to_user_pointer(&reloc);
Chris Wilson721d8742016-10-27 11:32:47 +010098 obj[2].relocation_count = 1;
99
100 i = 0;
101 batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0);
102 if (gen >= 8) {
103 batch[++i] = offset;
104 batch[++i] = 0;
105 } else if (gen >= 4) {
106 batch[++i] = 0;
107 batch[++i] = offset;
108 reloc.offset += sizeof(uint32_t);
109 } else {
110 batch[i]--;
111 batch[++i] = offset;
112 }
113 batch[++i] = value;
114 batch[++i] = MI_BATCH_BUFFER_END;
115 gem_write(fd, obj[2].handle, 0, batch, sizeof(batch));
116 gem_execbuf(fd, &execbuf);
117 gem_close(fd, obj[2].handle);
118}
119
120static uint32_t *make_busy(int fd, uint32_t target, unsigned ring)
121{
122 const int gen = intel_gen(intel_get_drm_devid(fd));
123 struct drm_i915_gem_exec_object2 obj[2];
124 struct drm_i915_gem_relocation_entry reloc[2];
125 struct drm_i915_gem_execbuffer2 execbuf;
126 uint32_t *batch;
127 int i;
128
129 memset(&execbuf, 0, sizeof(execbuf));
Chris Wilson4de67b22017-01-02 11:05:21 +0000130 execbuf.buffers_ptr = to_user_pointer(obj + !target);
Chris Wilson721d8742016-10-27 11:32:47 +0100131 execbuf.buffer_count = 1 + !!target;
132
133 memset(obj, 0, sizeof(obj));
134 obj[0].handle = target;
135 obj[1].handle = gem_create(fd, 4096);
136 batch = gem_mmap__wc(fd, obj[1].handle, 0, 4096, PROT_WRITE);
137 gem_set_domain(fd, obj[1].handle,
138 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
139
Chris Wilson4de67b22017-01-02 11:05:21 +0000140 obj[1].relocs_ptr = to_user_pointer(reloc);
Chris Wilson721d8742016-10-27 11:32:47 +0100141 obj[1].relocation_count = 1 + !!target;
142 memset(reloc, 0, sizeof(reloc));
143
144 reloc[0].target_handle = obj[1].handle; /* recurse */
145 reloc[0].presumed_offset = 0;
146 reloc[0].offset = sizeof(uint32_t);
147 reloc[0].delta = 0;
148 reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND;
149 reloc[0].write_domain = 0;
150
151 reloc[1].target_handle = target;
152 reloc[1].presumed_offset = 0;
153 reloc[1].offset = 1024;
154 reloc[1].delta = 0;
155 reloc[1].read_domains = I915_GEM_DOMAIN_COMMAND;
156 reloc[1].write_domain = 0;
157
158 i = 0;
159 batch[i] = MI_BATCH_BUFFER_START;
160 if (gen >= 8) {
161 batch[i] |= 1 << 8 | 1;
162 batch[++i] = 0;
163 batch[++i] = 0;
164 } else if (gen >= 6) {
165 batch[i] |= 1 << 8;
166 batch[++i] = 0;
167 } else {
168 batch[i] |= 2 << 6;
169 batch[++i] = 0;
170 if (gen < 4) {
171 batch[i] |= 1;
172 reloc[0].delta = 1;
173 }
174 }
175 i++;
176
177 if (ring != -1) {
178 execbuf.flags = ring;
179 for (int n = 0; n < BUSY_QLEN; n++)
180 gem_execbuf(fd, &execbuf);
181 } else {
182 for_each_engine(fd, ring) {
183 if (ring == 0)
184 continue;
185
186 execbuf.flags = ring;
187 for (int n = 0; n < BUSY_QLEN; n++)
188 gem_execbuf(fd, &execbuf);
189 igt_assert(execbuf.flags == ring);
190 }
191 }
192
193 if (target) {
194 execbuf.flags = 0;
195 reloc[1].write_domain = I915_GEM_DOMAIN_COMMAND;
196 gem_execbuf(fd, &execbuf);
197 }
198
199 gem_close(fd, obj[1].handle);
200
201 return batch;
202}
203
204static void finish_busy(uint32_t *busy)
205{
206 *busy = MI_BATCH_BUFFER_END;
207 munmap(busy, 4096);
208}
209
210struct cork {
211 int device;
212 uint32_t handle;
213 uint32_t fence;
214};
215
216static void plug(int fd, struct cork *c)
217{
218 struct vgem_bo bo;
219 int dmabuf;
220
221 c->device = drm_open_driver(DRIVER_VGEM);
222
223 bo.width = bo.height = 1;
224 bo.bpp = 4;
225 vgem_create(c->device, &bo);
226 c->fence = vgem_fence_attach(c->device, &bo, VGEM_FENCE_WRITE);
227
228 dmabuf = prime_handle_to_fd(c->device, bo.handle);
229 c->handle = prime_fd_to_handle(fd, dmabuf);
230 close(dmabuf);
231}
232
233static void unplug(struct cork *c)
234{
235 vgem_fence_signal(c->device, c->fence);
236 close(c->device);
237}
238
239static void fifo(int fd, unsigned ring)
240{
241 struct cork cork;
242 uint32_t *busy;
243 uint32_t scratch;
244 uint32_t *ptr;
245
246 scratch = gem_create(fd, 4096);
247
248 busy = make_busy(fd, scratch, ring);
249 plug(fd, &cork);
250
251 /* Same priority, same timeline, final result will be the second eb */
252 store_dword(fd, 0, ring, scratch, 0, 1, cork.handle, 0);
253 store_dword(fd, 0, ring, scratch, 0, 2, cork.handle, 0);
254
255 unplug(&cork); /* only now submit our batches */
256 igt_debugfs_dump(fd, "i915_engine_info");
257 finish_busy(busy);
258
259 ptr = gem_mmap__gtt(fd, scratch, 4096, PROT_READ);
260 gem_set_domain(fd, scratch, /* no write hazard lies! */
261 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
262 gem_close(fd, scratch);
263
264 igt_assert_eq_u32(ptr[0], 2);
265 munmap(ptr, 4096);
266}
267
268static void reorder(int fd, unsigned ring, unsigned flags)
269#define EQUAL 1
270{
271 struct cork cork;
272 uint32_t scratch;
273 uint32_t *busy;
274 uint32_t *ptr;
275 uint32_t ctx[2];
276
277 ctx[LO] = gem_context_create(fd);
278 ctx_set_priority(fd, ctx[LO], -MAX_PRIO);
279
280 ctx[HI] = gem_context_create(fd);
281 ctx_set_priority(fd, ctx[HI], flags & EQUAL ? -MAX_PRIO : 0);
282
283 scratch = gem_create(fd, 4096);
284
285 busy = make_busy(fd, scratch, ring);
286 plug(fd, &cork);
287
288 /* We expect the high priority context to be executed first, and
289 * so the final result will be value from the low priority context.
290 */
291 store_dword(fd, ctx[LO], ring, scratch, 0, ctx[LO], cork.handle, 0);
292 store_dword(fd, ctx[HI], ring, scratch, 0, ctx[HI], cork.handle, 0);
293
294 unplug(&cork); /* only now submit our batches */
295 igt_debugfs_dump(fd, "i915_engine_info");
296 finish_busy(busy);
297
298 gem_context_destroy(fd, ctx[LO]);
299 gem_context_destroy(fd, ctx[HI]);
300
301 ptr = gem_mmap__gtt(fd, scratch, 4096, PROT_READ);
302 gem_set_domain(fd, scratch, /* no write hazard lies! */
303 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
304 gem_close(fd, scratch);
305
306 if (flags & EQUAL) /* equal priority, result will be fifo */
307 igt_assert_eq_u32(ptr[0], ctx[HI]);
308 else
309 igt_assert_eq_u32(ptr[0], ctx[LO]);
310 munmap(ptr, 4096);
311}
312
313static void promotion(int fd, unsigned ring)
314{
315 struct cork cork;
316 uint32_t result, dep;
317 uint32_t *busy;
318 uint32_t *ptr;
319 uint32_t ctx[3];
320
321 ctx[LO] = gem_context_create(fd);
322 ctx_set_priority(fd, ctx[LO], -MAX_PRIO);
323
324 ctx[HI] = gem_context_create(fd);
325 ctx_set_priority(fd, ctx[HI], 0);
326
327 ctx[NOISE] = gem_context_create(fd);
328 ctx_set_priority(fd, ctx[NOISE], -MAX_PRIO/2);
329
330 result = gem_create(fd, 4096);
331 dep = gem_create(fd, 4096);
332
333 busy = make_busy(fd, result, ring);
334 plug(fd, &cork);
335
336 /* Expect that HI promotes LO, so the order will be LO, HI, NOISE.
337 *
338 * fifo would be NOISE, LO, HI.
339 * strict priority would be HI, NOISE, LO
340 */
341 store_dword(fd, ctx[NOISE], ring, result, 0, ctx[NOISE], cork.handle, 0);
342 store_dword(fd, ctx[LO], ring, result, 0, ctx[LO], cork.handle, 0);
343
344 /* link LO <-> HI via a dependency on another buffer */
345 store_dword(fd, ctx[LO], ring, dep, 0, ctx[LO], 0, I915_GEM_DOMAIN_INSTRUCTION);
346 store_dword(fd, ctx[HI], ring, dep, 0, ctx[HI], 0, 0);
347
348 store_dword(fd, ctx[HI], ring, result, 0, ctx[HI], 0, 0);
349
350 unplug(&cork); /* only now submit our batches */
351 igt_debugfs_dump(fd, "i915_engine_info");
352 finish_busy(busy);
353
354 gem_context_destroy(fd, ctx[NOISE]);
355 gem_context_destroy(fd, ctx[LO]);
356 gem_context_destroy(fd, ctx[HI]);
357
358 ptr = gem_mmap__gtt(fd, dep, 4096, PROT_READ);
359 gem_set_domain(fd, dep, /* no write hazard lies! */
360 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
361 gem_close(fd, dep);
362
363 igt_assert_eq_u32(ptr[0], ctx[HI]);
364 munmap(ptr, 4096);
365
366 ptr = gem_mmap__gtt(fd, result, 4096, PROT_READ);
367 gem_set_domain(fd, result, /* no write hazard lies! */
368 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
369 gem_close(fd, result);
370
371 igt_assert_eq_u32(ptr[0], ctx[NOISE]);
372 munmap(ptr, 4096);
373}
374
375static void deep(int fd, unsigned ring)
376{
377#define XS 8
378 struct cork cork;
379 uint32_t result, dep[XS];
380 uint32_t *busy;
381 uint32_t *ptr;
382 uint32_t *ctx;
383
384 ctx = malloc(sizeof(*ctx)*(MAX_PRIO + 1));
385 for (int n = 0; n <= MAX_PRIO; n++) {
386 ctx[n] = gem_context_create(fd);
387 ctx_set_priority(fd, ctx[n], n);
388 }
389
390 result = gem_create(fd, 4096);
391 for (int m = 0; m < XS; m ++)
392 dep[m] = gem_create(fd, 4096);
393
394 busy = make_busy(fd, result, ring);
395 plug(fd, &cork);
396
397 /* Create a deep dependency chain, with a few branches */
398 for (int n = 0; n <= MAX_PRIO; n++)
399 for (int m = 0; m < XS; m++)
400 store_dword(fd, ctx[n], ring, dep[m], 4*n, ctx[n], cork.handle, I915_GEM_DOMAIN_INSTRUCTION);
401
402 for (int n = 0; n <= MAX_PRIO; n++) {
403 for (int m = 0; m < XS; m++) {
404 store_dword(fd, ctx[n], ring, result, 4*n, ctx[n], dep[m], 0);
405 store_dword(fd, ctx[n], ring, result, 4*m, ctx[n], 0, I915_GEM_DOMAIN_INSTRUCTION);
406 }
407 }
408
409 igt_assert(gem_bo_busy(fd, result));
410 unplug(&cork); /* only now submit our batches */
411 igt_debugfs_dump(fd, "i915_engine_info");
412 finish_busy(busy);
413
414 for (int n = 0; n <= MAX_PRIO; n++)
415 gem_context_destroy(fd, ctx[n]);
416
417 for (int m = 0; m < XS; m++) {
418 ptr = gem_mmap__gtt(fd, dep[m], 4096, PROT_READ);
419 gem_set_domain(fd, dep[m], /* no write hazard lies! */
420 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
421 gem_close(fd, dep[m]);
422
423 for (int n = 0; n <= MAX_PRIO; n++)
424 igt_assert_eq_u32(ptr[n], ctx[n]);
425 munmap(ptr, 4096);
426 }
427
428 ptr = gem_mmap__gtt(fd, result, 4096, PROT_READ);
429 gem_set_domain(fd, result, /* no write hazard lies! */
430 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
431 gem_close(fd, result);
432
433 for (int m = 0; m < XS; m++)
434 igt_assert_eq_u32(ptr[m], ctx[MAX_PRIO]);
435 munmap(ptr, 4096);
436
437 free(ctx);
Chris Wilsonf6920752017-04-24 13:20:04 +0100438#undef XS
439}
440
Chris Wilsona19ef052017-07-31 14:15:59 +0100441static void alarm_handler(int sig)
442{
443}
444
445static int __execbuf(int fd, struct drm_i915_gem_execbuffer2 *execbuf)
446{
447 return ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
448}
449
450static unsigned int measure_ring_size(int fd, unsigned int ring)
451{
452 struct sigaction sa = { .sa_handler = alarm_handler };
453 struct drm_i915_gem_exec_object2 obj[2];
454 struct drm_i915_gem_execbuffer2 execbuf;
455 const uint32_t bbe = MI_BATCH_BUFFER_END;
456 unsigned int count, last;
457 struct itimerval itv;
458 struct cork c;
459
460 memset(obj, 0, sizeof(obj));
461 obj[1].handle = gem_create(fd, 4096);
462 gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe));
463
464 memset(&execbuf, 0, sizeof(execbuf));
465 execbuf.buffers_ptr = to_user_pointer(obj + 1);
466 execbuf.buffer_count = 1;
467 execbuf.flags = ring;
468 gem_execbuf(fd, &execbuf);
469 gem_sync(fd, obj[1].handle);
470
471 plug(fd, &c);
472 obj[0].handle = c.handle;
473
474 execbuf.buffers_ptr = to_user_pointer(obj);
475 execbuf.buffer_count = 2;
476
477 sigaction(SIGALRM, &sa, NULL);
478 itv.it_interval.tv_sec = 0;
479 itv.it_interval.tv_usec = 100;
480 itv.it_value.tv_sec = 0;
481 itv.it_value.tv_usec = 1000;
482 setitimer(ITIMER_REAL, &itv, NULL);
483
484 last = -1;
485 count = 0;
486 do {
487 if (__execbuf(fd, &execbuf) == 0) {
488 count++;
489 continue;
490 }
491
492 if (last == count)
493 break;
494
495 last = count;
496 } while (1);
497
498 memset(&itv, 0, sizeof(itv));
499 setitimer(ITIMER_REAL, &itv, NULL);
500
501 unplug(&c);
502 gem_close(fd, obj[1].handle);
503
504 return count;
505}
506
Chris Wilsonf6920752017-04-24 13:20:04 +0100507static void wide(int fd, unsigned ring)
508{
Chris Wilsonf6920752017-04-24 13:20:04 +0100509#define NCTX 4096
Chris Wilsona19ef052017-07-31 14:15:59 +0100510 struct timespec tv = {};
511 unsigned int ring_size = measure_ring_size(fd, ring);
Chris Wilsonf6920752017-04-24 13:20:04 +0100512
513 struct cork cork;
514 uint32_t result;
515 uint32_t *busy;
516 uint32_t *ptr;
517 uint32_t *ctx;
Chris Wilsona19ef052017-07-31 14:15:59 +0100518 unsigned int count;
Chris Wilsonf6920752017-04-24 13:20:04 +0100519
520 ctx = malloc(sizeof(*ctx)*NCTX);
521 for (int n = 0; n < NCTX; n++)
522 ctx[n] = gem_context_create(fd);
523
Chris Wilsonf6920752017-04-24 13:20:04 +0100524 result = gem_create(fd, 4*NCTX);
525
526 busy = make_busy(fd, result, ring);
527 plug(fd, &cork);
528
529 /* Lots of in-order requests, plugged and submitted simultaneously */
Chris Wilsona19ef052017-07-31 14:15:59 +0100530 for (count = 0;
531 igt_seconds_elapsed(&tv) < 5 && count < ring_size;
532 count++) {
533 for (int n = 0; n < NCTX; n++) {
534 store_dword(fd, ctx[n], ring, result, 4*n, ctx[n], cork.handle, I915_GEM_DOMAIN_INSTRUCTION);
535 }
Chris Wilsonf6920752017-04-24 13:20:04 +0100536 }
Chris Wilsona19ef052017-07-31 14:15:59 +0100537 igt_info("Submitted %d requests over %d contexts in %.1fms\n",
538 count, NCTX, igt_nsec_elapsed(&tv) * 1e-6);
Chris Wilsonf6920752017-04-24 13:20:04 +0100539
540 igt_assert(gem_bo_busy(fd, result));
541 unplug(&cork); /* only now submit our batches */
542 igt_debugfs_dump(fd, "i915_engine_info");
543 finish_busy(busy);
544
545 for (int n = 0; n < NCTX; n++)
546 gem_context_destroy(fd, ctx[n]);
547
548 ptr = gem_mmap__gtt(fd, result, 4*NCTX, PROT_READ);
549 gem_set_domain(fd, result, /* no write hazard lies! */
550 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
551 for (int n = 0; n < NCTX; n++)
552 igt_assert_eq_u32(ptr[n], ctx[n]);
553 munmap(ptr, 4096);
554
Chris Wilsonf6920752017-04-24 13:20:04 +0100555 gem_close(fd, result);
556 free(ctx);
557#undef CTX
Chris Wilson721d8742016-10-27 11:32:47 +0100558}
559
560static bool has_scheduler(int fd)
561{
562 drm_i915_getparam_t gp;
563 int has = -1;
564
565 gp.param = LOCAL_PARAM_HAS_SCHEDULER;
566 gp.value = &has;
567 drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
568
569 return has > 0;
570}
571
572igt_main
573{
574 const struct intel_execution_engine *e;
575 int fd = -1;
576
577 igt_skip_on_simulation();
578
579 igt_fixture {
580 fd = drm_open_driver_master(DRIVER_INTEL);
Chris Wilson9518cb52017-02-22 15:24:54 +0000581 igt_require_gem(fd);
Chris Wilson721d8742016-10-27 11:32:47 +0100582 gem_require_mmap_wc(fd);
583 igt_fork_hang_detector(fd);
584 }
585
586 igt_subtest_group {
587 for (e = intel_execution_engines; e->name; e++) {
588 /* default exec-id is purely symbolic */
589 if (e->exec_id == 0)
590 continue;
591
592 igt_subtest_f("fifo-%s", e->name) {
593 gem_require_ring(fd, e->exec_id | e->flags);
Chris Wilsonbc787762017-05-18 12:11:59 +0100594 igt_require(gem_can_store_dword(fd, e->exec_id) | e->flags);
Chris Wilson721d8742016-10-27 11:32:47 +0100595 fifo(fd, e->exec_id | e->flags);
596 }
597 }
598 }
599
600 igt_subtest_group {
601 igt_fixture {
602 igt_require(has_scheduler(fd));
Chris Wilsonaf0e1c52017-02-21 18:25:58 +0000603 ctx_has_priority(fd);
Chris Wilson721d8742016-10-27 11:32:47 +0100604 }
605
606 for (e = intel_execution_engines; e->name; e++) {
607 /* default exec-id is purely symbolic */
608 if (e->exec_id == 0)
609 continue;
610
611 igt_subtest_group {
Chris Wilson073cfd72017-03-17 11:52:51 +0000612 igt_fixture {
Chris Wilson721d8742016-10-27 11:32:47 +0100613 gem_require_ring(fd, e->exec_id | e->flags);
Chris Wilsonbc787762017-05-18 12:11:59 +0100614 igt_require(gem_can_store_dword(fd, e->exec_id) | e->flags);
Chris Wilson073cfd72017-03-17 11:52:51 +0000615 }
Chris Wilson721d8742016-10-27 11:32:47 +0100616
617 igt_subtest_f("in-order-%s", e->name)
618 reorder(fd, e->exec_id | e->flags, EQUAL);
619
620 igt_subtest_f("out-order-%s", e->name)
621 reorder(fd, e->exec_id | e->flags, 0);
622
623 igt_subtest_f("promotion-%s", e->name)
624 promotion(fd, e->exec_id | e->flags);
625
626 igt_subtest_f("deep-%s", e->name)
627 deep(fd, e->exec_id | e->flags);
Chris Wilsonf6920752017-04-24 13:20:04 +0100628
629 igt_subtest_f("wide-%s", e->name)
630 wide(fd, e->exec_id | e->flags);
Chris Wilson721d8742016-10-27 11:32:47 +0100631 }
632 }
633 }
634
635 igt_fixture {
636 igt_stop_hang_detector();
637 close(fd);
638 }
639}