[igt-dev] [PATCH i-g-t 1/2] lib/dummyload: Allow spin batches to be restarted
Tvrtko Ursulin
tursulin at ursulin.net
Wed Jan 31 12:34:40 UTC 2018
From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
This adds the igt_spin_batch_restart API so same spin batch can be
re-used in tests which care about low setup cost.
Batch will be re-submited in the manner completely identical to as
it was originally submitted.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
---
lib/igt_dummyload.c | 150 +++++++++++++++++++++++++++++++++-------------------
lib/igt_dummyload.h | 9 ++++
2 files changed, 106 insertions(+), 53 deletions(-)
diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 27eb402bb699..102efd197e5b 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -71,6 +71,35 @@ fill_reloc(struct drm_i915_gem_relocation_entry *reloc,
reloc->write_domain = write_domains;
}
+static int __igt_spin_batch_submit(int fd, igt_spin_t *spin)
+{
+ int fence_fd = -1;
+ unsigned int i;
+
+ for (i = 0; i < spin->nengine; i++) {
+ spin->execbuf.flags &= ~ENGINE_MASK;
+ spin->execbuf.flags |= spin->engines[i];
+ gem_execbuf_wr(fd, &spin->execbuf);
+ if (spin->out_fence_requested) {
+ int _fd = spin->execbuf.rsvd2 >> 32;
+
+ igt_assert(_fd >= 0);
+ if (fence_fd == -1) {
+ fence_fd = _fd;
+ } else {
+ int old_fd = fence_fd;
+
+ fence_fd = sync_fence_merge(old_fd, _fd);
+ close(old_fd);
+ close(_fd);
+ }
+ igt_assert(fence_fd >= 0);
+ }
+ }
+
+ return fence_fd;
+}
+
static int emit_recursive_batch(igt_spin_t *spin,
int fd, uint32_t ctx, unsigned engine,
uint32_t dep, bool out_fence)
@@ -78,52 +107,46 @@ static int emit_recursive_batch(igt_spin_t *spin,
#define SCRATCH 0
#define BATCH 1
const int gen = intel_gen(intel_get_drm_devid(fd));
- struct drm_i915_gem_exec_object2 obj[2];
- struct drm_i915_gem_relocation_entry relocs[2];
- struct drm_i915_gem_execbuffer2 execbuf;
- unsigned int engines[16];
- unsigned int nengine;
- int fence_fd = -1;
uint32_t *batch;
- int i;
- nengine = 0;
+ spin->nengine = 0;
if (engine == -1) {
for_each_engine(fd, engine)
if (engine)
- engines[nengine++] = engine;
+ spin->engines[spin->nengine++] = engine;
} else {
gem_require_ring(fd, engine);
- engines[nengine++] = engine;
+ spin->engines[spin->nengine++] = engine;
}
- igt_require(nengine);
+ igt_require(spin->nengine);
- memset(&execbuf, 0, sizeof(execbuf));
- memset(obj, 0, sizeof(obj));
- memset(relocs, 0, sizeof(relocs));
+ memset(&spin->execbuf, 0, sizeof(spin->execbuf));
+ memset(spin->obj, 0, sizeof(spin->obj));
+ memset(spin->relocs, 0, sizeof(spin->relocs));
- obj[BATCH].handle = gem_create(fd, BATCH_SIZE);
- batch = __gem_mmap__wc(fd, obj[BATCH].handle,
+ spin->obj[BATCH].handle = gem_create(fd, BATCH_SIZE);
+ batch = __gem_mmap__wc(fd, spin->obj[BATCH].handle,
0, BATCH_SIZE, PROT_WRITE);
if (!batch)
- batch = __gem_mmap__gtt(fd, obj[BATCH].handle,
+ batch = __gem_mmap__gtt(fd, spin->obj[BATCH].handle,
BATCH_SIZE, PROT_WRITE);
- gem_set_domain(fd, obj[BATCH].handle,
+ gem_set_domain(fd, spin->obj[BATCH].handle,
I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
- execbuf.buffer_count++;
+ spin->execbuf.buffer_count++;
if (dep) {
/* dummy write to dependency */
- obj[SCRATCH].handle = dep;
- fill_reloc(&relocs[obj[BATCH].relocation_count++],
+ spin->obj[SCRATCH].handle = dep;
+ fill_reloc(&spin->relocs[spin->obj[BATCH].relocation_count++],
dep, 1020,
I915_GEM_DOMAIN_RENDER,
I915_GEM_DOMAIN_RENDER);
- execbuf.buffer_count++;
+ spin->execbuf.buffer_count++;
}
spin->batch = batch;
- spin->handle = obj[BATCH].handle;
+ spin->handle = spin->obj[BATCH].handle;
+ spin->out_fence_requested = out_fence;
/* Allow ourselves to be preempted */
*batch++ = MI_ARB_CHK;
@@ -142,8 +165,8 @@ static int emit_recursive_batch(igt_spin_t *spin,
batch += 1000;
/* recurse */
- fill_reloc(&relocs[obj[BATCH].relocation_count],
- obj[BATCH].handle, (batch - spin->batch) + 1,
+ fill_reloc(&spin->relocs[spin->obj[BATCH].relocation_count],
+ spin->obj[BATCH].handle, (batch - spin->batch) + 1,
I915_GEM_DOMAIN_COMMAND, 0);
if (gen >= 8) {
*batch++ = MI_BATCH_BUFFER_START | 1 << 8 | 1;
@@ -157,41 +180,21 @@ static int emit_recursive_batch(igt_spin_t *spin,
*batch = 0;
if (gen < 4) {
*batch |= 1;
- relocs[obj[BATCH].relocation_count].delta = 1;
+ spin->relocs[spin->obj[BATCH].relocation_count].delta = 1;
}
batch++;
}
- obj[BATCH].relocation_count++;
- obj[BATCH].relocs_ptr = to_user_pointer(relocs);
+ spin->obj[BATCH].relocation_count++;
+ spin->obj[BATCH].relocs_ptr = to_user_pointer(spin->relocs);
- execbuf.buffers_ptr = to_user_pointer(obj + (2 - execbuf.buffer_count));
- execbuf.rsvd1 = ctx;
+ spin->execbuf.buffers_ptr =
+ to_user_pointer(spin->obj + (2 - spin->execbuf.buffer_count));
+ spin->execbuf.rsvd1 = ctx;
if (out_fence)
- execbuf.flags |= I915_EXEC_FENCE_OUT;
-
- for (i = 0; i < nengine; i++) {
- execbuf.flags &= ~ENGINE_MASK;
- execbuf.flags |= engines[i];
- gem_execbuf_wr(fd, &execbuf);
- if (out_fence) {
- int _fd = execbuf.rsvd2 >> 32;
-
- igt_assert(_fd >= 0);
- if (fence_fd == -1) {
- fence_fd = _fd;
- } else {
- int old_fd = fence_fd;
-
- fence_fd = sync_fence_merge(old_fd, _fd);
- close(old_fd);
- close(_fd);
- }
- igt_assert(fence_fd >= 0);
- }
- }
+ spin->execbuf.flags |= I915_EXEC_FENCE_OUT;
- return fence_fd;
+ return __igt_spin_batch_submit(fd, spin);
}
static igt_spin_t *
@@ -273,6 +276,47 @@ igt_spin_batch_new_fence(int fd, uint32_t ctx, unsigned engine)
return __igt_spin_batch_new_fence(fd, ctx, engine);
}
+/**
+ * __igt_spin_batch_restart:
+ * @fd: open i915 drm file descriptor
+ * @spin: spin batch state from igt_spin_batch_new()
+ *
+ * Restarts the spin batch which was previously ended either explicitly
+ * or via timeout.
+ *
+ * This version does not verify that the batch is currently idle.
+ *
+ * Returns:
+ * New fence fd if spin batch was originaly created as requesting the
+ * output fence.
+ */
+int __igt_spin_batch_restart(int fd, igt_spin_t *spin)
+{
+ *spin->batch = MI_ARB_CHK;
+ __sync_synchronize();
+
+ return __igt_spin_batch_submit(fd, spin);
+}
+
+/**
+ * igt_spin_batch_restart:
+ * @fd: open i915 drm file descriptor
+ * @spin: spin batch state from igt_spin_batch_new()
+ *
+ * Restarts the spin batch which was previously ended either explicitly
+ * or via timeout.
+ *
+ * Returns:
+ * New fence fd if spin batch was originaly created as requesting the
+ * output fence.
+ */
+int igt_spin_batch_restart(int fd, igt_spin_t *spin)
+{
+ igt_assert(!gem_bo_busy(fd, spin->handle));
+
+ return __igt_spin_batch_restart(fd, spin);
+}
+
static void notify(union sigval arg)
{
igt_spin_t *spin = arg.sival_ptr;
diff --git a/lib/igt_dummyload.h b/lib/igt_dummyload.h
index ffa7e351dea3..b9f201d4afb6 100644
--- a/lib/igt_dummyload.h
+++ b/lib/igt_dummyload.h
@@ -36,6 +36,12 @@ typedef struct igt_spin {
struct igt_list link;
uint32_t *batch;
int out_fence;
+ struct drm_i915_gem_exec_object2 obj[2];
+ struct drm_i915_gem_relocation_entry relocs[2];
+ struct drm_i915_gem_execbuffer2 execbuf;
+ unsigned int engines[16];
+ unsigned int nengine;
+ bool out_fence_requested;
} igt_spin_t;
igt_spin_t *__igt_spin_batch_new(int fd,
@@ -55,6 +61,9 @@ igt_spin_t *igt_spin_batch_new_fence(int fd,
uint32_t ctx,
unsigned engine);
+int __igt_spin_batch_restart(int fd, igt_spin_t *spin);
+int igt_spin_batch_restart(int fd, igt_spin_t *spin);
+
void igt_spin_batch_set_timeout(igt_spin_t *spin, int64_t ns);
void igt_spin_batch_end(igt_spin_t *spin);
void igt_spin_batch_free(int fd, igt_spin_t *spin);
--
2.14.1
More information about the igt-dev
mailing list