1 /*
2  * SPDX-License-Identifier: MIT
3  *
4  * Copyright © 2017-2018 Intel Corporation
5  */
6 
7 #include <linux/prime_numbers.h>
8 
9 #include "intel_engine_pm.h"
10 #include "intel_gt.h"
11 #include "intel_gt_requests.h"
12 #include "intel_ring.h"
13 
14 #include "../selftests/i915_random.h"
15 #include "../i915_selftest.h"
16 
17 #include "../selftests/igt_flush_test.h"
18 #include "../selftests/mock_gem_device.h"
19 #include "selftests/mock_timeline.h"
20 
21 static struct page *hwsp_page(struct intel_timeline *tl)
22 {
23 	struct drm_i915_gem_object *obj = tl->hwsp_ggtt->obj;
24 
25 	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
26 	return sg_page(obj->mm.pages->sgl);
27 }
28 
29 static unsigned long hwsp_cacheline(struct intel_timeline *tl)
30 {
31 	unsigned long address = (unsigned long)page_address(hwsp_page(tl));
32 
33 	return (address + tl->hwsp_offset) / CACHELINE_BYTES;
34 }
35 
36 #define CACHELINES_PER_PAGE (PAGE_SIZE / CACHELINE_BYTES)
37 
38 struct mock_hwsp_freelist {
39 	struct intel_gt *gt;
40 	struct radix_tree_root cachelines;
41 	struct intel_timeline **history;
42 	unsigned long count, max;
43 	struct rnd_state prng;
44 };
45 
46 enum {
47 	SHUFFLE = BIT(0),
48 };
49 
50 static void __mock_hwsp_record(struct mock_hwsp_freelist *state,
51 			       unsigned int idx,
52 			       struct intel_timeline *tl)
53 {
54 	tl = xchg(&state->history[idx], tl);
55 	if (tl) {
56 		radix_tree_delete(&state->cachelines, hwsp_cacheline(tl));
57 		intel_timeline_put(tl);
58 	}
59 }
60 
61 static int __mock_hwsp_timeline(struct mock_hwsp_freelist *state,
62 				unsigned int count,
63 				unsigned int flags)
64 {
65 	struct intel_timeline *tl;
66 	unsigned int idx;
67 
68 	while (count--) {
69 		unsigned long cacheline;
70 		int err;
71 
72 		tl = intel_timeline_create(state->gt, NULL);
73 		if (IS_ERR(tl))
74 			return PTR_ERR(tl);
75 
76 		cacheline = hwsp_cacheline(tl);
77 		err = radix_tree_insert(&state->cachelines, cacheline, tl);
78 		if (err) {
79 			if (err == -EEXIST) {
80 				pr_err("HWSP cacheline %lu already used; duplicate allocation!\n",
81 				       cacheline);
82 			}
83 			intel_timeline_put(tl);
84 			return err;
85 		}
86 
87 		idx = state->count++ % state->max;
88 		__mock_hwsp_record(state, idx, tl);
89 	}
90 
91 	if (flags & SHUFFLE)
92 		i915_prandom_shuffle(state->history,
93 				     sizeof(*state->history),
94 				     min(state->count, state->max),
95 				     &state->prng);
96 
97 	count = i915_prandom_u32_max_state(min(state->count, state->max),
98 					   &state->prng);
99 	while (count--) {
100 		idx = --state->count % state->max;
101 		__mock_hwsp_record(state, idx, NULL);
102 	}
103 
104 	return 0;
105 }
106 
107 static int mock_hwsp_freelist(void *arg)
108 {
109 	struct mock_hwsp_freelist state;
110 	struct drm_i915_private *i915;
111 	const struct {
112 		const char *name;
113 		unsigned int flags;
114 	} phases[] = {
115 		{ "linear", 0 },
116 		{ "shuffled", SHUFFLE },
117 		{ },
118 	}, *p;
119 	unsigned int na;
120 	int err = 0;
121 
122 	i915 = mock_gem_device();
123 	if (!i915)
124 		return -ENOMEM;
125 
126 	INIT_RADIX_TREE(&state.cachelines, GFP_KERNEL);
127 	state.prng = I915_RND_STATE_INITIALIZER(i915_selftest.random_seed);
128 
129 	state.gt = &i915->gt;
130 
131 	/*
132 	 * Create a bunch of timelines and check that their HWSP do not overlap.
133 	 * Free some, and try again.
134 	 */
135 
136 	state.max = PAGE_SIZE / sizeof(*state.history);
137 	state.count = 0;
138 	state.history = kcalloc(state.max, sizeof(*state.history), GFP_KERNEL);
139 	if (!state.history) {
140 		err = -ENOMEM;
141 		goto err_put;
142 	}
143 
144 	for (p = phases; p->name; p++) {
145 		pr_debug("%s(%s)\n", __func__, p->name);
146 		for_each_prime_number_from(na, 1, 2 * CACHELINES_PER_PAGE) {
147 			err = __mock_hwsp_timeline(&state, na, p->flags);
148 			if (err)
149 				goto out;
150 		}
151 	}
152 
153 out:
154 	for (na = 0; na < state.max; na++)
155 		__mock_hwsp_record(&state, na, NULL);
156 	kfree(state.history);
157 err_put:
158 	drm_dev_put(&i915->drm);
159 	return err;
160 }
161 
162 struct __igt_sync {
163 	const char *name;
164 	u32 seqno;
165 	bool expected;
166 	bool set;
167 };
168 
169 static int __igt_sync(struct intel_timeline *tl,
170 		      u64 ctx,
171 		      const struct __igt_sync *p,
172 		      const char *name)
173 {
174 	int ret;
175 
176 	if (__intel_timeline_sync_is_later(tl, ctx, p->seqno) != p->expected) {
177 		pr_err("%s: %s(ctx=%llu, seqno=%u) expected passed %s but failed\n",
178 		       name, p->name, ctx, p->seqno, yesno(p->expected));
179 		return -EINVAL;
180 	}
181 
182 	if (p->set) {
183 		ret = __intel_timeline_sync_set(tl, ctx, p->seqno);
184 		if (ret)
185 			return ret;
186 	}
187 
188 	return 0;
189 }
190 
191 static int igt_sync(void *arg)
192 {
193 	const struct __igt_sync pass[] = {
194 		{ "unset", 0, false, false },
195 		{ "new", 0, false, true },
196 		{ "0a", 0, true, true },
197 		{ "1a", 1, false, true },
198 		{ "1b", 1, true, true },
199 		{ "0b", 0, true, false },
200 		{ "2a", 2, false, true },
201 		{ "4", 4, false, true },
202 		{ "INT_MAX", INT_MAX, false, true },
203 		{ "INT_MAX-1", INT_MAX-1, true, false },
204 		{ "INT_MAX+1", (u32)INT_MAX+1, false, true },
205 		{ "INT_MAX", INT_MAX, true, false },
206 		{ "UINT_MAX", UINT_MAX, false, true },
207 		{ "wrap", 0, false, true },
208 		{ "unwrap", UINT_MAX, true, false },
209 		{},
210 	}, *p;
211 	struct intel_timeline tl;
212 	int order, offset;
213 	int ret = -ENODEV;
214 
215 	mock_timeline_init(&tl, 0);
216 	for (p = pass; p->name; p++) {
217 		for (order = 1; order < 64; order++) {
218 			for (offset = -1; offset <= (order > 1); offset++) {
219 				u64 ctx = BIT_ULL(order) + offset;
220 
221 				ret = __igt_sync(&tl, ctx, p, "1");
222 				if (ret)
223 					goto out;
224 			}
225 		}
226 	}
227 	mock_timeline_fini(&tl);
228 
229 	mock_timeline_init(&tl, 0);
230 	for (order = 1; order < 64; order++) {
231 		for (offset = -1; offset <= (order > 1); offset++) {
232 			u64 ctx = BIT_ULL(order) + offset;
233 
234 			for (p = pass; p->name; p++) {
235 				ret = __igt_sync(&tl, ctx, p, "2");
236 				if (ret)
237 					goto out;
238 			}
239 		}
240 	}
241 
242 out:
243 	mock_timeline_fini(&tl);
244 	return ret;
245 }
246 
247 static unsigned int random_engine(struct rnd_state *rnd)
248 {
249 	return i915_prandom_u32_max_state(I915_NUM_ENGINES, rnd);
250 }
251 
252 static int bench_sync(void *arg)
253 {
254 	struct rnd_state prng;
255 	struct intel_timeline tl;
256 	unsigned long end_time, count;
257 	u64 prng32_1M;
258 	ktime_t kt;
259 	int order, last_order;
260 
261 	mock_timeline_init(&tl, 0);
262 
263 	/* Lookups from cache are very fast and so the random number generation
264 	 * and the loop itself becomes a significant factor in the per-iteration
265 	 * timings. We try to compensate the results by measuring the overhead
266 	 * of the prng and subtract it from the reported results.
267 	 */
268 	prandom_seed_state(&prng, i915_selftest.random_seed);
269 	count = 0;
270 	kt = ktime_get();
271 	end_time = jiffies + HZ/10;
272 	do {
273 		u32 x;
274 
275 		/* Make sure the compiler doesn't optimise away the prng call */
276 		WRITE_ONCE(x, prandom_u32_state(&prng));
277 
278 		count++;
279 	} while (!time_after(jiffies, end_time));
280 	kt = ktime_sub(ktime_get(), kt);
281 	pr_debug("%s: %lu random evaluations, %lluns/prng\n",
282 		 __func__, count, (long long)div64_ul(ktime_to_ns(kt), count));
283 	prng32_1M = div64_ul(ktime_to_ns(kt) << 20, count);
284 
285 	/* Benchmark (only) setting random context ids */
286 	prandom_seed_state(&prng, i915_selftest.random_seed);
287 	count = 0;
288 	kt = ktime_get();
289 	end_time = jiffies + HZ/10;
290 	do {
291 		u64 id = i915_prandom_u64_state(&prng);
292 
293 		__intel_timeline_sync_set(&tl, id, 0);
294 		count++;
295 	} while (!time_after(jiffies, end_time));
296 	kt = ktime_sub(ktime_get(), kt);
297 	kt = ktime_sub_ns(kt, (count * prng32_1M * 2) >> 20);
298 	pr_info("%s: %lu random insertions, %lluns/insert\n",
299 		__func__, count, (long long)div64_ul(ktime_to_ns(kt), count));
300 
301 	/* Benchmark looking up the exact same context ids as we just set */
302 	prandom_seed_state(&prng, i915_selftest.random_seed);
303 	end_time = count;
304 	kt = ktime_get();
305 	while (end_time--) {
306 		u64 id = i915_prandom_u64_state(&prng);
307 
308 		if (!__intel_timeline_sync_is_later(&tl, id, 0)) {
309 			mock_timeline_fini(&tl);
310 			pr_err("Lookup of %llu failed\n", id);
311 			return -EINVAL;
312 		}
313 	}
314 	kt = ktime_sub(ktime_get(), kt);
315 	kt = ktime_sub_ns(kt, (count * prng32_1M * 2) >> 20);
316 	pr_info("%s: %lu random lookups, %lluns/lookup\n",
317 		__func__, count, (long long)div64_ul(ktime_to_ns(kt), count));
318 
319 	mock_timeline_fini(&tl);
320 	cond_resched();
321 
322 	mock_timeline_init(&tl, 0);
323 
324 	/* Benchmark setting the first N (in order) contexts */
325 	count = 0;
326 	kt = ktime_get();
327 	end_time = jiffies + HZ/10;
328 	do {
329 		__intel_timeline_sync_set(&tl, count++, 0);
330 	} while (!time_after(jiffies, end_time));
331 	kt = ktime_sub(ktime_get(), kt);
332 	pr_info("%s: %lu in-order insertions, %lluns/insert\n",
333 		__func__, count, (long long)div64_ul(ktime_to_ns(kt), count));
334 
335 	/* Benchmark looking up the exact same context ids as we just set */
336 	end_time = count;
337 	kt = ktime_get();
338 	while (end_time--) {
339 		if (!__intel_timeline_sync_is_later(&tl, end_time, 0)) {
340 			pr_err("Lookup of %lu failed\n", end_time);
341 			mock_timeline_fini(&tl);
342 			return -EINVAL;
343 		}
344 	}
345 	kt = ktime_sub(ktime_get(), kt);
346 	pr_info("%s: %lu in-order lookups, %lluns/lookup\n",
347 		__func__, count, (long long)div64_ul(ktime_to_ns(kt), count));
348 
349 	mock_timeline_fini(&tl);
350 	cond_resched();
351 
352 	mock_timeline_init(&tl, 0);
353 
354 	/* Benchmark searching for a random context id and maybe changing it */
355 	prandom_seed_state(&prng, i915_selftest.random_seed);
356 	count = 0;
357 	kt = ktime_get();
358 	end_time = jiffies + HZ/10;
359 	do {
360 		u32 id = random_engine(&prng);
361 		u32 seqno = prandom_u32_state(&prng);
362 
363 		if (!__intel_timeline_sync_is_later(&tl, id, seqno))
364 			__intel_timeline_sync_set(&tl, id, seqno);
365 
366 		count++;
367 	} while (!time_after(jiffies, end_time));
368 	kt = ktime_sub(ktime_get(), kt);
369 	kt = ktime_sub_ns(kt, (count * prng32_1M * 2) >> 20);
370 	pr_info("%s: %lu repeated insert/lookups, %lluns/op\n",
371 		__func__, count, (long long)div64_ul(ktime_to_ns(kt), count));
372 	mock_timeline_fini(&tl);
373 	cond_resched();
374 
375 	/* Benchmark searching for a known context id and changing the seqno */
376 	for (last_order = 1, order = 1; order < 32;
377 	     ({ int tmp = last_order; last_order = order; order += tmp; })) {
378 		unsigned int mask = BIT(order) - 1;
379 
380 		mock_timeline_init(&tl, 0);
381 
382 		count = 0;
383 		kt = ktime_get();
384 		end_time = jiffies + HZ/10;
385 		do {
386 			/* Without assuming too many details of the underlying
387 			 * implementation, try to identify its phase-changes
388 			 * (if any)!
389 			 */
390 			u64 id = (u64)(count & mask) << order;
391 
392 			__intel_timeline_sync_is_later(&tl, id, 0);
393 			__intel_timeline_sync_set(&tl, id, 0);
394 
395 			count++;
396 		} while (!time_after(jiffies, end_time));
397 		kt = ktime_sub(ktime_get(), kt);
398 		pr_info("%s: %lu cyclic/%d insert/lookups, %lluns/op\n",
399 			__func__, count, order,
400 			(long long)div64_ul(ktime_to_ns(kt), count));
401 		mock_timeline_fini(&tl);
402 		cond_resched();
403 	}
404 
405 	return 0;
406 }
407 
408 int intel_timeline_mock_selftests(void)
409 {
410 	static const struct i915_subtest tests[] = {
411 		SUBTEST(mock_hwsp_freelist),
412 		SUBTEST(igt_sync),
413 		SUBTEST(bench_sync),
414 	};
415 
416 	return i915_subtests(tests, NULL);
417 }
418 
419 static int emit_ggtt_store_dw(struct i915_request *rq, u32 addr, u32 value)
420 {
421 	u32 *cs;
422 
423 	cs = intel_ring_begin(rq, 4);
424 	if (IS_ERR(cs))
425 		return PTR_ERR(cs);
426 
427 	if (INTEL_GEN(rq->i915) >= 8) {
428 		*cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
429 		*cs++ = addr;
430 		*cs++ = 0;
431 		*cs++ = value;
432 	} else if (INTEL_GEN(rq->i915) >= 4) {
433 		*cs++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
434 		*cs++ = 0;
435 		*cs++ = addr;
436 		*cs++ = value;
437 	} else {
438 		*cs++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
439 		*cs++ = addr;
440 		*cs++ = value;
441 		*cs++ = MI_NOOP;
442 	}
443 
444 	intel_ring_advance(rq, cs);
445 
446 	return 0;
447 }
448 
449 static struct i915_request *
450 tl_write(struct intel_timeline *tl, struct intel_engine_cs *engine, u32 value)
451 {
452 	struct i915_request *rq;
453 	int err;
454 
455 	err = intel_timeline_pin(tl);
456 	if (err) {
457 		rq = ERR_PTR(err);
458 		goto out;
459 	}
460 
461 	rq = intel_engine_create_kernel_request(engine);
462 	if (IS_ERR(rq))
463 		goto out_unpin;
464 
465 	i915_request_get(rq);
466 
467 	err = emit_ggtt_store_dw(rq, tl->hwsp_offset, value);
468 	i915_request_add(rq);
469 	if (err) {
470 		i915_request_put(rq);
471 		rq = ERR_PTR(err);
472 	}
473 
474 out_unpin:
475 	intel_timeline_unpin(tl);
476 out:
477 	if (IS_ERR(rq))
478 		pr_err("Failed to write to timeline!\n");
479 	return rq;
480 }
481 
482 static struct intel_timeline *
483 checked_intel_timeline_create(struct intel_gt *gt)
484 {
485 	struct intel_timeline *tl;
486 
487 	tl = intel_timeline_create(gt, NULL);
488 	if (IS_ERR(tl))
489 		return tl;
490 
491 	if (*tl->hwsp_seqno != tl->seqno) {
492 		pr_err("Timeline created with incorrect breadcrumb, found %x, expected %x\n",
493 		       *tl->hwsp_seqno, tl->seqno);
494 		intel_timeline_put(tl);
495 		return ERR_PTR(-EINVAL);
496 	}
497 
498 	return tl;
499 }
500 
501 static int live_hwsp_engine(void *arg)
502 {
503 #define NUM_TIMELINES 4096
504 	struct intel_gt *gt = arg;
505 	struct intel_timeline **timelines;
506 	struct intel_engine_cs *engine;
507 	enum intel_engine_id id;
508 	unsigned long count, n;
509 	int err = 0;
510 
511 	/*
512 	 * Create a bunch of timelines and check we can write
513 	 * independently to each of their breadcrumb slots.
514 	 */
515 
516 	timelines = kvmalloc_array(NUM_TIMELINES * I915_NUM_ENGINES,
517 				   sizeof(*timelines),
518 				   GFP_KERNEL);
519 	if (!timelines)
520 		return -ENOMEM;
521 
522 	count = 0;
523 	for_each_engine(engine, gt, id) {
524 		if (!intel_engine_can_store_dword(engine))
525 			continue;
526 
527 		intel_engine_pm_get(engine);
528 
529 		for (n = 0; n < NUM_TIMELINES; n++) {
530 			struct intel_timeline *tl;
531 			struct i915_request *rq;
532 
533 			tl = checked_intel_timeline_create(gt);
534 			if (IS_ERR(tl)) {
535 				err = PTR_ERR(tl);
536 				break;
537 			}
538 
539 			rq = tl_write(tl, engine, count);
540 			if (IS_ERR(rq)) {
541 				intel_timeline_put(tl);
542 				err = PTR_ERR(rq);
543 				break;
544 			}
545 
546 			timelines[count++] = tl;
547 			i915_request_put(rq);
548 		}
549 
550 		intel_engine_pm_put(engine);
551 		if (err)
552 			break;
553 	}
554 
555 	if (igt_flush_test(gt->i915))
556 		err = -EIO;
557 
558 	for (n = 0; n < count; n++) {
559 		struct intel_timeline *tl = timelines[n];
560 
561 		if (!err && *tl->hwsp_seqno != n) {
562 			pr_err("Invalid seqno stored in timeline %lu, found 0x%x\n",
563 			       n, *tl->hwsp_seqno);
564 			err = -EINVAL;
565 		}
566 		intel_timeline_put(tl);
567 	}
568 
569 	kvfree(timelines);
570 	return err;
571 #undef NUM_TIMELINES
572 }
573 
574 static int live_hwsp_alternate(void *arg)
575 {
576 #define NUM_TIMELINES 4096
577 	struct intel_gt *gt = arg;
578 	struct intel_timeline **timelines;
579 	struct intel_engine_cs *engine;
580 	enum intel_engine_id id;
581 	unsigned long count, n;
582 	int err = 0;
583 
584 	/*
585 	 * Create a bunch of timelines and check we can write
586 	 * independently to each of their breadcrumb slots with adjacent
587 	 * engines.
588 	 */
589 
590 	timelines = kvmalloc_array(NUM_TIMELINES * I915_NUM_ENGINES,
591 				   sizeof(*timelines),
592 				   GFP_KERNEL);
593 	if (!timelines)
594 		return -ENOMEM;
595 
596 	count = 0;
597 	for (n = 0; n < NUM_TIMELINES; n++) {
598 		for_each_engine(engine, gt, id) {
599 			struct intel_timeline *tl;
600 			struct i915_request *rq;
601 
602 			if (!intel_engine_can_store_dword(engine))
603 				continue;
604 
605 			tl = checked_intel_timeline_create(gt);
606 			if (IS_ERR(tl)) {
607 				intel_engine_pm_put(engine);
608 				err = PTR_ERR(tl);
609 				goto out;
610 			}
611 
612 			intel_engine_pm_get(engine);
613 			rq = tl_write(tl, engine, count);
614 			intel_engine_pm_put(engine);
615 			if (IS_ERR(rq)) {
616 				intel_timeline_put(tl);
617 				err = PTR_ERR(rq);
618 				goto out;
619 			}
620 
621 			timelines[count++] = tl;
622 			i915_request_put(rq);
623 		}
624 	}
625 
626 out:
627 	if (igt_flush_test(gt->i915))
628 		err = -EIO;
629 
630 	for (n = 0; n < count; n++) {
631 		struct intel_timeline *tl = timelines[n];
632 
633 		if (!err && *tl->hwsp_seqno != n) {
634 			pr_err("Invalid seqno stored in timeline %lu, found 0x%x\n",
635 			       n, *tl->hwsp_seqno);
636 			err = -EINVAL;
637 		}
638 		intel_timeline_put(tl);
639 	}
640 
641 	kvfree(timelines);
642 	return err;
643 #undef NUM_TIMELINES
644 }
645 
646 static int live_hwsp_wrap(void *arg)
647 {
648 	struct intel_gt *gt = arg;
649 	struct intel_engine_cs *engine;
650 	struct intel_timeline *tl;
651 	enum intel_engine_id id;
652 	int err = 0;
653 
654 	/*
655 	 * Across a seqno wrap, we need to keep the old cacheline alive for
656 	 * foreign GPU references.
657 	 */
658 
659 	tl = intel_timeline_create(gt, NULL);
660 	if (IS_ERR(tl))
661 		return PTR_ERR(tl);
662 
663 	if (!tl->has_initial_breadcrumb || !tl->hwsp_cacheline)
664 		goto out_free;
665 
666 	err = intel_timeline_pin(tl);
667 	if (err)
668 		goto out_free;
669 
670 	for_each_engine(engine, gt, id) {
671 		const u32 *hwsp_seqno[2];
672 		struct i915_request *rq;
673 		u32 seqno[2];
674 
675 		if (!intel_engine_can_store_dword(engine))
676 			continue;
677 
678 		rq = intel_engine_create_kernel_request(engine);
679 		if (IS_ERR(rq)) {
680 			err = PTR_ERR(rq);
681 			goto out;
682 		}
683 
684 		tl->seqno = -4u;
685 
686 		mutex_lock_nested(&tl->mutex, SINGLE_DEPTH_NESTING);
687 		err = intel_timeline_get_seqno(tl, rq, &seqno[0]);
688 		mutex_unlock(&tl->mutex);
689 		if (err) {
690 			i915_request_add(rq);
691 			goto out;
692 		}
693 		pr_debug("seqno[0]:%08x, hwsp_offset:%08x\n",
694 			 seqno[0], tl->hwsp_offset);
695 
696 		err = emit_ggtt_store_dw(rq, tl->hwsp_offset, seqno[0]);
697 		if (err) {
698 			i915_request_add(rq);
699 			goto out;
700 		}
701 		hwsp_seqno[0] = tl->hwsp_seqno;
702 
703 		mutex_lock_nested(&tl->mutex, SINGLE_DEPTH_NESTING);
704 		err = intel_timeline_get_seqno(tl, rq, &seqno[1]);
705 		mutex_unlock(&tl->mutex);
706 		if (err) {
707 			i915_request_add(rq);
708 			goto out;
709 		}
710 		pr_debug("seqno[1]:%08x, hwsp_offset:%08x\n",
711 			 seqno[1], tl->hwsp_offset);
712 
713 		err = emit_ggtt_store_dw(rq, tl->hwsp_offset, seqno[1]);
714 		if (err) {
715 			i915_request_add(rq);
716 			goto out;
717 		}
718 		hwsp_seqno[1] = tl->hwsp_seqno;
719 
720 		/* With wrap should come a new hwsp */
721 		GEM_BUG_ON(seqno[1] >= seqno[0]);
722 		GEM_BUG_ON(hwsp_seqno[0] == hwsp_seqno[1]);
723 
724 		i915_request_add(rq);
725 
726 		if (i915_request_wait(rq, 0, HZ / 5) < 0) {
727 			pr_err("Wait for timeline writes timed out!\n");
728 			err = -EIO;
729 			goto out;
730 		}
731 
732 		if (*hwsp_seqno[0] != seqno[0] || *hwsp_seqno[1] != seqno[1]) {
733 			pr_err("Bad timeline values: found (%x, %x), expected (%x, %x)\n",
734 			       *hwsp_seqno[0], *hwsp_seqno[1],
735 			       seqno[0], seqno[1]);
736 			err = -EINVAL;
737 			goto out;
738 		}
739 
740 		intel_gt_retire_requests(gt); /* recycle HWSP */
741 	}
742 
743 out:
744 	if (igt_flush_test(gt->i915))
745 		err = -EIO;
746 
747 	intel_timeline_unpin(tl);
748 out_free:
749 	intel_timeline_put(tl);
750 	return err;
751 }
752 
753 static int live_hwsp_recycle(void *arg)
754 {
755 	struct intel_gt *gt = arg;
756 	struct intel_engine_cs *engine;
757 	enum intel_engine_id id;
758 	unsigned long count;
759 	int err = 0;
760 
761 	/*
762 	 * Check seqno writes into one timeline at a time. We expect to
763 	 * recycle the breadcrumb slot between iterations and neither
764 	 * want to confuse ourselves or the GPU.
765 	 */
766 
767 	count = 0;
768 	for_each_engine(engine, gt, id) {
769 		IGT_TIMEOUT(end_time);
770 
771 		if (!intel_engine_can_store_dword(engine))
772 			continue;
773 
774 		intel_engine_pm_get(engine);
775 
776 		do {
777 			struct intel_timeline *tl;
778 			struct i915_request *rq;
779 
780 			tl = checked_intel_timeline_create(gt);
781 			if (IS_ERR(tl)) {
782 				err = PTR_ERR(tl);
783 				break;
784 			}
785 
786 			rq = tl_write(tl, engine, count);
787 			if (IS_ERR(rq)) {
788 				intel_timeline_put(tl);
789 				err = PTR_ERR(rq);
790 				break;
791 			}
792 
793 			if (i915_request_wait(rq, 0, HZ / 5) < 0) {
794 				pr_err("Wait for timeline writes timed out!\n");
795 				i915_request_put(rq);
796 				intel_timeline_put(tl);
797 				err = -EIO;
798 				break;
799 			}
800 
801 			if (*tl->hwsp_seqno != count) {
802 				pr_err("Invalid seqno stored in timeline %lu, found 0x%x\n",
803 				       count, *tl->hwsp_seqno);
804 				err = -EINVAL;
805 			}
806 
807 			i915_request_put(rq);
808 			intel_timeline_put(tl);
809 			count++;
810 
811 			if (err)
812 				break;
813 		} while (!__igt_timeout(end_time, NULL));
814 
815 		intel_engine_pm_put(engine);
816 		if (err)
817 			break;
818 	}
819 
820 	return err;
821 }
822 
823 int intel_timeline_live_selftests(struct drm_i915_private *i915)
824 {
825 	static const struct i915_subtest tests[] = {
826 		SUBTEST(live_hwsp_recycle),
827 		SUBTEST(live_hwsp_engine),
828 		SUBTEST(live_hwsp_alternate),
829 		SUBTEST(live_hwsp_wrap),
830 	};
831 
832 	if (intel_gt_is_wedged(&i915->gt))
833 		return 0;
834 
835 	return intel_gt_live_subtests(tests, &i915->gt);
836 }
837