@@ -71,26 +71,23 @@ static void trigger_reset(int fd)
gem_quiescent_gpu(fd);
}
-static void wedge_gpu(int fd)
+static void manual_hang(int drm_fd)
{
- /* First idle the GPU then disable GPU resets before injecting a hang */
- gem_quiescent_gpu(fd);
-
- igt_require(i915_reset_control(false));
+ int dir = igt_debugfs_dir(drm_fd);
- igt_debug("Wedging GPU by injecting hang\n");
- igt_post_hang_ring(fd, igt_hang_ring(fd, I915_EXEC_DEFAULT));
+ igt_sysfs_set(dir, "i915_wedged", "-1");
- igt_assert(i915_reset_control(true));
+ close(dir);
}
-static void wedgeme(int drm_fd)
+static void wedge_gpu(int fd)
{
- int dir = igt_debugfs_dir(drm_fd);
-
- igt_sysfs_set(dir, "i915_wedged", "-1");
+ /* First idle the GPU then disable GPU resets before injecting a hang */
+ gem_quiescent_gpu(fd);
- close(dir);
+ igt_require(i915_reset_control(false));
+ manual_hang(fd);
+ igt_assert(i915_reset_control(true));
}
static int __gem_throttle(int fd)
@@ -149,29 +146,66 @@ static int __gem_wait(int fd, uint32_t handle, int64_t timeout)
return err;
}
+static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags)
+{
+ if (gem_can_store_dword(fd, flags))
+ return __igt_spin_batch_new_poll(fd, ctx, flags);
+ else
+ return __igt_spin_batch_new(fd, ctx, flags, 0);
+}
+
+static void __spin_wait(int fd, igt_spin_t *spin)
+{
+ if (spin->running) {
+ while (!*((volatile bool *)spin->running))
+ ;
+ } else {
+ igt_debug("__spin_wait - usleep mode\n");
+ usleep(500e3); /* Better than nothing! */
+ }
+}
+
+/*
+ * Wedge the GPU when we know our batch is running.
+ */
+static void wedge_after_running(int fd, igt_spin_t *spin)
+{
+ __spin_wait(fd, spin);
+ manual_hang(fd);
+}
+
static void test_wait(int fd)
{
- igt_hang_t hang;
+ struct timespec ts = { };
+ igt_spin_t *hang;
igt_require_gem(fd);
+ igt_nsec_elapsed(&ts);
+
/* If the request we wait on completes due to a hang (even for
* that request), the user expects the return value to 0 (success).
*/
- hang = igt_hang_ring(fd, I915_EXEC_DEFAULT);
- igt_assert_eq(__gem_wait(fd, hang.handle, -1), 0);
- igt_post_hang_ring(fd, hang);
+ igt_require(i915_reset_control(true));
+ hang = __spin_poll(fd, 0, I915_EXEC_DEFAULT);
+ wedge_after_running(fd, hang);
+ igt_assert_eq(__gem_wait(fd, hang->handle, -1), 0);
+ igt_spin_batch_free(fd, hang);
/* If the GPU is wedged during the wait, again we expect the return
* value to be 0 (success).
*/
igt_require(i915_reset_control(false));
- hang = igt_hang_ring(fd, I915_EXEC_DEFAULT);
- igt_assert_eq(__gem_wait(fd, hang.handle, -1), 0);
- igt_post_hang_ring(fd, hang);
+ hang = __spin_poll(fd, 0, I915_EXEC_DEFAULT);
+ wedge_after_running(fd, hang);
+ igt_assert_eq(__gem_wait(fd, hang->handle, -1), 0);
+ igt_spin_batch_free(fd, hang);
igt_require(i915_reset_control(true));
trigger_reset(fd);
+
+ /* HACK for CI */
+ igt_assert(igt_nsec_elapsed(&ts) < 5e9);
}
static void test_suspend(int fd, int state)
@@ -181,7 +215,7 @@ static void test_suspend(int fd, int state)
/* Check we can suspend when the driver is already wedged */
igt_require(i915_reset_control(false));
- wedgeme(fd);
+ manual_hang(fd);
igt_system_suspend_autoresume(state, SUSPEND_TEST_DEVICES);
@@ -209,11 +243,10 @@ static void test_inflight(int fd)
int fence[64]; /* conservative estimate of ring size */
gem_quiescent_gpu(fd);
-
igt_debug("Starting %s on engine '%s'\n", __func__, e__->name);
igt_require(i915_reset_control(false));
- hang = __igt_spin_batch_new(fd, 0, engine, 0);
+ hang = __spin_poll(fd, 0, engine);
obj[0].handle = hang->handle;
memset(&execbuf, 0, sizeof(execbuf));
@@ -227,6 +260,8 @@ static void test_inflight(int fd)
igt_assert(fence[n] != -1);
}
+ wedge_after_running(fd, hang);
+
igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0);
for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) {
igt_assert_eq(sync_fence_status(fence[n]), -EIO);
@@ -256,7 +291,7 @@ static void test_inflight_suspend(int fd)
obj[1].handle = gem_create(fd, 4096);
gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe));
- hang = __igt_spin_batch_new(fd, 0, 0, 0);
+ hang = __spin_poll(fd, 0, 0);
obj[0].handle = hang->handle;
memset(&execbuf, 0, sizeof(execbuf));
@@ -273,6 +308,8 @@ static void test_inflight_suspend(int fd)
igt_set_autoresume_delay(30);
igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE);
+ wedge_after_running(fd, hang);
+
igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0);
for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) {
igt_assert_eq(sync_fence_status(fence[n]), -EIO);
@@ -330,7 +367,7 @@ static void test_inflight_contexts(int fd)
igt_debug("Starting %s on engine '%s'\n", __func__, e__->name);
igt_require(i915_reset_control(false));
- hang = __igt_spin_batch_new(fd, 0, engine, 0);
+ hang = __spin_poll(fd, ctx[0], engine);
obj[0].handle = hang->handle;
memset(&execbuf, 0, sizeof(execbuf));
@@ -345,6 +382,8 @@ static void test_inflight_contexts(int fd)
igt_assert(fence[n] != -1);
}
+ wedge_after_running(fd, hang);
+
igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0);
for (unsigned int n = 0; n < ARRAY_SIZE(fence); n++) {
igt_assert_eq(sync_fence_status(fence[n]), -EIO);
@@ -375,7 +414,7 @@ static void test_inflight_external(int fd)
fence = igt_cork_plug(&cork, fd);
igt_require(i915_reset_control(false));
- hang = __igt_spin_batch_new(fd, 0, 0, 0);
+ hang = __spin_poll(fd, 0, 0);
memset(&obj, 0, sizeof(obj));
obj.handle = gem_create(fd, 4096);
@@ -393,6 +432,8 @@ static void test_inflight_external(int fd)
fence = execbuf.rsvd2 >> 32;
igt_assert(fence != -1);
+ wedge_after_running(fd, hang);
+
gem_sync(fd, hang->handle); /* wedged, with an unready batch */
igt_assert(!gem_bo_busy(fd, hang->handle));
igt_assert(gem_bo_busy(fd, obj.handle));
@@ -420,7 +461,7 @@ static void test_inflight_internal(int fd)
igt_require(gem_has_exec_fence(fd));
igt_require(i915_reset_control(false));
- hang = __igt_spin_batch_new(fd, 0, 0, 0);
+ hang = __spin_poll(fd, 0, 0);
memset(obj, 0, sizeof(obj));
obj[0].handle = hang->handle;
@@ -441,6 +482,8 @@ static void test_inflight_internal(int fd)
nfence++;
}
+ wedge_after_running(fd, hang);
+
igt_assert_eq(__gem_wait(fd, obj[1].handle, -1), 0);
while (nfence--) {
igt_assert_eq(sync_fence_status(fences[nfence]), -EIO);