[RFC] drm/i915/selftests: Autotune timeouts
diff mbox series

Message ID 20191115184156.1482912-1-chris@chris-wilson.co.uk
State New
Headers show
Series
  • [RFC] drm/i915/selftests: Autotune timeouts
Related show

Commit Message

Chris Wilson Nov. 15, 2019, 6:41 p.m. UTC
Not all HW is made equal, and so one timeout for a test on one may fail
on another. Now that we measure a baseline for the latency of an engine,
we can provide a more precise estimate for how long a test will run and
after applying some safety factors, provide an accurate timeout for the
test.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Stuart Summers <stuart.summers@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |  3 +-
 .../drm/i915/gem/selftests/i915_gem_context.c |  7 +--
 drivers/gpu/drm/i915/gt/intel_workarounds.c   |  3 +-
 drivers/gpu/drm/i915/gt/selftest_context.c    |  3 +-
 drivers/gpu/drm/i915/gt/selftest_engine_cs.c  |  5 ++-
 drivers/gpu/drm/i915/gt/selftest_hangcheck.c  |  7 +--
 drivers/gpu/drm/i915/gt/selftest_lrc.c        | 41 ++++++++---------
 drivers/gpu/drm/i915/gt/selftest_mocs.c       |  3 +-
 drivers/gpu/drm/i915/gt/selftest_timeline.c   |  5 ++-
 .../gpu/drm/i915/gt/selftest_workarounds.c    |  2 +-
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |  3 +-
 drivers/gpu/drm/i915/selftests/i915_request.c | 10 ++---
 drivers/gpu/drm/i915/selftests/igt_utils.c    | 44 +++++++++++++++++++
 drivers/gpu/drm/i915/selftests/igt_utils.h    | 20 +++++++++
 14 files changed, 115 insertions(+), 41 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/selftests/igt_utils.c
 create mode 100644 drivers/gpu/drm/i915/selftests/igt_utils.h

Comments

Chris Wilson Nov. 15, 2019, 6:45 p.m. UTC | #1
Quoting Chris Wilson (2019-11-15 18:41:56)
> +unsigned long igt_request_timeout(struct intel_engine_cs *engine,
> +                                 unsigned int factor)
> +{
> +       unsigned long base;
> +
> +       if (is_power_of_2(engine->mask)) {
> +               base = ewma_delay_read(&engine->delay);
> +       } else {
> +               intel_engine_mask_t mask = engine->mask, tmp;
> +               unsigned int n = 0;
> +
> +               base = 0;
> +               for_each_engine_masked(engine, engine->gt, mask, tmp)
> +                       base += ewma_delay_read(&engine->delay), n++;
> +               base /= n;

I forgot to switch to max().
-Chris

Patch
diff mbox series

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 7b83a510babb..faef8c1666d4 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -262,7 +262,8 @@  i915-$(CONFIG_DRM_I915_SELFTEST) += \
 	selftests/igt_live_test.o \
 	selftests/igt_mmap.o \
 	selftests/igt_reset.o \
-	selftests/igt_spinner.o
+	selftests/igt_spinner.o \
+	selftests/igt_utils.o
 
 # virtual gpu code
 i915-y += i915_vgpu.o
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
index 106a3bfa3bb6..b41568477426 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -18,6 +18,7 @@ 
 #include "selftests/igt_live_test.h"
 #include "selftests/igt_reset.h"
 #include "selftests/igt_spinner.h"
+#include "selftests/igt_utils.h"
 #include "selftests/mock_drm.h"
 #include "selftests/mock_gem_device.h"
 
@@ -86,7 +87,7 @@  static int live_nop_switch(void *arg)
 			}
 			i915_request_add(rq);
 		}
-		if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+		if (igt_request_wait(rq, 0, 2) < 0) {
 			pr_err("Failed to populated %d contexts\n", nctx);
 			intel_gt_set_wedged(&i915->gt);
 			err = -EIO;
@@ -129,7 +130,7 @@  static int live_nop_switch(void *arg)
 
 				i915_request_add(rq);
 			}
-			if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+			if (igt_request_wait(rq, 0, 2) < 0) {
 				pr_err("Switching between %ld contexts timed out\n",
 				       prime);
 				intel_gt_set_wedged(&i915->gt);
@@ -193,7 +194,7 @@  static int __live_parallel_switch1(void *data)
 
 			i915_request_add(rq);
 		}
-		if (i915_request_wait(rq, 0, HZ / 5) < 0)
+		if (igt_request_wait(rq, 0, 2) < 0)
 			err = -ETIME;
 		i915_request_put(rq);
 		if (err)
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index 399acae2f33f..9ba588e113e5 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -9,6 +9,7 @@ 
 #include "intel_gt.h"
 #include "intel_ring.h"
 #include "intel_workarounds.h"
+#include "selftests/igt_utils.h"
 
 /**
  * DOC: Hardware workarounds
@@ -1593,7 +1594,7 @@  static int engine_wa_list_verify(struct intel_context *ce,
 		goto err_vma;
 
 	i915_request_add(rq);
-	if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+	if (igt_request_wait(rq, 0, 2) < 0) {
 		err = -ETIME;
 		goto err_vma;
 	}
diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c
index 57e40db8cbd2..65d033fd6bf8 100644
--- a/drivers/gpu/drm/i915/gt/selftest_context.c
+++ b/drivers/gpu/drm/i915/gt/selftest_context.c
@@ -11,6 +11,7 @@ 
 
 #include "gem/selftests/mock_context.h"
 #include "selftests/igt_flush_test.h"
+#include "selftests/igt_utils.h"
 #include "selftests/mock_drm.h"
 
 static int request_sync(struct i915_request *rq)
@@ -26,7 +27,7 @@  static int request_sync(struct i915_request *rq)
 	__i915_request_commit(rq);
 	__i915_request_queue(rq, NULL);
 
-	timeout = i915_request_wait(rq, 0, HZ / 10);
+	timeout = igt_request_wait(rq, 0, 1);
 	if (timeout < 0)
 		err = timeout;
 	else
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
index 5981a7b71ec9..e0de46509a88 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
@@ -11,6 +11,7 @@ 
 
 #include "i915_selftest.h"
 #include "selftests/igt_flush_test.h"
+#include "selftests/igt_utils.h"
 
 #define COUNT 5
 
@@ -171,7 +172,7 @@  static int perf_mi_bb_start(void *arg)
 			i915_request_get(rq);
 			i915_request_add(rq);
 
-			if (i915_request_wait(rq, 0, HZ / 5) < 0)
+			if (igt_request_wait(rq, 0, 2) < 0)
 				err = -EIO;
 			i915_request_put(rq);
 			if (err)
@@ -315,7 +316,7 @@  static int perf_mi_noop(void *arg)
 			i915_request_get(rq);
 			i915_request_add(rq);
 
-			if (i915_request_wait(rq, 0, HZ / 5) < 0)
+			if (igt_request_wait(rq, 0, 2) < 0)
 				err = -EIO;
 			i915_request_put(rq);
 			if (err)
diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
index ff2d8af282a6..1ae25a668e19 100644
--- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
@@ -33,6 +33,7 @@ 
 #include "selftests/igt_flush_test.h"
 #include "selftests/igt_reset.h"
 #include "selftests/igt_atomic.h"
+#include "selftests/igt_utils.h"
 
 #include "selftests/mock_drm.h"
 
@@ -655,7 +656,7 @@  static int active_request_put(struct i915_request *rq)
 	if (!rq)
 		return 0;
 
-	if (i915_request_wait(rq, 0, 5 * HZ) < 0) {
+	if (igt_request_wait(rq, 0, 500) < 0) {
 		GEM_TRACE("%s timed out waiting for completion of fence %llx:%lld\n",
 			  rq->engine->name,
 			  rq->fence.context,
@@ -845,7 +846,7 @@  static int __igt_reset_engines(struct intel_gt *gt,
 			count++;
 
 			if (rq) {
-				if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+				if (igt_request_wait(rq, 0, 2) < 0) {
 					struct drm_printer p =
 						drm_info_printer(gt->i915->drm.dev);
 
@@ -1038,7 +1039,7 @@  static int igt_reset_wait(void *arg)
 
 	reset_count = fake_hangcheck(gt, ALL_ENGINES);
 
-	timeout = i915_request_wait(rq, 0, 10);
+	timeout = igt_request_wait(rq, 0, 1);
 	if (timeout < 0) {
 		pr_err("i915_request_wait failed on a stuck request: err=%ld\n",
 		       timeout);
diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c
index 2a1b5a2e0ec5..60597bb7bf18 100644
--- a/drivers/gpu/drm/i915/gt/selftest_lrc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c
@@ -14,6 +14,7 @@ 
 #include "selftests/i915_random.h"
 #include "selftests/igt_flush_test.h"
 #include "selftests/igt_live_test.h"
+#include "selftests/igt_utils.h"
 #include "selftests/igt_spinner.h"
 #include "selftests/lib_sw_fence.h"
 
@@ -751,7 +752,7 @@  static int live_busywait_preempt(void *arg)
 		}
 
 		/* Low priority request should be busywaiting now */
-		if (i915_request_wait(lo, 0, 1) != -ETIME) {
+		if (igt_request_wait(lo, 0, 0) != -ETIME) {
 			pr_err("%s: Busywaiting request did not!\n",
 			       engine->name);
 			err = -EIO;
@@ -779,7 +780,7 @@  static int live_busywait_preempt(void *arg)
 		intel_ring_advance(hi, cs);
 		i915_request_add(hi);
 
-		if (i915_request_wait(lo, 0, HZ / 5) < 0) {
+		if (igt_request_wait(lo, 0, 2) < 0) {
 			struct drm_printer p = drm_info_printer(gt->i915->drm.dev);
 
 			pr_err("%s: Failed to preempt semaphore busywait!\n",
@@ -1201,7 +1202,7 @@  static int __cancel_active0(struct live_preempt_cancel *arg)
 	if (err)
 		goto out;
 
-	if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+	if (igt_request_wait(rq, 0, 2) < 0) {
 		err = -EIO;
 		goto out;
 	}
@@ -1266,7 +1267,7 @@  static int __cancel_active1(struct live_preempt_cancel *arg)
 		goto out;
 
 	igt_spinner_end(&arg->a.spin);
-	if (i915_request_wait(rq[1], 0, HZ / 5) < 0) {
+	if (igt_request_wait(rq[1], 0, 2) < 0) {
 		err = -EIO;
 		goto out;
 	}
@@ -1349,7 +1350,7 @@  static int __cancel_queued(struct live_preempt_cancel *arg)
 	if (err)
 		goto out;
 
-	if (i915_request_wait(rq[2], 0, HZ / 5) < 0) {
+	if (igt_request_wait(rq[2], 0, 2) < 0) {
 		err = -EIO;
 		goto out;
 	}
@@ -1410,7 +1411,7 @@  static int __cancel_hostile(struct live_preempt_cancel *arg)
 	if (err)
 		goto out;
 
-	if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+	if (igt_request_wait(rq, 0, 2) < 0) {
 		err = -EIO;
 		goto out;
 	}
@@ -1727,9 +1728,9 @@  static int live_suppress_wait_preempt(void *arg)
 			}
 			GEM_BUG_ON(!i915_request_started(rq[0]));
 
-			if (i915_request_wait(rq[depth],
-					      I915_WAIT_PRIORITY,
-					      1) != -ETIME) {
+			if (igt_request_wait(rq[depth],
+					     I915_WAIT_PRIORITY,
+					     0) != -ETIME) {
 				pr_err("%s: Waiter depth:%d completed!\n",
 				       engine->name, depth);
 				goto err_wedged;
@@ -1820,7 +1821,7 @@  static int live_chain_preempt(void *arg)
 			 __func__, engine->name, ring_size);
 
 		igt_spinner_end(&lo.spin);
-		if (i915_request_wait(rq, 0, HZ / 2) < 0) {
+		if (igt_request_wait(rq, 0, 5) < 0) {
 			pr_err("Timed out waiting to flush %s\n", engine->name);
 			goto err_wedged;
 		}
@@ -1861,7 +1862,7 @@  static int live_chain_preempt(void *arg)
 			engine->schedule(rq, &attr);
 
 			igt_spinner_end(&hi.spin);
-			if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+			if (igt_request_wait(rq, 0, 2) < 0) {
 				struct drm_printer p =
 					drm_info_printer(gt->i915->drm.dev);
 
@@ -1877,7 +1878,7 @@  static int live_chain_preempt(void *arg)
 			if (IS_ERR(rq))
 				goto err_wedged;
 			i915_request_add(rq);
-			if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+			if (igt_request_wait(rq, 0, 2) < 0) {
 				struct drm_printer p =
 					drm_info_printer(gt->i915->drm.dev);
 
@@ -2080,7 +2081,7 @@  static int live_preempt_gang(void *arg)
 			struct i915_request *n =
 				list_next_entry(rq, client_link);
 
-			if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0) {
+			if (err == 0 && igt_request_wait(rq, 0, 2) < 0) {
 				struct drm_printer p =
 					drm_info_printer(engine->i915->drm.dev);
 
@@ -2294,7 +2295,7 @@  static int live_preempt_timeout(void *arg)
 		intel_engine_flush_submission(engine);
 		engine->props.preempt_timeout_ms = saved_timeout;
 
-		if (i915_request_wait(rq, 0, HZ / 10) < 0) {
+		if (igt_request_wait(rq, 0, 1) < 0) {
 			intel_gt_set_wedged(gt);
 			i915_request_put(rq);
 			err = -ETIME;
@@ -2642,7 +2643,7 @@  static int nop_virtual_engine(struct intel_gt *gt,
 		}
 
 		for (nc = 0; nc < nctx; nc++) {
-			if (i915_request_wait(request[nc], 0, HZ / 10) < 0) {
+			if (igt_request_wait(request[nc], 0, 1) < 0) {
 				pr_err("%s(%s): wait for %llx:%lld timed out\n",
 				       __func__, ve[0]->engine->name,
 				       request[nc]->fence.context,
@@ -2779,7 +2780,7 @@  static int mask_virtual_engine(struct intel_gt *gt,
 	}
 
 	for (n = 0; n < nsibling; n++) {
-		if (i915_request_wait(request[n], 0, HZ / 10) < 0) {
+		if (igt_request_wait(request[n], 0, 1) < 0) {
 			pr_err("%s(%s): wait for %llx:%lld timed out\n",
 			       __func__, ve->engine->name,
 			       request[n]->fence.context,
@@ -2918,7 +2919,7 @@  static int preserved_virtual_engine(struct intel_gt *gt,
 		i915_request_add(rq);
 	}
 
-	if (i915_request_wait(last, 0, HZ / 5) < 0) {
+	if (igt_request_wait(last, 0, 2) < 0) {
 		err = -ETIME;
 		goto out_end;
 	}
@@ -3081,7 +3082,7 @@  static int bond_virtual_engine(struct intel_gt *gt,
 		}
 		onstack_fence_fini(&fence);
 
-		if (i915_request_wait(rq[0], 0, HZ / 10) < 0) {
+		if (igt_request_wait(rq[0], 0, 1) < 0) {
 			pr_err("Master request did not execute (on %s)!\n",
 			       rq[0]->engine->name);
 			err = -EIO;
@@ -3480,7 +3481,7 @@  static int __live_lrc_state(struct intel_engine_cs *engine,
 	intel_engine_flush_submission(engine);
 	expected[RING_TAIL_IDX] = ce->ring->tail;
 
-	if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+	if (igt_request_wait(rq, 0, 2) < 0) {
 		err = -ETIME;
 		goto err_rq;
 	}
@@ -3613,7 +3614,7 @@  static int __live_gpr_clear(struct intel_engine_cs *engine,
 	i915_request_get(rq);
 	i915_request_add(rq);
 
-	if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+	if (igt_request_wait(rq, 0, 2) < 0) {
 		err = -ETIME;
 		goto err_rq;
 	}
diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c
index 80cb3cbaad77..4deee6fd034f 100644
--- a/drivers/gpu/drm/i915/gt/selftest_mocs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c
@@ -10,6 +10,7 @@ 
 #include "gem/selftests/mock_context.h"
 #include "selftests/igt_reset.h"
 #include "selftests/igt_spinner.h"
+#include "selftests/igt_utils.h"
 
 struct live_mocs {
 	struct drm_i915_mocs_table table;
@@ -21,7 +22,7 @@  static int request_add_sync(struct i915_request *rq, int err)
 {
 	i915_request_get(rq);
 	i915_request_add(rq);
-	if (i915_request_wait(rq, 0, HZ / 5) < 0)
+	if (igt_request_wait(rq, 0, 2) < 0)
 		err = -ETIME;
 	i915_request_put(rq);
 
diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c
index f04a59fe5d2c..b2f5fa98f9d1 100644
--- a/drivers/gpu/drm/i915/gt/selftest_timeline.c
+++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c
@@ -17,6 +17,7 @@ 
 #include "../selftests/igt_flush_test.h"
 #include "../selftests/mock_gem_device.h"
 #include "selftests/mock_timeline.h"
+#include "selftests/igt_utils.h"
 
 static struct page *hwsp_page(struct intel_timeline *tl)
 {
@@ -725,7 +726,7 @@  static int live_hwsp_wrap(void *arg)
 
 		i915_request_add(rq);
 
-		if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+		if (igt_request_wait(rq, 0, 2) < 0) {
 			pr_err("Wait for timeline writes timed out!\n");
 			err = -EIO;
 			goto out;
@@ -792,7 +793,7 @@  static int live_hwsp_recycle(void *arg)
 				break;
 			}
 
-			if (i915_request_wait(rq, 0, HZ / 5) < 0) {
+			if (igt_request_wait(rq, 0, 2) < 0) {
 				pr_err("Wait for timeline writes timed out!\n");
 				i915_request_put(rq);
 				intel_timeline_put(tl);
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index ac1921854cbf..7d50ddd5e53b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -37,7 +37,7 @@  static int request_add_sync(struct i915_request *rq, int err)
 {
 	i915_request_get(rq);
 	i915_request_add(rq);
-	if (i915_request_wait(rq, 0, HZ / 5) < 0)
+	if (igt_request_wait(rq, 0, 2) < 0)
 		err = -EIO;
 	i915_request_put(rq);
 
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
index d94db487c4dd..a5f97c0c7fe0 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -35,6 +35,7 @@ 
 #include "mock_drm.h"
 #include "mock_gem_device.h"
 #include "igt_flush_test.h"
+#include "igt_utils.h"
 
 static void cleanup_freed_objects(struct drm_i915_private *i915)
 {
@@ -1732,7 +1733,7 @@  static int context_sync(struct intel_context *ce)
 	i915_request_get(rq);
 	i915_request_add(rq);
 
-	timeout = i915_request_wait(rq, 0, HZ / 5);
+	timeout = igt_request_wait(rq, 0, 2);
 	i915_request_put(rq);
 
 	return timeout < 0 ? -EIO : 0;
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
index d29f44cf3162..6ec8af565bb2 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -33,6 +33,7 @@ 
 #include "i915_selftest.h"
 #include "igt_live_test.h"
 #include "igt_spinner.h"
+#include "igt_utils.h"
 #include "lib_sw_fence.h"
 
 #include "mock_drm.h"
@@ -68,9 +69,9 @@  static int igt_add_request(void *arg)
 
 static int igt_wait_request(void *arg)
 {
-	const long T = HZ / 4;
 	struct drm_i915_private *i915 = arg;
 	struct i915_request *request;
+	const unsigned long T = igt_request_timeout(i915->gt.engine[RCS0], 2);
 	int err = -EINVAL;
 
 	/* Submit a request, then wait upon it */
@@ -231,8 +232,7 @@  static int igt_request_rewind(void *arg)
 	request->engine->submit_request(request);
 	rcu_read_unlock();
 
-
-	if (i915_request_wait(vip, 0, HZ) == -ETIME) {
+	if (igt_request_wait(vip, 0, 10) == -ETIME) {
 		pr_err("timed out waiting for high priority request\n");
 		goto err;
 	}
@@ -1078,7 +1078,7 @@  static int __live_parallel_engine1(void *arg)
 		i915_request_add(rq);
 
 		err = 0;
-		if (i915_request_wait(rq, 0, HZ / 5) < 0)
+		if (igt_request_wait(rq, 0, 2) < 0)
 			err = -ETIME;
 		i915_request_put(rq);
 		if (err)
@@ -1176,7 +1176,7 @@  static int __live_parallel_spin(void *arg)
 	}
 	igt_spinner_end(&spin);
 
-	if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0)
+	if (err == 0 && igt_request_wait(rq, 0, 2) < 0)
 		err = -EIO;
 	i915_request_put(rq);
 
diff --git a/drivers/gpu/drm/i915/selftests/igt_utils.c b/drivers/gpu/drm/i915/selftests/igt_utils.c
new file mode 100644
index 000000000000..faf68a649da6
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/igt_utils.c
@@ -0,0 +1,44 @@ 
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2019 Intel Corporation
+ */
+
+#include <linux/jiffies.h>
+#include <linux/log2.h>
+
+#include "gt/intel_engine.h"
+#include "i915_drv.h" /* for_each_engine_masked() */
+#include "i915_request.h"
+#include "igt_utils.h"
+
+unsigned long igt_request_timeout(struct intel_engine_cs *engine,
+				  unsigned int factor)
+{
+	unsigned long base;
+
+	if (is_power_of_2(engine->mask)) {
+		base = ewma_delay_read(&engine->delay);
+	} else {
+		intel_engine_mask_t mask = engine->mask, tmp;
+		unsigned int n = 0;
+
+		base = 0;
+		for_each_engine_masked(engine, engine->gt, mask, tmp)
+			base += ewma_delay_read(&engine->delay), n++;
+		base /= n;
+	}
+
+	if (factor)
+		base *= factor * 10;
+
+	return usecs_to_jiffies(base) + 1;
+}
+
+int igt_request_wait(struct i915_request *rq,
+		     unsigned int flags,
+		     unsigned int factor)
+{
+	return i915_request_wait(rq, flags,
+				 igt_request_timeout(rq->engine, factor));
+}
diff --git a/drivers/gpu/drm/i915/selftests/igt_utils.h b/drivers/gpu/drm/i915/selftests/igt_utils.h
new file mode 100644
index 000000000000..b92fd1b511de
--- /dev/null
+++ b/drivers/gpu/drm/i915/selftests/igt_utils.h
@@ -0,0 +1,20 @@ 
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2019 Intel Corporation
+ */
+
+#ifndef __I915_SELFTESTS_IGT_UTILS_H__
+#define __I915_SELFTESTS_IGT_UTILS_H__
+
+struct intel_engine_cs;
+struct i915_request;
+
+unsigned long igt_request_timeout(struct intel_engine_cs *engine,
+				  unsigned int factor);
+
+int igt_request_wait(struct i915_request *rq,
+		     unsigned int flags,
+		     unsigned int factor);
+
+#endif /* __I915_SELFTESTS_IGT_UTILS_H__ */