All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing
@ 2019-11-22 13:02 Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 01/10] lib/syncobj: drop local declarations Lionel Landwerlin
                   ` (12 more replies)
  0 siblings, 13 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

Hi all,

This revision updates the mmio_base query by parsing debugfs as well
as addresses the comments from Chris on v1.

Cheers,

Chunming Zhou (1):
  igt: add timeline test cases

Lionel Landwerlin (9):
  lib/syncobj: drop local declarations
  drm-uapi: Update drm headers to
    17cc51390c141662748dbbc2fe98f3ed10f2e13e
  tests/syncobj_timeline: add more timeline tests
  tests/i915/exec_fence: switch to internal headers
  tests/i915/exec_fence: reuse syncobj helpers
  include: bump drm headers for i915 timeline semaphores
  tests/i915/exec_fence: add timeline fence tests
  lib/i915: Parse mmio base from debugfs
  tests/i915/gem_exec_fence: add engine chaining tests

 include/drm-uapi/amdgpu_drm.h   |   71 +-
 include/drm-uapi/drm.h          |   56 +
 include/drm-uapi/drm_fourcc.h   |   28 +-
 include/drm-uapi/drm_mode.h     |  122 +-
 include/drm-uapi/etnaviv_drm.h  |   10 +-
 include/drm-uapi/exynos_drm.h   |    2 +-
 include/drm-uapi/i915_drm.h     |   64 +-
 include/drm-uapi/msm_drm.h      |   14 +
 include/drm-uapi/nouveau_drm.h  |   51 +
 include/drm-uapi/omap_drm.h     |   18 +-
 include/drm-uapi/panfrost_drm.h |   88 ++
 include/drm-uapi/v3d_drm.h      |   36 +-
 lib/i915/gem_engine_topology.c  |   62 ++
 lib/i915/gem_engine_topology.h  |    5 +
 lib/igt_syncobj.c               |  281 ++++-
 lib/igt_syncobj.h               |   48 +-
 lib/intel_reg.h                 |    2 +
 tests/i915/gem_ctx_shared.c     |   38 +-
 tests/i915/gem_exec_fence.c     | 1859 +++++++++++++++++++++++++------
 tests/i915/gem_exec_latency.c   |   17 +-
 tests/meson.build               |    1 +
 tests/syncobj_basic.c           |    2 +-
 tests/syncobj_timeline.c        | 1537 +++++++++++++++++++++++++
 tests/syncobj_wait.c            |   58 +-
 24 files changed, 3998 insertions(+), 472 deletions(-)
 create mode 100644 tests/syncobj_timeline.c

--
2.24.0
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 01/10] lib/syncobj: drop local declarations
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 02/10] drm-uapi: Update drm headers to 17cc51390c141662748dbbc2fe98f3ed10f2e13e Lionel Landwerlin
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

We have copies of the DRM uAPI headers in the repo, so drop the local
declaration of syncobj defines/types.

v2: s/drmIoctl/igt_ioctl/ (Chris)
    Clear errno after report it through return value (Chris)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 lib/igt_syncobj.c     | 45 ++++++++++++++++++++++++---------
 lib/igt_syncobj.h     | 26 +------------------
 tests/syncobj_basic.c |  2 +-
 tests/syncobj_wait.c  | 58 +++++++++++++++++++++----------------------
 4 files changed, 64 insertions(+), 67 deletions(-)

diff --git a/lib/igt_syncobj.c b/lib/igt_syncobj.c
index 0fddb97a..ad23faaf 100644
--- a/lib/igt_syncobj.c
+++ b/lib/igt_syncobj.c
@@ -43,8 +43,11 @@ __syncobj_create(int fd, uint32_t *handle, uint32_t flags)
 	int err = 0;
 
 	create.flags = flags;
-	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &create))
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &create)) {
 		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
 	*handle = create.handle;
 	return err;
 }
@@ -74,8 +77,11 @@ __syncobj_destroy(int fd, uint32_t handle)
 	int err = 0;
 
 	destroy.handle = handle;
-	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy))
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy)) {
 		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
 	return err;
 }
 
@@ -95,8 +101,11 @@ int
 __syncobj_handle_to_fd(int fd, struct drm_syncobj_handle *args)
 {
 	int err = 0;
-	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args))
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args)) {
 		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
 	return err;
 }
 
@@ -125,8 +134,11 @@ int
 __syncobj_fd_to_handle(int fd, struct drm_syncobj_handle *args)
 {
 	int err = 0;
-	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args))
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args)) {
 		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
 	return err;
 }
 
@@ -170,11 +182,14 @@ syncobj_import_sync_file(int fd, uint32_t handle, int sync_file)
 }
 
 int
-__syncobj_wait(int fd, struct local_syncobj_wait *args)
+__syncobj_wait(int fd, struct drm_syncobj_wait *args)
 {
 	int err = 0;
-	if (drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_WAIT, args))
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, args)) {
 		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
 	return err;
 }
 
@@ -182,7 +197,7 @@ int
 syncobj_wait_err(int fd, uint32_t *handles, uint32_t count,
 		 uint64_t abs_timeout_nsec, uint32_t flags)
 {
-	struct local_syncobj_wait wait;
+	struct drm_syncobj_wait wait;
 
 	wait.handles = to_user_pointer(handles);
 	wait.timeout_nsec = abs_timeout_nsec;
@@ -212,7 +227,7 @@ syncobj_wait(int fd, uint32_t *handles, uint32_t count,
 	     uint64_t abs_timeout_nsec, uint32_t flags,
 	     uint32_t *first_signaled)
 {
-	struct local_syncobj_wait wait;
+	struct drm_syncobj_wait wait;
 	int ret;
 
 	wait.handles = to_user_pointer(handles);
@@ -236,13 +251,16 @@ syncobj_wait(int fd, uint32_t *handles, uint32_t count,
 static int
 __syncobj_reset(int fd, uint32_t *handles, uint32_t count)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	int err = 0;
 
 	array.handles = to_user_pointer(handles);
 	array.count_handles = count;
-	if (drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_RESET, &array))
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &array)) {
 		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
 	return err;
 }
 
@@ -263,13 +281,16 @@ syncobj_reset(int fd, uint32_t *handles, uint32_t count)
 static int
 __syncobj_signal(int fd, uint32_t *handles, uint32_t count)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	int err = 0;
 
 	array.handles = to_user_pointer(handles);
 	array.count_handles = count;
-	if (drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_SIGNAL, &array))
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &array)) {
 		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
 	return err;
 }
 
diff --git a/lib/igt_syncobj.h b/lib/igt_syncobj.h
index 44d1378d..51ad2364 100644
--- a/lib/igt_syncobj.h
+++ b/lib/igt_syncobj.h
@@ -28,30 +28,6 @@
 #include <stdbool.h>
 #include <drm.h>
 
-#define LOCAL_SYNCOBJ_CREATE_SIGNALED (1 << 0)
-
-#define LOCAL_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
-#define LOCAL_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
-struct local_syncobj_wait {
-       __u64 handles;
-       /* absolute timeout */
-       __s64 timeout_nsec;
-       __u32 count_handles;
-       __u32 flags;
-       __u32 first_signaled; /* only valid when not waiting all */
-       __u32 pad;
-};
-
-struct local_syncobj_array {
-       __u64 handles;
-       __u32 count_handles;
-       __u32 pad;
-};
-
-#define LOCAL_IOCTL_SYNCOBJ_WAIT	DRM_IOWR(0xC3, struct local_syncobj_wait)
-#define LOCAL_IOCTL_SYNCOBJ_RESET	DRM_IOWR(0xC4, struct local_syncobj_array)
-#define LOCAL_IOCTL_SYNCOBJ_SIGNAL	DRM_IOWR(0xC5, struct local_syncobj_array)
-
 uint32_t syncobj_create(int fd, uint32_t flags);
 void syncobj_destroy(int fd, uint32_t handle);
 int __syncobj_handle_to_fd(int fd, struct drm_syncobj_handle *args);
@@ -59,7 +35,7 @@ int __syncobj_fd_to_handle(int fd, struct drm_syncobj_handle *args);
 int syncobj_handle_to_fd(int fd, uint32_t handle, uint32_t flags);
 uint32_t syncobj_fd_to_handle(int fd, int syncobj_fd, uint32_t flags);
 void syncobj_import_sync_file(int fd, uint32_t handle, int sync_file);
-int __syncobj_wait(int fd, struct local_syncobj_wait *args);
+int __syncobj_wait(int fd, struct drm_syncobj_wait *args);
 int syncobj_wait_err(int fd, uint32_t *handles, uint32_t count,
 		     uint64_t abs_timeout_nsec, uint32_t flags);
 bool syncobj_wait(int fd, uint32_t *handles, uint32_t count,
diff --git a/tests/syncobj_basic.c b/tests/syncobj_basic.c
index 44769d3b..1dce45c9 100644
--- a/tests/syncobj_basic.c
+++ b/tests/syncobj_basic.c
@@ -149,7 +149,7 @@ test_bad_create_flags(int fd)
 static void
 test_create_signaled(int fd)
 {
-	uint32_t syncobj = syncobj_create(fd, LOCAL_SYNCOBJ_CREATE_SIGNALED);
+	uint32_t syncobj = syncobj_create(fd, DRM_SYNCOBJ_CREATE_SIGNALED);
 
 	igt_assert_eq(syncobj_wait_err(fd, &syncobj, 1, 0, 0), 0);
 
diff --git a/tests/syncobj_wait.c b/tests/syncobj_wait.c
index 04d79de7..669d0adf 100644
--- a/tests/syncobj_wait.c
+++ b/tests/syncobj_wait.c
@@ -140,7 +140,7 @@ syncobj_trigger_delayed(int fd, uint32_t syncobj, uint64_t nsec)
 static void
 test_wait_bad_flags(int fd)
 {
-	struct local_syncobj_wait wait = { 0 };
+	struct drm_syncobj_wait wait = { 0 };
 	wait.flags = 0xdeadbeef;
 	igt_assert_eq(__syncobj_wait(fd, &wait), -EINVAL);
 }
@@ -148,14 +148,14 @@ test_wait_bad_flags(int fd)
 static void
 test_wait_zero_handles(int fd)
 {
-	struct local_syncobj_wait wait = { 0 };
+	struct drm_syncobj_wait wait = { 0 };
 	igt_assert_eq(__syncobj_wait(fd, &wait), -EINVAL);
 }
 
 static void
 test_wait_illegal_handle(int fd)
 {
-	struct local_syncobj_wait wait = { 0 };
+	struct drm_syncobj_wait wait = { 0 };
 	uint32_t handle = 0;
 
 	wait.count_handles = 1;
@@ -166,43 +166,43 @@ test_wait_illegal_handle(int fd)
 static void
 test_reset_zero_handles(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	int ret;
 
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_RESET, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &array);
 	igt_assert(ret == -1 && errno ==  EINVAL);
 }
 
 static void
 test_reset_illegal_handle(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	uint32_t handle = 0;
 	int ret;
 
 	array.count_handles = 1;
 	array.handles = to_user_pointer(&handle);
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_RESET, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &array);
 	igt_assert(ret == -1 && errno == ENOENT);
 }
 
 static void
 test_reset_one_illegal_handle(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	uint32_t syncobjs[3];
 	int ret;
 
-	syncobjs[0] = syncobj_create(fd, LOCAL_SYNCOBJ_CREATE_SIGNALED);
+	syncobjs[0] = syncobj_create(fd, DRM_SYNCOBJ_CREATE_SIGNALED);
 	syncobjs[1] = 0;
-	syncobjs[2] = syncobj_create(fd, LOCAL_SYNCOBJ_CREATE_SIGNALED);
+	syncobjs[2] = syncobj_create(fd, DRM_SYNCOBJ_CREATE_SIGNALED);
 
 	igt_assert_eq(syncobj_wait_err(fd, &syncobjs[0], 1, 0, 0), 0);
 	igt_assert_eq(syncobj_wait_err(fd, &syncobjs[2], 1, 0, 0), 0);
 
 	array.count_handles = 3;
 	array.handles = to_user_pointer(syncobjs);
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_RESET, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &array);
 	igt_assert(ret == -1 && errno == ENOENT);
 
 	/* Assert that we didn't actually reset anything */
@@ -216,44 +216,44 @@ test_reset_one_illegal_handle(int fd)
 static void
 test_reset_bad_pad(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	uint32_t handle = 0;
 	int ret;
 
 	array.pad = 0xdeadbeef;
 	array.count_handles = 1;
 	array.handles = to_user_pointer(&handle);
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_RESET, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_RESET, &array);
 	igt_assert(ret == -1 && errno == EINVAL);
 }
 
 static void
 test_signal_zero_handles(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	int ret;
 
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_SIGNAL, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &array);
 	igt_assert(ret == -1 && errno == EINVAL);
 }
 
 static void
 test_signal_illegal_handle(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	uint32_t handle = 0;
 	int ret;
 
 	array.count_handles = 1;
 	array.handles = to_user_pointer(&handle);
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_SIGNAL, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &array);
 	igt_assert(ret == -1 && errno == ENOENT);
 }
 
 static void
 test_signal_one_illegal_handle(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	uint32_t syncobjs[3];
 	int ret;
 
@@ -266,7 +266,7 @@ test_signal_one_illegal_handle(int fd)
 
 	array.count_handles = 3;
 	array.handles = to_user_pointer(syncobjs);
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_SIGNAL, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &array);
 	igt_assert(ret == -1 && errno == ENOENT);
 
 	/* Assert that we didn't actually reset anything */
@@ -280,14 +280,14 @@ test_signal_one_illegal_handle(int fd)
 static void
 test_signal_bad_pad(int fd)
 {
-	struct local_syncobj_array array = { 0 };
+	struct drm_syncobj_array array = { 0 };
 	uint32_t handle = 0;
 	int ret;
 
 	array.pad = 0xdeadbeef;
 	array.count_handles = 1;
 	array.handles = to_user_pointer(&handle);
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_SIGNAL, &array);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &array);
 	igt_assert(ret == -1 && errno ==  EINVAL);
 }
 
@@ -304,10 +304,10 @@ flags_for_test_flags(uint32_t test_flags)
 	uint32_t flags = 0;
 
 	if (test_flags & WAIT_FOR_SUBMIT)
-		flags |= LOCAL_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+		flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
 
 	if (test_flags & WAIT_ALL)
-		flags |= LOCAL_SYNCOBJ_WAIT_FLAGS_WAIT_ALL;
+		flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL;
 
 	return flags;
 }
@@ -432,7 +432,7 @@ static void
 test_reset_during_wait_for_submit(int fd)
 {
 	uint32_t syncobj = syncobj_create(fd, 0);
-	uint32_t flags = LOCAL_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+	uint32_t flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
 	struct fd_handle_pair pair;
 	timer_t timer;
 
@@ -454,7 +454,7 @@ static void
 test_signal(int fd)
 {
 	uint32_t syncobj = syncobj_create(fd, 0);
-	uint32_t flags = LOCAL_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+	uint32_t flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
 
 	igt_assert_eq(syncobj_wait_err(fd, &syncobj, 1, 0, 0), -EINVAL);
 	igt_assert_eq(syncobj_wait_err(fd, &syncobj, 1, 0, flags), -ETIME);
@@ -511,7 +511,7 @@ test_multi_wait(int fd, uint32_t test_flags, int expect)
 
 struct wait_thread_data {
 	int fd;
-	struct local_syncobj_wait wait;
+	struct drm_syncobj_wait wait;
 };
 
 static void *
@@ -713,7 +713,7 @@ test_wait_complex(int fd, uint32_t test_flags)
 static void
 test_wait_interrupted(int fd, uint32_t test_flags)
 {
-	struct local_syncobj_wait wait = { 0 };
+	struct drm_syncobj_wait wait = { 0 };
 	uint32_t syncobj = syncobj_create(fd, 0);
 	int timeline;
 
@@ -740,7 +740,7 @@ test_wait_interrupted(int fd, uint32_t test_flags)
 static bool
 has_syncobj_wait(int fd)
 {
-	struct local_syncobj_wait wait = { 0 };
+	struct drm_syncobj_wait wait = { 0 };
 	uint32_t handle = 0;
 	uint64_t value;
 	int ret;
@@ -753,7 +753,7 @@ has_syncobj_wait(int fd)
 	/* Try waiting for zero sync objects should fail with EINVAL */
 	wait.count_handles = 1;
 	wait.handles = to_user_pointer(&handle);
-	ret = drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_WAIT, &wait);
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
 	return ret == -1 && errno == ENOENT;
 }
 
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 02/10] drm-uapi: Update drm headers to 17cc51390c141662748dbbc2fe98f3ed10f2e13e
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 01/10] lib/syncobj: drop local declarations Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 03/10] igt: add timeline test cases Lionel Landwerlin
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

  commit 17cc51390c141662748dbbc2fe98f3ed10f2e13e
  Merge: 2d0720f5a4fc b4011644b03c
  Author: Dave Airlie <airlied@redhat.com>
  Date:   Fri Nov 15 12:34:39 2019 +1000

      Merge branch 'vmwgfx-next' of git://people.freedesktop.org/~thomash/linux into drm-next

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 include/drm-uapi/amdgpu_drm.h   |  71 ++++++++++++++++++-
 include/drm-uapi/drm.h          |  39 ++++++++++
 include/drm-uapi/drm_fourcc.h   |  28 +++++++-
 include/drm-uapi/drm_mode.h     | 122 +++++++++++++++++++++++++++++++-
 include/drm-uapi/etnaviv_drm.h  |  10 ++-
 include/drm-uapi/exynos_drm.h   |   2 +-
 include/drm-uapi/msm_drm.h      |  14 ++++
 include/drm-uapi/nouveau_drm.h  |  51 +++++++++++++
 include/drm-uapi/omap_drm.h     |  18 ++---
 include/drm-uapi/panfrost_drm.h |  88 +++++++++++++++++++++++
 include/drm-uapi/v3d_drm.h      |  36 +++++++++-
 11 files changed, 459 insertions(+), 20 deletions(-)

diff --git a/include/drm-uapi/amdgpu_drm.h b/include/drm-uapi/amdgpu_drm.h
index be84e43c..bbdad866 100644
--- a/include/drm-uapi/amdgpu_drm.h
+++ b/include/drm-uapi/amdgpu_drm.h
@@ -128,6 +128,10 @@ extern "C" {
  * for the second page onward should be set to NC.
  */
 #define AMDGPU_GEM_CREATE_MQD_GFX9		(1 << 8)
+/* Flag that BO may contain sensitive data that must be wiped before
+ * releasing the memory
+ */
+#define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE	(1 << 9)
 
 struct drm_amdgpu_gem_create_in  {
 	/** the requested memory size */
@@ -210,13 +214,19 @@ union drm_amdgpu_bo_list {
 #define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1<<1)
 /* indicate some job from this context once cause gpu hang */
 #define AMDGPU_CTX_QUERY2_FLAGS_GUILTY   (1<<2)
+/* indicate some errors are detected by RAS */
+#define AMDGPU_CTX_QUERY2_FLAGS_RAS_CE   (1<<3)
+#define AMDGPU_CTX_QUERY2_FLAGS_RAS_UE   (1<<4)
 
 /* Context priority level */
 #define AMDGPU_CTX_PRIORITY_UNSET       -2048
 #define AMDGPU_CTX_PRIORITY_VERY_LOW    -1023
 #define AMDGPU_CTX_PRIORITY_LOW         -512
 #define AMDGPU_CTX_PRIORITY_NORMAL      0
-/* Selecting a priority above NORMAL requires CAP_SYS_NICE or DRM_MASTER */
+/*
+ * When used in struct drm_amdgpu_ctx_in, a priority above NORMAL requires
+ * CAP_SYS_NICE or DRM_MASTER
+*/
 #define AMDGPU_CTX_PRIORITY_HIGH        512
 #define AMDGPU_CTX_PRIORITY_VERY_HIGH   1023
 
@@ -226,6 +236,7 @@ struct drm_amdgpu_ctx_in {
 	/** For future use, no flags defined so far */
 	__u32	flags;
 	__u32	ctx_id;
+	/** AMDGPU_CTX_PRIORITY_* */
 	__s32	priority;
 };
 
@@ -272,13 +283,15 @@ union drm_amdgpu_vm {
 
 /* sched ioctl */
 #define AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE	1
+#define AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE	2
 
 struct drm_amdgpu_sched_in {
 	/* AMDGPU_SCHED_OP_* */
 	__u32	op;
 	__u32	fd;
+	/** AMDGPU_CTX_PRIORITY_* */
 	__s32	priority;
-	__u32	flags;
+	__u32   ctx_id;
 };
 
 union drm_amdgpu_sched {
@@ -487,6 +500,8 @@ struct drm_amdgpu_gem_op {
 #define AMDGPU_VM_MTYPE_CC		(3 << 5)
 /* Use UC MTYPE instead of default MTYPE */
 #define AMDGPU_VM_MTYPE_UC		(4 << 5)
+/* Use RW MTYPE instead of default MTYPE */
+#define AMDGPU_VM_MTYPE_RW		(5 << 5)
 
 struct drm_amdgpu_gem_va {
 	/** GEM object handle */
@@ -523,6 +538,9 @@ struct drm_amdgpu_gem_va {
 #define AMDGPU_CHUNK_ID_SYNCOBJ_IN      0x04
 #define AMDGPU_CHUNK_ID_SYNCOBJ_OUT     0x05
 #define AMDGPU_CHUNK_ID_BO_HANDLES      0x06
+#define AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES	0x07
+#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT    0x08
+#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL  0x09
 
 struct drm_amdgpu_cs_chunk {
 	__u32		chunk_id;
@@ -565,6 +583,11 @@ union drm_amdgpu_cs {
  * caches (L2/vL1/sL1/I$). */
 #define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3)
 
+/* Set GDS_COMPUTE_MAX_WAVE_ID = DEFAULT before PACKET3_INDIRECT_BUFFER.
+ * This will reset wave ID counters for the IB.
+ */
+#define AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID (1 << 4)
+
 struct drm_amdgpu_cs_chunk_ib {
 	__u32 _pad;
 	/** AMDGPU_IB_FLAG_* */
@@ -598,6 +621,12 @@ struct drm_amdgpu_cs_chunk_sem {
 	__u32 handle;
 };
 
+struct drm_amdgpu_cs_chunk_syncobj {
+       __u32 handle;
+       __u32 flags;
+       __u64 point;
+};
+
 #define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ	0
 #define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD	1
 #define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD	2
@@ -673,6 +702,7 @@ struct drm_amdgpu_cs_chunk_data {
 	#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11
 	/* Subquery id: Query DMCU firmware version */
 	#define AMDGPU_INFO_FW_DMCU		0x12
+	#define AMDGPU_INFO_FW_TA		0x13
 /* number of bytes moved for TTM migration */
 #define AMDGPU_INFO_NUM_BYTES_MOVED		0x0f
 /* the used VRAM size */
@@ -726,6 +756,37 @@ struct drm_amdgpu_cs_chunk_data {
 /* Number of VRAM page faults on CPU access. */
 #define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS	0x1E
 #define AMDGPU_INFO_VRAM_LOST_COUNTER		0x1F
+/* query ras mask of enabled features*/
+#define AMDGPU_INFO_RAS_ENABLED_FEATURES	0x20
+
+/* RAS MASK: UMC (VRAM) */
+#define AMDGPU_INFO_RAS_ENABLED_UMC			(1 << 0)
+/* RAS MASK: SDMA */
+#define AMDGPU_INFO_RAS_ENABLED_SDMA			(1 << 1)
+/* RAS MASK: GFX */
+#define AMDGPU_INFO_RAS_ENABLED_GFX			(1 << 2)
+/* RAS MASK: MMHUB */
+#define AMDGPU_INFO_RAS_ENABLED_MMHUB			(1 << 3)
+/* RAS MASK: ATHUB */
+#define AMDGPU_INFO_RAS_ENABLED_ATHUB			(1 << 4)
+/* RAS MASK: PCIE */
+#define AMDGPU_INFO_RAS_ENABLED_PCIE			(1 << 5)
+/* RAS MASK: HDP */
+#define AMDGPU_INFO_RAS_ENABLED_HDP			(1 << 6)
+/* RAS MASK: XGMI */
+#define AMDGPU_INFO_RAS_ENABLED_XGMI			(1 << 7)
+/* RAS MASK: DF */
+#define AMDGPU_INFO_RAS_ENABLED_DF			(1 << 8)
+/* RAS MASK: SMN */
+#define AMDGPU_INFO_RAS_ENABLED_SMN			(1 << 9)
+/* RAS MASK: SEM */
+#define AMDGPU_INFO_RAS_ENABLED_SEM			(1 << 10)
+/* RAS MASK: MP0 */
+#define AMDGPU_INFO_RAS_ENABLED_MP0			(1 << 11)
+/* RAS MASK: MP1 */
+#define AMDGPU_INFO_RAS_ENABLED_MP1			(1 << 12)
+/* RAS MASK: FUSE */
+#define AMDGPU_INFO_RAS_ENABLED_FUSE			(1 << 13)
 
 #define AMDGPU_INFO_MMR_SE_INDEX_SHIFT	0
 #define AMDGPU_INFO_MMR_SE_INDEX_MASK	0xff
@@ -862,6 +923,7 @@ struct drm_amdgpu_info_firmware {
 #define AMDGPU_VRAM_TYPE_HBM   6
 #define AMDGPU_VRAM_TYPE_DDR3  7
 #define AMDGPU_VRAM_TYPE_DDR4  8
+#define AMDGPU_VRAM_TYPE_GDDR6 9
 
 struct drm_amdgpu_info_device {
 	/** PCI Device ID */
@@ -941,6 +1003,10 @@ struct drm_amdgpu_info_device {
 	__u64 high_va_offset;
 	/** The maximum high virtual address */
 	__u64 high_va_max;
+	/* gfx10 pa_sc_tile_steering_override */
+	__u32 pa_sc_tile_steering_override;
+	/* disabled TCCs */
+	__u64 tcc_disabled_mask;
 };
 
 struct drm_amdgpu_info_hw_ip {
@@ -994,6 +1060,7 @@ struct drm_amdgpu_info_vce_clock_table {
 #define AMDGPU_FAMILY_CZ			135 /* Carrizo, Stoney */
 #define AMDGPU_FAMILY_AI			141 /* Vega10 */
 #define AMDGPU_FAMILY_RV			142 /* Raven */
+#define AMDGPU_FAMILY_NV			143 /* Navi10 */
 
 #if defined(__cplusplus)
 }
diff --git a/include/drm-uapi/drm.h b/include/drm-uapi/drm.h
index 85c685a2..ab940339 100644
--- a/include/drm-uapi/drm.h
+++ b/include/drm-uapi/drm.h
@@ -44,6 +44,7 @@ typedef unsigned int drm_handle_t;
 
 #else /* One of the BSDs */
 
+#include <stdint.h>
 #include <sys/ioccom.h>
 #include <sys/types.h>
 typedef int8_t   __s8;
@@ -643,6 +644,7 @@ struct drm_gem_open {
 #define DRM_CAP_PAGE_FLIP_TARGET	0x11
 #define DRM_CAP_CRTC_IN_VBLANK_EVENT	0x12
 #define DRM_CAP_SYNCOBJ		0x13
+#define DRM_CAP_SYNCOBJ_TIMELINE	0x14
 
 /** DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
@@ -729,8 +731,18 @@ struct drm_syncobj_handle {
 	__u32 pad;
 };
 
+struct drm_syncobj_transfer {
+	__u32 src_handle;
+	__u32 dst_handle;
+	__u64 src_point;
+	__u64 dst_point;
+	__u32 flags;
+	__u32 pad;
+};
+
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */
 struct drm_syncobj_wait {
 	__u64 handles;
 	/* absolute timeout */
@@ -741,12 +753,34 @@ struct drm_syncobj_wait {
 	__u32 pad;
 };
 
+struct drm_syncobj_timeline_wait {
+	__u64 handles;
+	/* wait on specific timeline point for every handles*/
+	__u64 points;
+	/* absolute timeout */
+	__s64 timeout_nsec;
+	__u32 count_handles;
+	__u32 flags;
+	__u32 first_signaled; /* only valid when not waiting all */
+	__u32 pad;
+};
+
+
 struct drm_syncobj_array {
 	__u64 handles;
 	__u32 count_handles;
 	__u32 pad;
 };
 
+#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0) /* last available point on timeline syncobj */
+struct drm_syncobj_timeline_array {
+	__u64 handles;
+	__u64 points;
+	__u32 count_handles;
+	__u32 flags;
+};
+
+
 /* Query current scanout sequence number */
 struct drm_crtc_get_sequence {
 	__u32 crtc_id;		/* requested crtc_id */
@@ -903,6 +937,11 @@ extern "C" {
 #define DRM_IOCTL_MODE_GET_LEASE	DRM_IOWR(0xC8, struct drm_mode_get_lease)
 #define DRM_IOCTL_MODE_REVOKE_LEASE	DRM_IOWR(0xC9, struct drm_mode_revoke_lease)
 
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT	DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait)
+#define DRM_IOCTL_SYNCOBJ_QUERY		DRM_IOWR(0xCB, struct drm_syncobj_timeline_array)
+#define DRM_IOCTL_SYNCOBJ_TRANSFER	DRM_IOWR(0xCC, struct drm_syncobj_transfer)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL	DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
diff --git a/include/drm-uapi/drm_fourcc.h b/include/drm-uapi/drm_fourcc.h
index b93eb2d4..2073420d 100644
--- a/include/drm-uapi/drm_fourcc.h
+++ b/include/drm-uapi/drm_fourcc.h
@@ -69,7 +69,7 @@ extern "C" {
 #define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
 				 ((__u32)(c) << 16) | ((__u32)(d) << 24))
 
-#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
+#define DRM_FORMAT_BIG_ENDIAN (1U<<31) /* format is big endian instead of little endian */
 
 /* Reserve 0 for the invalid format specifier */
 #define DRM_FORMAT_INVALID	0
@@ -649,7 +649,21 @@ extern "C" {
  * Further information on the use of AFBC modifiers can be found in
  * Documentation/gpu/afbc.rst
  */
-#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode)	fourcc_mod_code(ARM, __afbc_mode)
+
+/*
+ * The top 4 bits (out of the 56 bits alloted for specifying vendor specific
+ * modifiers) denote the category for modifiers. Currently we have only two
+ * categories of modifiers ie AFBC and MISC. We can have a maximum of sixteen
+ * different categories.
+ */
+#define DRM_FORMAT_MOD_ARM_CODE(__type, __val) \
+	fourcc_mod_code(ARM, ((__u64)(__type) << 52) | ((__val) & 0x000fffffffffffffULL))
+
+#define DRM_FORMAT_MOD_ARM_TYPE_AFBC 0x00
+#define DRM_FORMAT_MOD_ARM_TYPE_MISC 0x01
+
+#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) \
+	DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_AFBC, __afbc_mode)
 
 /*
  * AFBC superblock size
@@ -743,6 +757,16 @@ extern "C" {
  */
 #define AFBC_FORMAT_MOD_BCH     (1ULL << 11)
 
+/*
+ * Arm 16x16 Block U-Interleaved modifier
+ *
+ * This is used by Arm Mali Utgard and Midgard GPUs. It divides the image
+ * into 16x16 pixel blocks. Blocks are stored linearly in order, but pixels
+ * in the block are reordered.
+ */
+#define DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED \
+	DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_MISC, 1ULL)
+
 /*
  * Allwinner tiled modifier
  *
diff --git a/include/drm-uapi/drm_mode.h b/include/drm-uapi/drm_mode.h
index a439c2e6..735c8cfd 100644
--- a/include/drm-uapi/drm_mode.h
+++ b/include/drm-uapi/drm_mode.h
@@ -33,7 +33,15 @@
 extern "C" {
 #endif
 
-#define DRM_DISPLAY_INFO_LEN	32
+/**
+ * DOC: overview
+ *
+ * DRM exposes many UAPI and structure definition to have a consistent
+ * and standardized interface with user.
+ * Userspace can refer to these structure definitions and UAPI formats
+ * to communicate to driver
+ */
+
 #define DRM_CONNECTOR_NAME_LEN	32
 #define DRM_DISPLAY_MODE_LEN	32
 #define DRM_PROP_NAME_LEN	32
@@ -353,6 +361,7 @@ enum drm_mode_subconnector {
 #define DRM_MODE_CONNECTOR_DSI		16
 #define DRM_MODE_CONNECTOR_DPI		17
 #define DRM_MODE_CONNECTOR_WRITEBACK	18
+#define DRM_MODE_CONNECTOR_SPI		19
 
 struct drm_mode_get_connector {
 
@@ -622,7 +631,8 @@ struct drm_color_ctm {
 
 struct drm_color_lut {
 	/*
-	 * Data is U0.16 fixed point format.
+	 * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and
+	 * 0xffff == 1.0.
 	 */
 	__u16 red;
 	__u16 green;
@@ -630,6 +640,92 @@ struct drm_color_lut {
 	__u16 reserved;
 };
 
+/**
+ * struct hdr_metadata_infoframe - HDR Metadata Infoframe Data.
+ *
+ * HDR Metadata Infoframe as per CTA 861.G spec. This is expected
+ * to match exactly with the spec.
+ *
+ * Userspace is expected to pass the metadata information as per
+ * the format described in this structure.
+ */
+struct hdr_metadata_infoframe {
+	/**
+	 * @eotf: Electro-Optical Transfer Function (EOTF)
+	 * used in the stream.
+	 */
+	__u8 eotf;
+	/**
+	 * @metadata_type: Static_Metadata_Descriptor_ID.
+	 */
+	__u8 metadata_type;
+	/**
+	 * @display_primaries: Color Primaries of the Data.
+	 * These are coded as unsigned 16-bit values in units of
+	 * 0.00002, where 0x0000 represents zero and 0xC350
+	 * represents 1.0000.
+	 * @display_primaries.x: X cordinate of color primary.
+	 * @display_primaries.y: Y cordinate of color primary.
+	 */
+	struct {
+		__u16 x, y;
+		} display_primaries[3];
+	/**
+	 * @white_point: White Point of Colorspace Data.
+	 * These are coded as unsigned 16-bit values in units of
+	 * 0.00002, where 0x0000 represents zero and 0xC350
+	 * represents 1.0000.
+	 * @white_point.x: X cordinate of whitepoint of color primary.
+	 * @white_point.y: Y cordinate of whitepoint of color primary.
+	 */
+	struct {
+		__u16 x, y;
+		} white_point;
+	/**
+	 * @max_display_mastering_luminance: Max Mastering Display Luminance.
+	 * This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
+	 * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
+	 */
+	__u16 max_display_mastering_luminance;
+	/**
+	 * @min_display_mastering_luminance: Min Mastering Display Luminance.
+	 * This value is coded as an unsigned 16-bit value in units of
+	 * 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
+	 * represents 6.5535 cd/m2.
+	 */
+	__u16 min_display_mastering_luminance;
+	/**
+	 * @max_cll: Max Content Light Level.
+	 * This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
+	 * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
+	 */
+	__u16 max_cll;
+	/**
+	 * @max_fall: Max Frame Average Light Level.
+	 * This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
+	 * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
+	 */
+	__u16 max_fall;
+};
+
+/**
+ * struct hdr_output_metadata - HDR output metadata
+ *
+ * Metadata Information to be passed from userspace
+ */
+struct hdr_output_metadata {
+	/**
+	 * @metadata_type: Static_Metadata_Descriptor_ID.
+	 */
+	__u32 metadata_type;
+	/**
+	 * @hdmi_metadata_type1: HDR Metadata Infoframe.
+	 */
+	union {
+		struct hdr_metadata_infoframe hdmi_metadata_type1;
+	};
+};
+
 #define DRM_MODE_PAGE_FLIP_EVENT 0x01
 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02
 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
@@ -803,6 +899,10 @@ struct drm_format_modifier {
 };
 
 /**
+ * struct drm_mode_create_blob - Create New block property
+ * @data: Pointer to data to copy.
+ * @length: Length of data to copy.
+ * @blob_id: new property ID.
  * Create a new 'blob' data property, copying length bytes from data pointer,
  * and returning new blob ID.
  */
@@ -816,6 +916,8 @@ struct drm_mode_create_blob {
 };
 
 /**
+ * struct drm_mode_destroy_blob - Destroy user blob
+ * @blob_id: blob_id to destroy
  * Destroy a user-created blob property.
  */
 struct drm_mode_destroy_blob {
@@ -823,6 +925,12 @@ struct drm_mode_destroy_blob {
 };
 
 /**
+ * struct drm_mode_create_lease - Create lease
+ * @object_ids: Pointer to array of object ids.
+ * @object_count: Number of object ids.
+ * @flags: flags for new FD.
+ * @lessee_id: unique identifier for lessee.
+ * @fd: file descriptor to new drm_master file.
  * Lease mode resources, creating another drm_master.
  */
 struct drm_mode_create_lease {
@@ -840,6 +948,10 @@ struct drm_mode_create_lease {
 };
 
 /**
+ * struct drm_mode_list_lessees - List lessees
+ * @count_lessees: Number of lessees.
+ * @pad: pad.
+ * @lessees_ptr: Pointer to lessess.
  * List lesses from a drm_master
  */
 struct drm_mode_list_lessees {
@@ -860,6 +972,10 @@ struct drm_mode_list_lessees {
 };
 
 /**
+ * struct drm_mode_get_lease - Get Lease
+ * @count_objects: Number of leased objects.
+ * @pad: pad.
+ * @objects_ptr: Pointer to objects.
  * Get leased objects
  */
 struct drm_mode_get_lease {
@@ -880,6 +996,8 @@ struct drm_mode_get_lease {
 };
 
 /**
+ * struct drm_mode_revoke_lease - Revoke lease
+ * @lessee_id: Unique ID of lessee.
  * Revoke lease
  */
 struct drm_mode_revoke_lease {
diff --git a/include/drm-uapi/etnaviv_drm.h b/include/drm-uapi/etnaviv_drm.h
index 0d5c49dc..09d0df8b 100644
--- a/include/drm-uapi/etnaviv_drm.h
+++ b/include/drm-uapi/etnaviv_drm.h
@@ -73,6 +73,7 @@ struct drm_etnaviv_timespec {
 #define ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT         0x18
 #define ETNAVIV_PARAM_GPU_NUM_CONSTANTS             0x19
 #define ETNAVIV_PARAM_GPU_NUM_VARYINGS              0x1a
+#define ETNAVIV_PARAM_SOFTPIN_START_ADDR            0x1b
 
 #define ETNA_MAX_PIPES 4
 
@@ -148,6 +149,11 @@ struct drm_etnaviv_gem_submit_reloc {
  * then patching the cmdstream for this entry is skipped.  This can
  * avoid kernel needing to map/access the cmdstream bo in the common
  * case.
+ * If the submit is a softpin submit (ETNA_SUBMIT_SOFTPIN) the 'presumed'
+ * field is interpreted as the fixed location to map the bo into the gpu
+ * virtual address space. If the kernel is unable to map the buffer at
+ * this location the submit will fail. This means userspace is responsible
+ * for the whole gpu virtual address management.
  */
 #define ETNA_SUBMIT_BO_READ             0x0001
 #define ETNA_SUBMIT_BO_WRITE            0x0002
@@ -177,9 +183,11 @@ struct drm_etnaviv_gem_submit_pmr {
 #define ETNA_SUBMIT_NO_IMPLICIT         0x0001
 #define ETNA_SUBMIT_FENCE_FD_IN         0x0002
 #define ETNA_SUBMIT_FENCE_FD_OUT        0x0004
+#define ETNA_SUBMIT_SOFTPIN             0x0008
 #define ETNA_SUBMIT_FLAGS		(ETNA_SUBMIT_NO_IMPLICIT | \
 					 ETNA_SUBMIT_FENCE_FD_IN | \
-					 ETNA_SUBMIT_FENCE_FD_OUT)
+					 ETNA_SUBMIT_FENCE_FD_OUT| \
+					 ETNA_SUBMIT_SOFTPIN)
 #define ETNA_PIPE_3D      0x00
 #define ETNA_PIPE_2D      0x01
 #define ETNA_PIPE_VG      0x02
diff --git a/include/drm-uapi/exynos_drm.h b/include/drm-uapi/exynos_drm.h
index 7414cfd7..293815e3 100644
--- a/include/drm-uapi/exynos_drm.h
+++ b/include/drm-uapi/exynos_drm.h
@@ -68,7 +68,7 @@ struct drm_exynos_gem_info {
 /**
  * A structure for user connection request of virtual display.
  *
- * @connection: indicate whether doing connetion or not by user.
+ * @connection: indicate whether doing connection or not by user.
  * @extensions: if this value is 1 then the vidi driver would need additional
  *	128bytes edid data.
  * @edid: the edid data pointer from user side.
diff --git a/include/drm-uapi/msm_drm.h b/include/drm-uapi/msm_drm.h
index 91a16b33..0b85ed6a 100644
--- a/include/drm-uapi/msm_drm.h
+++ b/include/drm-uapi/msm_drm.h
@@ -74,6 +74,8 @@ struct drm_msm_timespec {
 #define MSM_PARAM_TIMESTAMP  0x05
 #define MSM_PARAM_GMEM_BASE  0x06
 #define MSM_PARAM_NR_RINGS   0x07
+#define MSM_PARAM_PP_PGTABLE 0x08  /* => 1 for per-process pagetables, else 0 */
+#define MSM_PARAM_FAULTS     0x09
 
 struct drm_msm_param {
 	__u32 pipe;           /* in, MSM_PIPE_x */
@@ -286,6 +288,16 @@ struct drm_msm_submitqueue {
 	__u32 id;      /* out, identifier */
 };
 
+#define MSM_SUBMITQUEUE_PARAM_FAULTS   0
+
+struct drm_msm_submitqueue_query {
+	__u64 data;
+	__u32 id;
+	__u32 param;
+	__u32 len;
+	__u32 pad;
+};
+
 #define DRM_MSM_GET_PARAM              0x00
 /* placeholder:
 #define DRM_MSM_SET_PARAM              0x01
@@ -302,6 +314,7 @@ struct drm_msm_submitqueue {
  */
 #define DRM_MSM_SUBMITQUEUE_NEW        0x0A
 #define DRM_MSM_SUBMITQUEUE_CLOSE      0x0B
+#define DRM_MSM_SUBMITQUEUE_QUERY      0x0C
 
 #define DRM_IOCTL_MSM_GET_PARAM        DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
 #define DRM_IOCTL_MSM_GEM_NEW          DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
@@ -313,6 +326,7 @@ struct drm_msm_submitqueue {
 #define DRM_IOCTL_MSM_GEM_MADVISE      DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_MADVISE, struct drm_msm_gem_madvise)
 #define DRM_IOCTL_MSM_SUBMITQUEUE_NEW    DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_NEW, struct drm_msm_submitqueue)
 #define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE  DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32)
+#define DRM_IOCTL_MSM_SUBMITQUEUE_QUERY  DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_QUERY, struct drm_msm_submitqueue_query)
 
 #if defined(__cplusplus)
 }
diff --git a/include/drm-uapi/nouveau_drm.h b/include/drm-uapi/nouveau_drm.h
index 259588a4..9459a6e3 100644
--- a/include/drm-uapi/nouveau_drm.h
+++ b/include/drm-uapi/nouveau_drm.h
@@ -133,12 +133,63 @@ struct drm_nouveau_gem_cpu_fini {
 #define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC  0x05 /* deprecated */
 #define DRM_NOUVEAU_GPUOBJ_FREE        0x06 /* deprecated */
 #define DRM_NOUVEAU_NVIF               0x07
+#define DRM_NOUVEAU_SVM_INIT           0x08
+#define DRM_NOUVEAU_SVM_BIND           0x09
 #define DRM_NOUVEAU_GEM_NEW            0x40
 #define DRM_NOUVEAU_GEM_PUSHBUF        0x41
 #define DRM_NOUVEAU_GEM_CPU_PREP       0x42
 #define DRM_NOUVEAU_GEM_CPU_FINI       0x43
 #define DRM_NOUVEAU_GEM_INFO           0x44
 
+struct drm_nouveau_svm_init {
+	__u64 unmanaged_addr;
+	__u64 unmanaged_size;
+};
+
+struct drm_nouveau_svm_bind {
+	__u64 header;
+	__u64 va_start;
+	__u64 va_end;
+	__u64 npages;
+	__u64 stride;
+	__u64 result;
+	__u64 reserved0;
+	__u64 reserved1;
+};
+
+#define NOUVEAU_SVM_BIND_COMMAND_SHIFT          0
+#define NOUVEAU_SVM_BIND_COMMAND_BITS           8
+#define NOUVEAU_SVM_BIND_COMMAND_MASK           ((1 << 8) - 1)
+#define NOUVEAU_SVM_BIND_PRIORITY_SHIFT         8
+#define NOUVEAU_SVM_BIND_PRIORITY_BITS          8
+#define NOUVEAU_SVM_BIND_PRIORITY_MASK          ((1 << 8) - 1)
+#define NOUVEAU_SVM_BIND_TARGET_SHIFT           16
+#define NOUVEAU_SVM_BIND_TARGET_BITS            32
+#define NOUVEAU_SVM_BIND_TARGET_MASK            0xffffffff
+
+/*
+ * Below is use to validate ioctl argument, userspace can also use it to make
+ * sure that no bit are set beyond known fields for a given kernel version.
+ */
+#define NOUVEAU_SVM_BIND_VALID_BITS     48
+#define NOUVEAU_SVM_BIND_VALID_MASK     ((1ULL << NOUVEAU_SVM_BIND_VALID_BITS) - 1)
+
+
+/*
+ * NOUVEAU_BIND_COMMAND__MIGRATE: synchronous migrate to target memory.
+ * result: number of page successfuly migrate to the target memory.
+ */
+#define NOUVEAU_SVM_BIND_COMMAND__MIGRATE               0
+
+/*
+ * NOUVEAU_SVM_BIND_HEADER_TARGET__GPU_VRAM: target the GPU VRAM memory.
+ */
+#define NOUVEAU_SVM_BIND_TARGET__GPU_VRAM               (1UL << 31)
+
+
+#define DRM_IOCTL_NOUVEAU_SVM_INIT           DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SVM_INIT, struct drm_nouveau_svm_init)
+#define DRM_IOCTL_NOUVEAU_SVM_BIND           DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_SVM_BIND, struct drm_nouveau_svm_bind)
+
 #define DRM_IOCTL_NOUVEAU_GEM_NEW            DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new)
 #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF        DRM_IOWR(DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf)
 #define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP       DRM_IOW (DRM_COMMAND_BASE + DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep)
diff --git a/include/drm-uapi/omap_drm.h b/include/drm-uapi/omap_drm.h
index 1fccffef..5a142fad 100644
--- a/include/drm-uapi/omap_drm.h
+++ b/include/drm-uapi/omap_drm.h
@@ -38,20 +38,20 @@ struct drm_omap_param {
 	__u64 value;			/* in (set_param), out (get_param) */
 };
 
-#define OMAP_BO_SCANOUT		0x00000001	/* scanout capable (phys contiguous) */
-#define OMAP_BO_CACHE_MASK	0x00000006	/* cache type mask, see cache modes */
-#define OMAP_BO_TILED_MASK	0x00000f00	/* tiled mapping mask, see tiled modes */
+/* Scanout buffer, consumable by DSS */
+#define OMAP_BO_SCANOUT		0x00000001
 
-/* cache modes */
-#define OMAP_BO_CACHED		0x00000000	/* default */
-#define OMAP_BO_WC		0x00000002	/* write-combine */
-#define OMAP_BO_UNCACHED	0x00000004	/* strongly-ordered (uncached) */
+/* Buffer CPU caching mode: cached, write-combining or uncached. */
+#define OMAP_BO_CACHED		0x00000000
+#define OMAP_BO_WC		0x00000002
+#define OMAP_BO_UNCACHED	0x00000004
+#define OMAP_BO_CACHE_MASK	0x00000006
 
-/* tiled modes */
+/* Use TILER for the buffer. The TILER container unit can be 8, 16 or 32 bits. */
 #define OMAP_BO_TILED_8		0x00000100
 #define OMAP_BO_TILED_16	0x00000200
 #define OMAP_BO_TILED_32	0x00000300
-#define OMAP_BO_TILED		(OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32)
+#define OMAP_BO_TILED_MASK	0x00000f00
 
 union omap_gem_size {
 	__u32 bytes;		/* (for non-tiled formats) */
diff --git a/include/drm-uapi/panfrost_drm.h b/include/drm-uapi/panfrost_drm.h
index a52e0283..ec19db1e 100644
--- a/include/drm-uapi/panfrost_drm.h
+++ b/include/drm-uapi/panfrost_drm.h
@@ -18,6 +18,9 @@ extern "C" {
 #define DRM_PANFROST_MMAP_BO			0x03
 #define DRM_PANFROST_GET_PARAM			0x04
 #define DRM_PANFROST_GET_BO_OFFSET		0x05
+#define DRM_PANFROST_PERFCNT_ENABLE		0x06
+#define DRM_PANFROST_PERFCNT_DUMP		0x07
+#define DRM_PANFROST_MADVISE			0x08
 
 #define DRM_IOCTL_PANFROST_SUBMIT		DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_SUBMIT, struct drm_panfrost_submit)
 #define DRM_IOCTL_PANFROST_WAIT_BO		DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_WAIT_BO, struct drm_panfrost_wait_bo)
@@ -25,6 +28,16 @@ extern "C" {
 #define DRM_IOCTL_PANFROST_MMAP_BO		DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_MMAP_BO, struct drm_panfrost_mmap_bo)
 #define DRM_IOCTL_PANFROST_GET_PARAM		DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_GET_PARAM, struct drm_panfrost_get_param)
 #define DRM_IOCTL_PANFROST_GET_BO_OFFSET	DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_GET_BO_OFFSET, struct drm_panfrost_get_bo_offset)
+#define DRM_IOCTL_PANFROST_MADVISE		DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_MADVISE, struct drm_panfrost_madvise)
+
+/*
+ * Unstable ioctl(s): only exposed when the unsafe unstable_ioctls module
+ * param is set to true.
+ * All these ioctl(s) are subject to deprecation, so please don't rely on
+ * them for anything but debugging purpose.
+ */
+#define DRM_IOCTL_PANFROST_PERFCNT_ENABLE	DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_PERFCNT_ENABLE, struct drm_panfrost_perfcnt_enable)
+#define DRM_IOCTL_PANFROST_PERFCNT_DUMP		DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_PERFCNT_DUMP, struct drm_panfrost_perfcnt_dump)
 
 #define PANFROST_JD_REQ_FS (1 << 0)
 /**
@@ -71,6 +84,9 @@ struct drm_panfrost_wait_bo {
 	__s64 timeout_ns;	/* absolute */
 };
 
+#define PANFROST_BO_NOEXEC	1
+#define PANFROST_BO_HEAP	2
+
 /**
  * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs.
  *
@@ -116,6 +132,45 @@ struct drm_panfrost_mmap_bo {
 
 enum drm_panfrost_param {
 	DRM_PANFROST_PARAM_GPU_PROD_ID,
+	DRM_PANFROST_PARAM_GPU_REVISION,
+	DRM_PANFROST_PARAM_SHADER_PRESENT,
+	DRM_PANFROST_PARAM_TILER_PRESENT,
+	DRM_PANFROST_PARAM_L2_PRESENT,
+	DRM_PANFROST_PARAM_STACK_PRESENT,
+	DRM_PANFROST_PARAM_AS_PRESENT,
+	DRM_PANFROST_PARAM_JS_PRESENT,
+	DRM_PANFROST_PARAM_L2_FEATURES,
+	DRM_PANFROST_PARAM_CORE_FEATURES,
+	DRM_PANFROST_PARAM_TILER_FEATURES,
+	DRM_PANFROST_PARAM_MEM_FEATURES,
+	DRM_PANFROST_PARAM_MMU_FEATURES,
+	DRM_PANFROST_PARAM_THREAD_FEATURES,
+	DRM_PANFROST_PARAM_MAX_THREADS,
+	DRM_PANFROST_PARAM_THREAD_MAX_WORKGROUP_SZ,
+	DRM_PANFROST_PARAM_THREAD_MAX_BARRIER_SZ,
+	DRM_PANFROST_PARAM_COHERENCY_FEATURES,
+	DRM_PANFROST_PARAM_TEXTURE_FEATURES0,
+	DRM_PANFROST_PARAM_TEXTURE_FEATURES1,
+	DRM_PANFROST_PARAM_TEXTURE_FEATURES2,
+	DRM_PANFROST_PARAM_TEXTURE_FEATURES3,
+	DRM_PANFROST_PARAM_JS_FEATURES0,
+	DRM_PANFROST_PARAM_JS_FEATURES1,
+	DRM_PANFROST_PARAM_JS_FEATURES2,
+	DRM_PANFROST_PARAM_JS_FEATURES3,
+	DRM_PANFROST_PARAM_JS_FEATURES4,
+	DRM_PANFROST_PARAM_JS_FEATURES5,
+	DRM_PANFROST_PARAM_JS_FEATURES6,
+	DRM_PANFROST_PARAM_JS_FEATURES7,
+	DRM_PANFROST_PARAM_JS_FEATURES8,
+	DRM_PANFROST_PARAM_JS_FEATURES9,
+	DRM_PANFROST_PARAM_JS_FEATURES10,
+	DRM_PANFROST_PARAM_JS_FEATURES11,
+	DRM_PANFROST_PARAM_JS_FEATURES12,
+	DRM_PANFROST_PARAM_JS_FEATURES13,
+	DRM_PANFROST_PARAM_JS_FEATURES14,
+	DRM_PANFROST_PARAM_JS_FEATURES15,
+	DRM_PANFROST_PARAM_NR_CORE_GROUPS,
+	DRM_PANFROST_PARAM_THREAD_TLS_ALLOC,
 };
 
 struct drm_panfrost_get_param {
@@ -135,6 +190,39 @@ struct drm_panfrost_get_bo_offset {
 	__u64 offset;
 };
 
+struct drm_panfrost_perfcnt_enable {
+	__u32 enable;
+	/*
+	 * On bifrost we have 2 sets of counters, this parameter defines the
+	 * one to track.
+	 */
+	__u32 counterset;
+};
+
+struct drm_panfrost_perfcnt_dump {
+	__u64 buf_ptr;
+};
+
+/* madvise provides a way to tell the kernel in case a buffers contents
+ * can be discarded under memory pressure, which is useful for userspace
+ * bo cache where we want to optimistically hold on to buffer allocate
+ * and potential mmap, but allow the pages to be discarded under memory
+ * pressure.
+ *
+ * Typical usage would involve madvise(DONTNEED) when buffer enters BO
+ * cache, and madvise(WILLNEED) if trying to recycle buffer from BO cache.
+ * In the WILLNEED case, 'retained' indicates to userspace whether the
+ * backing pages still exist.
+ */
+#define PANFROST_MADV_WILLNEED 0	/* backing pages are needed, status returned in 'retained' */
+#define PANFROST_MADV_DONTNEED 1	/* backing pages not needed */
+
+struct drm_panfrost_madvise {
+	__u32 handle;         /* in, GEM handle */
+	__u32 madv;           /* in, PANFROST_MADV_x */
+	__u32 retained;       /* out, whether backing store still exists */
+};
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/drm-uapi/v3d_drm.h b/include/drm-uapi/v3d_drm.h
index ea70669d..1ce746e2 100644
--- a/include/drm-uapi/v3d_drm.h
+++ b/include/drm-uapi/v3d_drm.h
@@ -37,6 +37,7 @@ extern "C" {
 #define DRM_V3D_GET_PARAM                         0x04
 #define DRM_V3D_GET_BO_OFFSET                     0x05
 #define DRM_V3D_SUBMIT_TFU                        0x06
+#define DRM_V3D_SUBMIT_CSD                        0x07
 
 #define DRM_IOCTL_V3D_SUBMIT_CL           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl)
 #define DRM_IOCTL_V3D_WAIT_BO             DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo)
@@ -45,6 +46,9 @@ extern "C" {
 #define DRM_IOCTL_V3D_GET_PARAM           DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_PARAM, struct drm_v3d_get_param)
 #define DRM_IOCTL_V3D_GET_BO_OFFSET       DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_GET_BO_OFFSET, struct drm_v3d_get_bo_offset)
 #define DRM_IOCTL_V3D_SUBMIT_TFU          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_TFU, struct drm_v3d_submit_tfu)
+#define DRM_IOCTL_V3D_SUBMIT_CSD          DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CSD, struct drm_v3d_submit_csd)
+
+#define DRM_V3D_SUBMIT_CL_FLUSH_CACHE             0x01
 
 /**
  * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D
@@ -59,7 +63,7 @@ extern "C" {
  * flushed by the time the render done IRQ happens, which is the
  * trigger for out_sync.  Any dirtying of cachelines by the job (only
  * possible using TMU writes) must be flushed by the caller using the
- * CL's cache flush commands.
+ * DRM_V3D_SUBMIT_CL_FLUSH_CACHE_FLAG flag.
  */
 struct drm_v3d_submit_cl {
 	/* Pointer to the binner command list.
@@ -122,8 +126,7 @@ struct drm_v3d_submit_cl {
 	/* Number of BO handles passed in (size is that times 4). */
 	__u32 bo_handle_count;
 
-	/* Pad, must be zero-filled. */
-	__u32 pad;
+	__u32 flags;
 };
 
 /**
@@ -190,6 +193,8 @@ enum drm_v3d_param {
 	DRM_V3D_PARAM_V3D_CORE0_IDENT1,
 	DRM_V3D_PARAM_V3D_CORE0_IDENT2,
 	DRM_V3D_PARAM_SUPPORTS_TFU,
+	DRM_V3D_PARAM_SUPPORTS_CSD,
+	DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH,
 };
 
 struct drm_v3d_get_param {
@@ -230,6 +235,31 @@ struct drm_v3d_submit_tfu {
 	__u32 out_sync;
 };
 
+/* Submits a compute shader for dispatch.  This job will block on any
+ * previous compute shaders submitted on this fd, and any other
+ * synchronization must be performed with in_sync/out_sync.
+ */
+struct drm_v3d_submit_csd {
+	__u32 cfg[7];
+	__u32 coef[4];
+
+	/* Pointer to a u32 array of the BOs that are referenced by the job.
+	 */
+	__u64 bo_handles;
+
+	/* Number of BO handles passed in (size is that times 4). */
+	__u32 bo_handle_count;
+
+	/* sync object to block on before running the CSD job.  Each
+	 * CSD job will execute in the order submitted to its FD.
+	 * Synchronization against rendering/TFU jobs or CSD from
+	 * other fds requires using sync objects.
+	 */
+	__u32 in_sync;
+	/* Sync object to signal when the CSD job is done. */
+	__u32 out_sync;
+};
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 03/10] igt: add timeline test cases
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 01/10] lib/syncobj: drop local declarations Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 02/10] drm-uapi: Update drm headers to 17cc51390c141662748dbbc2fe98f3ed10f2e13e Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 04/10] tests/syncobj_timeline: add more timeline tests Lionel Landwerlin
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev; +Cc: Chunming Zhou

From: Chunming Zhou <david1.zhou@amd.com>

v2: adapt to new transfer ioctl

v3: Drop useless uint64_t casts (Lionel)
    Fix timeline query prototypes (Lionel)
    Test multi wait with timeline & binary syncobjs (Lionel)

v4: Switch from drmIoctl to igt_ioctl in tests/*.c (Chris)
    Clear out errno in helper functions (Chris)

v5: Fix lib comments on transfer helpers (Lionel)

v6: Add igt_describe() (Lionel)

Signed-off-by: Chunming Zhou <david1.zhou@amd.com>
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/igt_syncobj.c        |  237 ++++++++
 lib/igt_syncobj.h        |   19 +
 tests/meson.build        |    1 +
 tests/syncobj_timeline.c | 1150 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 1407 insertions(+)
 create mode 100644 tests/syncobj_timeline.c

diff --git a/lib/igt_syncobj.c b/lib/igt_syncobj.c
index ad23faaf..b211dfef 100644
--- a/lib/igt_syncobj.c
+++ b/lib/igt_syncobj.c
@@ -307,3 +307,240 @@ syncobj_signal(int fd, uint32_t *handles, uint32_t count)
 {
 	igt_assert_eq(__syncobj_signal(fd, handles, count), 0);
 }
+
+static int
+__syncobj_timeline_signal(int fd, uint32_t *handles, uint64_t *points, uint32_t count)
+{
+	struct drm_syncobj_timeline_array array = { 0 };
+	int err = 0;
+
+	array.handles = to_user_pointer(handles);
+	array.points = to_user_pointer(points);
+	array.count_handles = count;
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &array)) {
+		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
+	return err;
+}
+
+/**
+ * syncobj_signal:
+ * @fd: The DRM file descriptor.
+ * @handles: Array of syncobj handles to signal
+ * @points: List of point of handles to signal.
+ * @count: Count of syncobj handles.
+ *
+ * Signal a set of syncobjs.
+ */
+void
+syncobj_timeline_signal(int fd, uint32_t *handles, uint64_t *points, uint32_t count)
+{
+	igt_assert_eq(__syncobj_timeline_signal(fd, handles, points, count), 0);
+}
+int
+__syncobj_timeline_wait_ioctl(int fd, struct drm_syncobj_timeline_wait *args)
+{
+	int err = 0;
+	if (igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, args)) {
+		err = -errno;
+		igt_assume(err);
+		errno = 0;
+	}
+	return err;
+}
+static int
+__syncobj_timeline_wait(int fd, uint32_t *handles, uint64_t *points,
+			unsigned num_handles,
+			int64_t timeout_nsec, unsigned flags,
+			uint32_t *first_signaled)
+{
+	struct drm_syncobj_timeline_wait args;
+	int ret;
+
+	args.handles = to_user_pointer(handles);
+	args.points = to_user_pointer(points);
+	args.timeout_nsec = timeout_nsec;
+	args.count_handles = num_handles;
+	args.flags = flags;
+	args.first_signaled = 0;
+	args.pad = 0;
+
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args);
+	if (ret < 0) {
+		ret = -errno;
+		igt_assume(ret);
+		errno = 0;
+	}
+
+	if (first_signaled)
+		*first_signaled = args.first_signaled;
+
+	return ret;
+}
+int
+syncobj_timeline_wait_err(int fd, uint32_t *handles, uint64_t *points,
+			  unsigned num_handles,
+			  int64_t timeout_nsec, unsigned flags)
+{
+	return __syncobj_timeline_wait(fd, handles, points, num_handles,
+				       timeout_nsec, flags, NULL);
+}
+
+/**
+ * syncobj_timeline_wait:
+ * @fd: The DRM file descriptor
+ * @handles: List of syncobj handles to wait for.
+ * @points: List of point of handles to wait for.
+ * @num_handles: Count of handles
+ * @timeout_nsec: Absolute wait timeout in nanoseconds.
+ * @flags: Wait ioctl flags.
+ * @first_signaled: Returned handle for first signaled syncobj.
+ *
+ * Waits in the kernel for any/all the requested syncobjs timeline point
+ * using the timeout and flags.
+ * Returns: bool value - false = timedout, true = signaled
+ */
+bool
+syncobj_timeline_wait(int fd, uint32_t *handles, uint64_t *points,
+		      unsigned num_handles,
+		      int64_t timeout_nsec, unsigned flags,
+		      uint32_t *first_signaled)
+{
+	int ret;
+
+	ret = __syncobj_timeline_wait(fd, handles, points, num_handles,
+				      timeout_nsec, flags, first_signaled);
+	if (ret == -ETIME)
+		return false;
+	igt_assert_eq(ret, 0);
+
+	return true;
+
+}
+
+static int
+__syncobj_timeline_query(int fd, uint32_t *handles, uint64_t *points,
+			 uint32_t handle_count)
+{
+	struct drm_syncobj_timeline_array args;
+	int ret;
+
+	args.handles = to_user_pointer(handles);
+	args.points = to_user_pointer(points);
+	args.count_handles = handle_count;
+	args.flags = 0;
+
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args);
+	if (ret) {
+		ret = -errno;
+		igt_assume(ret);
+		errno = 0;
+	}
+
+	return ret;
+}
+
+/**
+ * syncobj_timeline_query:
+ * @fd: The DRM file descriptor.
+ * @handles: Array of syncobj handles.
+ * @points: Array of syncobj points queried.
+ * @count: Count of syncobj handles.
+ *
+ * Queries a set of syncobjs.
+ */
+void
+syncobj_timeline_query(int fd, uint32_t *handles, uint64_t *points,
+		       uint32_t count)
+{
+	igt_assert_eq(__syncobj_timeline_query(fd, handles, points, count), 0);
+}
+
+static int
+__syncobj_binary_to_timeline(int fd, uint32_t timeline_handle,
+			     uint64_t point, uint32_t binary_handle)
+{
+	struct drm_syncobj_transfer args;
+	int ret;
+
+	args.src_handle = binary_handle;
+	args.dst_handle = timeline_handle;
+	args.src_point = 0;
+	args.dst_point = point;
+	args.flags = 0;
+	args.pad = 0;
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args);
+	if (ret) {
+		ret = -errno;
+		igt_assume(ret);
+		errno = 0;
+	}
+
+	return ret;
+}
+
+/**
+ * syncobj_binary_to_timeline:
+ * @fd: The DRM file descriptor.
+ * @timeline_handle: A syncobj timeline handle
+ * @point: A syncobj timeline point in the timeline handle
+ * @binary_handle: A syncobj binary handle
+ *
+ * Transfers a DMA fence from a binary syncobj into a timeline syncobj
+ * at a given point on the timeline.
+ */
+void
+syncobj_binary_to_timeline(int fd, uint32_t timeline_handle,
+			   uint64_t point, uint32_t binary_handle)
+{
+	igt_assert_eq(__syncobj_binary_to_timeline(fd, timeline_handle, point,
+						   binary_handle), 0);
+}
+
+static int
+__syncobj_timeline_to_binary(int fd, uint32_t binary_handle,
+			     uint32_t timeline_handle,
+			     uint64_t point,
+			     uint32_t flags)
+{
+	struct drm_syncobj_transfer args;
+	int ret;
+
+	args.dst_handle = binary_handle;
+	args.src_handle = timeline_handle;
+	args.dst_point = 0;
+	args.src_point = point;
+	args.flags = flags;
+	args.pad = 0;
+	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args);
+	if (ret) {
+		ret = -errno;
+		igt_assert(ret);
+	}
+
+	errno = 0;
+	return ret;
+}
+
+/**
+ * syncobj_binary_to_timeline:
+ * @fd: The DRM file descriptor.
+ * @binary_handle: A syncobj binary handle
+ * @timeline_handle: A syncobj timeline handle
+ * @point: A syncobj timeline point in the timeline handle
+ *
+ * Transfers DMA fence from a given point from timeline syncobj into a
+ * binary syncobj.
+ */
+void
+syncobj_timeline_to_binary(int fd, uint32_t binary_handle,
+			   uint32_t timeline_handle,
+			   uint64_t point,
+			   uint32_t flags)
+{
+	igt_assert_eq(__syncobj_timeline_to_binary(fd, binary_handle,
+						   timeline_handle, point,
+						   flags), 0);
+}
diff --git a/lib/igt_syncobj.h b/lib/igt_syncobj.h
index 51ad2364..20f1f18f 100644
--- a/lib/igt_syncobj.h
+++ b/lib/igt_syncobj.h
@@ -41,7 +41,26 @@ int syncobj_wait_err(int fd, uint32_t *handles, uint32_t count,
 bool syncobj_wait(int fd, uint32_t *handles, uint32_t count,
 		  uint64_t abs_timeout_nsec, uint32_t flags,
 		  uint32_t *first_signaled);
+int __syncobj_timeline_wait_ioctl(int fd,
+				  struct drm_syncobj_timeline_wait *args);
+bool syncobj_timeline_wait(int fd, uint32_t *handles, uint64_t *points,
+			   unsigned num_handles,
+			   int64_t timeout_nsec, unsigned flags,
+			   uint32_t *first_signaled);
+int syncobj_timeline_wait_err(int fd, uint32_t *handles, uint64_t *points,
+			      unsigned num_handles,
+			      int64_t timeout_nsec, unsigned flags);
 void syncobj_reset(int fd, uint32_t *handles, uint32_t count);
 void syncobj_signal(int fd, uint32_t *handles, uint32_t count);
+void syncobj_timeline_query(int fd, uint32_t *handles, uint64_t *points,
+			    uint32_t count);
+void syncobj_binary_to_timeline(int fd, uint32_t timeline_handle,
+				uint64_t point, uint32_t binary_handle);
+void syncobj_timeline_to_binary(int fd, uint32_t binary_handle,
+				uint32_t timeline_handle,
+				uint64_t point,
+				uint32_t flags);
+void syncobj_timeline_signal(int fd, uint32_t *handles, uint64_t *points,
+			     uint32_t count);
 
 #endif /* IGT_SYNCOBJ_H */
diff --git a/tests/meson.build b/tests/meson.build
index 755fc9e6..7ed4140b 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -82,6 +82,7 @@ test_progs = [
 	'prime_vgem',
 	'syncobj_basic',
 	'syncobj_wait',
+	'syncobj_timeline',
 	'template',
 	'tools_test',
 	'v3d_get_bo_offset',
diff --git a/tests/syncobj_timeline.c b/tests/syncobj_timeline.c
new file mode 100644
index 00000000..82fc08aa
--- /dev/null
+++ b/tests/syncobj_timeline.c
@@ -0,0 +1,1150 @@
+/*
+ * Copyright © 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "igt.h"
+#include "sw_sync.h"
+#include "igt_syncobj.h"
+#include <unistd.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <signal.h>
+#include "drm.h"
+
+IGT_TEST_DESCRIPTION("Tests for the drm timeline sync object API");
+
+/* One tenth of a second */
+#define SHORT_TIME_NSEC 100000000ull
+
+#define NSECS_PER_SEC 1000000000ull
+
+static uint64_t
+gettime_ns(void)
+{
+	struct timespec current;
+	clock_gettime(CLOCK_MONOTONIC, &current);
+	return (uint64_t)current.tv_sec * NSECS_PER_SEC + current.tv_nsec;
+}
+
+static void
+sleep_nsec(uint64_t time_nsec)
+{
+	struct timespec t;
+	t.tv_sec = time_nsec / NSECS_PER_SEC;
+	t.tv_nsec = time_nsec % NSECS_PER_SEC;
+	igt_assert_eq(nanosleep(&t, NULL), 0);
+}
+
+static uint64_t
+short_timeout(void)
+{
+	return gettime_ns() + SHORT_TIME_NSEC;
+}
+
+static int
+syncobj_attach_sw_sync(int fd, uint32_t handle, uint64_t point)
+{
+	int timeline, fence;
+
+	timeline = sw_sync_timeline_create();
+	fence = sw_sync_timeline_create_fence(timeline, 1);
+
+	if (point == 0) {
+		syncobj_import_sync_file(fd, handle, fence);
+	} else {
+		uint32_t syncobj = syncobj_create(fd, 0);
+
+		syncobj_import_sync_file(fd, syncobj, fence);
+		syncobj_binary_to_timeline(fd, handle, point, syncobj);
+		syncobj_destroy(fd, syncobj);
+	}
+
+	close(fence);
+
+	return timeline;
+}
+
+static void
+syncobj_trigger(int fd, uint32_t handle, uint64_t point)
+{
+	int timeline = syncobj_attach_sw_sync(fd, handle, point);
+	sw_sync_timeline_inc(timeline, 1);
+	close(timeline);
+}
+
+static timer_t
+set_timer(void (*cb)(union sigval), void *ptr, int i, uint64_t nsec)
+{
+        timer_t timer;
+        struct sigevent sev;
+        struct itimerspec its;
+
+        memset(&sev, 0, sizeof(sev));
+        sev.sigev_notify = SIGEV_THREAD;
+	if (ptr)
+		sev.sigev_value.sival_ptr = ptr;
+	else
+		sev.sigev_value.sival_int = i;
+        sev.sigev_notify_function = cb;
+        igt_assert(timer_create(CLOCK_MONOTONIC, &sev, &timer) == 0);
+
+        memset(&its, 0, sizeof(its));
+        its.it_value.tv_sec = nsec / NSEC_PER_SEC;
+        its.it_value.tv_nsec = nsec % NSEC_PER_SEC;
+        igt_assert(timer_settime(timer, 0, &its, NULL) == 0);
+
+	return timer;
+}
+
+struct fd_handle_pair {
+	int fd;
+	uint32_t handle;
+	uint64_t point;
+};
+
+static void
+timeline_inc_func(union sigval sigval)
+{
+	sw_sync_timeline_inc(sigval.sival_int, 1);
+}
+
+static void
+syncobj_trigger_free_pair_func(union sigval sigval)
+{
+	struct fd_handle_pair *pair = sigval.sival_ptr;
+	syncobj_trigger(pair->fd, pair->handle, pair->point);
+	free(pair);
+}
+
+static timer_t
+syncobj_trigger_delayed(int fd, uint32_t syncobj, uint64_t point, uint64_t nsec)
+{
+	struct fd_handle_pair *pair = malloc(sizeof(*pair));
+
+	pair->fd = fd;
+	pair->handle = syncobj;
+	pair->point = point;
+
+	return set_timer(syncobj_trigger_free_pair_func, pair, 0, nsec);
+}
+
+static const char *test_wait_bad_flags_desc =
+	"Verifies that an invalid value in drm_syncobj_timeline_wait::flags is"
+	" rejected";
+static void
+test_wait_bad_flags(int fd)
+{
+	struct drm_syncobj_timeline_wait wait = {};
+	wait.flags = 0xdeadbeef;
+	igt_assert_eq(__syncobj_timeline_wait_ioctl(fd, &wait), -EINVAL);
+}
+
+static const char *test_wait_zero_handles_desc =
+	"Verifies that waiting on an empty list of invalid syncobj handles is"
+	" rejected";
+static void
+test_wait_zero_handles(int fd)
+{
+	struct drm_syncobj_timeline_wait wait = {};
+	igt_assert_eq(__syncobj_timeline_wait_ioctl(fd, &wait), -EINVAL);
+}
+
+static const char *test_wait_illegal_handle_desc =
+	"Verifies that waiting on an invalid syncobj handle is rejected";
+static void
+test_wait_illegal_handle(int fd)
+{
+	struct drm_syncobj_timeline_wait wait = {};
+	uint32_t handle = 0;
+
+	wait.count_handles = 1;
+	wait.handles = to_user_pointer(&handle);
+	igt_assert_eq(__syncobj_timeline_wait_ioctl(fd, &wait), -ENOENT);
+}
+
+static const char *test_query_zero_handles_desc =
+	"Verifies that querying an empty list of syncobj handles is rejected";
+static void
+test_query_zero_handles(int fd)
+{
+	struct drm_syncobj_timeline_array args = {};
+	int ret;
+
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args);
+	igt_assert(ret == -1 && errno ==  EINVAL);
+}
+
+static const char *test_query_illegal_handle_desc =
+	"Verifies that querying an invalid syncobj handle is rejected";
+static void
+test_query_illegal_handle(int fd)
+{
+	struct drm_syncobj_timeline_array args = {};
+	uint32_t handle = 0;
+	int ret;
+
+	args.count_handles = 1;
+	args.handles = to_user_pointer(&handle);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &args);
+	igt_assert(ret == -1 && errno == ENOENT);
+}
+
+static const char *test_query_one_illegal_handle_desc =
+	"Verifies that querying a list of invalid syncobj handle including an"
+	" invalid one is rejected";
+static void
+test_query_one_illegal_handle(int fd)
+{
+	struct drm_syncobj_timeline_array array = {};
+	uint32_t syncobjs[3];
+	uint64_t initial_point = 1;
+	int ret;
+
+	syncobjs[0] = syncobj_create(fd, 0);
+	syncobjs[1] = 0;
+	syncobjs[2] = syncobj_create(fd, 0);
+
+	syncobj_timeline_signal(fd, &syncobjs[0], &initial_point, 1);
+	syncobj_timeline_signal(fd, &syncobjs[2], &initial_point, 1);
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobjs[0],
+						&initial_point, 1, 0, 0), 0);
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobjs[2],
+						&initial_point, 1, 0, 0), 0);
+
+	array.count_handles = 3;
+	array.handles = to_user_pointer(syncobjs);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &array);
+	igt_assert(ret == -1 && errno == ENOENT);
+
+	syncobj_destroy(fd, syncobjs[0]);
+	syncobj_destroy(fd, syncobjs[2]);
+}
+
+static const char *test_query_bad_pad_desc =
+	"Verify that querying a timeline syncobj with an invalid"
+	" drm_syncobj_timeline_array::flags field is rejected";
+static void
+test_query_bad_pad(int fd)
+{
+	struct drm_syncobj_timeline_array array = {};
+	uint32_t handle = 0;
+	int ret;
+
+	array.flags = 0xdeadbeef;
+	array.count_handles = 1;
+	array.handles = to_user_pointer(&handle);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_QUERY, &array);
+	igt_assert(ret == -1 && errno == EINVAL);
+}
+
+static const char *test_signal_zero_handles_desc =
+	"Verify that signaling an empty list of syncobj handles is rejected";
+static void
+test_signal_zero_handles(int fd)
+{
+	struct drm_syncobj_timeline_array args = {};
+	int ret;
+
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args);
+	igt_assert(ret == -1 && errno ==  EINVAL);
+}
+
+static const char *test_signal_illegal_handle_desc =
+	"Verify that signaling an invalid syncobj handle is rejected";
+static void
+test_signal_illegal_handle(int fd)
+{
+	struct drm_syncobj_timeline_array args = {};
+	uint32_t handle = 0;
+	int ret;
+
+	args.count_handles = 1;
+	args.handles = to_user_pointer(&handle);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args);
+	igt_assert(ret == -1 && errno == ENOENT);
+}
+
+static void
+test_signal_illegal_point(int fd)
+{
+	struct drm_syncobj_timeline_array args = {};
+	uint32_t handle = 1;
+	uint64_t point = 0;
+	int ret;
+
+	args.count_handles = 1;
+	args.handles = to_user_pointer(&handle);
+	args.points = to_user_pointer(&point);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args);
+	igt_assert(ret == -1 && errno == ENOENT);
+}
+
+static const char *test_signal_one_illegal_handle_desc =
+	"Verify that an invalid syncobj handle in drm_syncobj_timeline_array is"
+	" rejected for signaling";
+static void
+test_signal_one_illegal_handle(int fd)
+{
+	struct drm_syncobj_timeline_array array = {};
+	uint32_t syncobjs[3];
+	uint64_t initial_point = 1;
+	int ret;
+
+	syncobjs[0] = syncobj_create(fd, 0);
+	syncobjs[1] = 0;
+	syncobjs[2] = syncobj_create(fd, 0);
+
+	syncobj_timeline_signal(fd, &syncobjs[0], &initial_point, 1);
+	syncobj_timeline_signal(fd, &syncobjs[2], &initial_point, 1);
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobjs[0],
+						&initial_point, 1, 0, 0), 0);
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobjs[2],
+						&initial_point, 1, 0, 0), 0);
+
+	array.count_handles = 3;
+	array.handles = to_user_pointer(syncobjs);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &array);
+	igt_assert(ret == -1 && errno == ENOENT);
+
+	syncobj_destroy(fd, syncobjs[0]);
+	syncobj_destroy(fd, syncobjs[2]);
+}
+
+static const char *test_signal_bad_pad_desc =
+	"Verifies that an invalid value in drm_syncobj_timeline_array.flags is"
+	" rejected";
+static void
+test_signal_bad_pad(int fd)
+{
+	struct drm_syncobj_timeline_array array = {};
+	uint32_t handle = 0;
+	int ret;
+
+	array.flags = 0xdeadbeef;
+	array.count_handles = 1;
+	array.handles = to_user_pointer(&handle);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &array);
+	igt_assert(ret == -1 && errno == EINVAL);
+}
+
+static const char *test_signal_array_desc =
+	"Verifies the signaling of a list of timeline syncobj";
+static void
+test_signal_array(int fd)
+{
+	uint32_t syncobjs[4];
+	uint64_t points[4] = {1, 1, 1, 0};
+
+	syncobjs[0] = syncobj_create(fd, 0);
+	syncobjs[1] = syncobj_create(fd, 0);
+	syncobjs[2] = syncobj_create(fd, 0);
+	syncobjs[3] = syncobj_create(fd, 0);
+
+	syncobj_timeline_signal(fd, syncobjs, points, 4);
+	igt_assert_eq(syncobj_timeline_wait_err(fd, syncobjs,
+						points, 3, 0, 0), 0);
+	igt_assert_eq(syncobj_wait_err(fd, &syncobjs[3], 1, 0, 0), 0);
+
+	syncobj_destroy(fd, syncobjs[0]);
+	syncobj_destroy(fd, syncobjs[1]);
+	syncobj_destroy(fd, syncobjs[2]);
+	syncobj_destroy(fd, syncobjs[3]);
+}
+
+static const char *test_transfer_illegal_handle_desc =
+	"Verifies that an invalid syncobj handle is rejected in"
+	" drm_syncobj_transfer";
+static void
+test_transfer_illegal_handle(int fd)
+{
+	struct drm_syncobj_transfer args = {};
+	uint32_t handle = 0;
+	int ret;
+
+	args.src_handle = to_user_pointer(&handle);
+	args.dst_handle = to_user_pointer(&handle);
+	args.src_point = 1;
+	args.dst_point = 0;
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args);
+	igt_assert(ret == -1 && errno == ENOENT);
+}
+
+static const char *test_transfer_bad_pad_desc =
+	"Verifies that invalid drm_syncobj_transfer::pad field value is"
+	" rejected";
+static void
+test_transfer_bad_pad(int fd)
+{
+	struct drm_syncobj_transfer arg = {};
+	uint32_t handle = 0;
+	int ret;
+
+	arg.pad = 0xdeadbeef;
+	arg.src_handle = to_user_pointer(&handle);
+	arg.dst_handle = to_user_pointer(&handle);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &arg);
+	igt_assert(ret == -1 && errno == EINVAL);
+}
+
+#define WAIT_FOR_SUBMIT		(1 << 0)
+#define WAIT_ALL		(1 << 1)
+#define WAIT_AVAILABLE		(1 << 2)
+#define WAIT_UNSUBMITTED	(1 << 3)
+#define WAIT_SUBMITTED		(1 << 4)
+#define WAIT_SIGNALED		(1 << 5)
+#define WAIT_FLAGS_MAX		(1 << 6) - 1
+
+static uint32_t
+flags_for_test_flags(uint32_t test_flags)
+{
+	uint32_t flags = 0;
+
+	if (test_flags & WAIT_FOR_SUBMIT)
+		flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+
+	if (test_flags & WAIT_AVAILABLE)
+		flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE;
+
+	if (test_flags & WAIT_ALL)
+		flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL;
+
+	return flags;
+}
+
+static const char *test_signal_wait_desc =
+	"Verifies wait behavior on a single timeline syncobj";
+static void
+test_single_wait(int fd, uint32_t test_flags, int expect)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint32_t flags = flags_for_test_flags(test_flags);
+	uint64_t point = 1;
+	int timeline = -1;
+
+	if (test_flags & (WAIT_SUBMITTED | WAIT_SIGNALED))
+		timeline = syncobj_attach_sw_sync(fd, syncobj, point);
+
+	if (test_flags & WAIT_SIGNALED)
+		sw_sync_timeline_inc(timeline, 1);
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point, 1,
+						0, flags), expect);
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point, 1,
+						short_timeout(), flags), expect);
+
+	if (expect != -ETIME) {
+		igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point, 1,
+							UINT64_MAX, flags), expect);
+	}
+
+	syncobj_destroy(fd, syncobj);
+	if (timeline != -1)
+		close(timeline);
+}
+
+static const char *test_wait_delayed_signal_desc =
+	"Verifies wait behavior on a timeline syncobj with a delayed signal"
+	" from a different thread";
+static void
+test_wait_delayed_signal(int fd, uint32_t test_flags)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint32_t flags = flags_for_test_flags(test_flags);
+	uint64_t point = 1;
+	int timeline = -1;
+	timer_t timer;
+
+	if (test_flags & WAIT_FOR_SUBMIT) {
+		timer = syncobj_trigger_delayed(fd, syncobj, point, SHORT_TIME_NSEC);
+	} else {
+		timeline = syncobj_attach_sw_sync(fd, syncobj, point);
+		timer = set_timer(timeline_inc_func, NULL,
+				  timeline, SHORT_TIME_NSEC);
+	}
+
+	igt_assert(syncobj_timeline_wait(fd, &syncobj, &point, 1,
+				gettime_ns() + SHORT_TIME_NSEC * 2,
+				flags, NULL));
+
+	timer_delete(timer);
+
+	if (timeline != -1)
+		close(timeline);
+
+	syncobj_destroy(fd, syncobj);
+}
+
+static const char *test_reset_unsignaled_desc =
+	"Verifies behavior of a reset operation on an unsignaled timeline"
+	" syncobj";
+static void
+test_reset_unsignaled(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint64_t point = 1;
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point,
+						1, 0, 0), -EINVAL);
+
+	syncobj_reset(fd, &syncobj, 1);
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point,
+						1, 0, 0), -EINVAL);
+
+	syncobj_destroy(fd, syncobj);
+}
+
+static const char *test_reset_signaled_desc =
+	"Verifies behavior of a reset operation on a signaled timeline syncobj";
+static void
+test_reset_signaled(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint64_t point = 1;
+
+	syncobj_trigger(fd, syncobj, point);
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point,
+						1, 0, 0), 0);
+
+	syncobj_reset(fd, &syncobj, 1);
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point,
+						1, 0, 0), -EINVAL);
+
+	syncobj_destroy(fd, syncobj);
+}
+
+static const char *test_reset_multiple_signaled_desc =
+	"Verifies behavior of a reset operation on a list of signaled timeline"
+	" syncobjs";
+static void
+test_reset_multiple_signaled(int fd)
+{
+	uint64_t points[3] = {1, 1, 1};
+	uint32_t syncobjs[3];
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		syncobjs[i] = syncobj_create(fd, 0);
+		syncobj_trigger(fd, syncobjs[i], points[i]);
+	}
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, syncobjs, points, 3, 0, 0), 0);
+
+	syncobj_reset(fd, syncobjs, 3);
+
+	for (i = 0; i < 3; i++) {
+		igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobjs[i],
+							&points[i], 1,
+							0, 0), -EINVAL);
+		syncobj_destroy(fd, syncobjs[i]);
+	}
+}
+
+static void
+reset_and_trigger_func(union sigval sigval)
+{
+	struct fd_handle_pair *pair = sigval.sival_ptr;
+	syncobj_reset(pair->fd, &pair->handle, 1);
+	syncobj_trigger(pair->fd, pair->handle, pair->point);
+}
+
+static const char *test_reset_during_wait_for_submit_desc =
+	"Verifies behavior of a reset operation a timeline syncobj while wait"
+	" operation is ongoing";
+static void
+test_reset_during_wait_for_submit(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint32_t flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+	struct fd_handle_pair pair;
+	uint64_t point = 1;
+	timer_t timer;
+
+	pair.fd = fd;
+	pair.handle = syncobj;
+	timer = set_timer(reset_and_trigger_func, &pair, 0, SHORT_TIME_NSEC);
+
+	/* A reset should be a no-op even if we're in the middle of a wait */
+	igt_assert(syncobj_timeline_wait(fd, &syncobj, &point, 1,
+				gettime_ns() + SHORT_TIME_NSEC * 2,
+				flags, NULL));
+
+	timer_delete(timer);
+
+	syncobj_destroy(fd, syncobj);
+}
+
+static const char *test_signal_desc =
+	"Verifies basic signaling of a timeline syncobj";
+static void
+test_signal(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint32_t flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+	uint64_t point = 1;
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point,
+						1, 0, 0), -EINVAL);
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &syncobj, &point,
+						1, 0, flags), -ETIME);
+
+	syncobj_timeline_signal(fd, &syncobj, &point, 1);
+
+	igt_assert(syncobj_timeline_wait(fd, &syncobj, &point, 1, 0, 0, NULL));
+	igt_assert(syncobj_timeline_wait(fd, &syncobj, &point, 1, 0, flags, NULL));
+
+	syncobj_destroy(fd, syncobj);
+}
+
+static const char *test_multi_wait_desc =
+	"Verifies waiting on a list of timeline syncobjs";
+static void
+test_multi_wait(int fd, uint32_t test_flags, int expect)
+{
+	uint32_t tflag, flags;
+	int i, fidx, timeline;
+	uint64_t points[5] = {
+		1 + rand() % 1000,
+		0, /* non timeline syncobj */
+		1 + rand() % 1000,
+		1 + rand() % 1000,
+		0, /* non timeline syncobj */
+	};
+	uint32_t syncobjs[ARRAY_SIZE(points)];
+
+	for (i = 0; i < ARRAY_SIZE(points); i++)
+		syncobjs[i] = syncobj_create(fd, 0);
+
+	flags = flags_for_test_flags(test_flags);
+	test_flags &= ~(WAIT_ALL | WAIT_FOR_SUBMIT | WAIT_AVAILABLE);
+
+	for (i = 0; i < ARRAY_SIZE(points); i++) {
+		fidx = ffs(test_flags) - 1;
+		tflag = (1 << fidx);
+
+		if (test_flags & ~tflag)
+			test_flags &= ~tflag;
+
+		if (tflag & (WAIT_SUBMITTED | WAIT_SIGNALED)) {
+			timeline = syncobj_attach_sw_sync(fd, syncobjs[i],
+							  points[i]);
+		}
+		if (tflag & WAIT_SIGNALED)
+			sw_sync_timeline_inc(timeline, 1);
+	}
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, syncobjs,
+						points, ARRAY_SIZE(points),
+						0, flags), expect);
+
+	igt_assert_eq(syncobj_timeline_wait_err(fd, syncobjs,
+						points, ARRAY_SIZE(points),
+						short_timeout(),
+						flags), expect);
+
+	if (expect != -ETIME) {
+		igt_assert_eq(syncobj_timeline_wait_err(fd, syncobjs,
+							points, ARRAY_SIZE(points),
+							UINT64_MAX,
+							flags), expect);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(points); i++)
+		syncobj_destroy(fd, syncobjs[i]);
+}
+
+struct wait_thread_data {
+	int fd;
+	struct drm_syncobj_timeline_wait wait;
+};
+
+static void *
+wait_thread_func(void *data)
+{
+	struct wait_thread_data *wait = data;
+	igt_assert_eq(__syncobj_timeline_wait_ioctl(wait->fd, &wait->wait), 0);
+	return NULL;
+}
+
+static const char *test_wait_snapshot_desc =
+	"Verifies waiting on a list of timeline syncobjs with different thread"
+	" for wait/signal";
+static void
+test_wait_snapshot(int fd, uint32_t test_flags)
+{
+	struct wait_thread_data wait = {};
+	uint32_t syncobjs[2];
+	uint64_t points[2] = {1, 1};
+	int timelines[3] = { -1, -1, -1 };
+	pthread_t thread;
+
+	syncobjs[0] = syncobj_create(fd, 0);
+	syncobjs[1] = syncobj_create(fd, 0);
+
+	if (!(test_flags & WAIT_FOR_SUBMIT)) {
+		timelines[0] = syncobj_attach_sw_sync(fd, syncobjs[0], points[0]);
+		timelines[1] = syncobj_attach_sw_sync(fd, syncobjs[1], points[1]);
+	}
+
+	wait.fd = fd;
+	wait.wait.handles = to_user_pointer(syncobjs);
+	wait.wait.count_handles = 2;
+	wait.wait.points = to_user_pointer(points);
+	wait.wait.timeout_nsec = short_timeout();
+	wait.wait.flags = flags_for_test_flags(test_flags);
+
+	igt_assert_eq(pthread_create(&thread, NULL, wait_thread_func, &wait), 0);
+
+	sleep_nsec(SHORT_TIME_NSEC / 5);
+
+	/* Try to fake the kernel out by triggering or partially triggering
+	 * the first fence.
+	 */
+	if (test_flags & WAIT_ALL) {
+		/* If it's WAIT_ALL, actually trigger it */
+		if (timelines[0] == -1)
+			syncobj_trigger(fd, syncobjs[0], points[0]);
+		else
+			sw_sync_timeline_inc(timelines[0], 1);
+	} else if (test_flags & WAIT_FOR_SUBMIT) {
+		timelines[0] = syncobj_attach_sw_sync(fd, syncobjs[0], points[0]);
+	}
+
+	sleep_nsec(SHORT_TIME_NSEC / 5);
+
+	/* Then reset it */
+	syncobj_reset(fd, &syncobjs[0], 1);
+
+	sleep_nsec(SHORT_TIME_NSEC / 5);
+
+	/* Then "submit" it in a way that will never trigger.  This way, if
+	 * the kernel picks up on the new fence (it shouldn't), we'll get a
+	 * timeout.
+	 */
+	timelines[2] = syncobj_attach_sw_sync(fd, syncobjs[0], points[0]);
+
+	sleep_nsec(SHORT_TIME_NSEC / 5);
+
+	/* Now trigger the second fence to complete the wait */
+
+	if (timelines[1] == -1)
+		syncobj_trigger(fd, syncobjs[1], points[1]);
+	else
+		sw_sync_timeline_inc(timelines[1], 1);
+
+	pthread_join(thread, NULL);
+
+	if (!(test_flags & WAIT_ALL))
+		igt_assert_eq(wait.wait.first_signaled, 1);
+
+	close(timelines[0]);
+	close(timelines[1]);
+	close(timelines[2]);
+	syncobj_destroy(fd, syncobjs[0]);
+	syncobj_destroy(fd, syncobjs[1]);
+}
+
+/* The numbers 0-7, each repeated 5x and shuffled. */
+static const unsigned shuffled_0_7_x4[] = {
+	2, 0, 6, 1, 1, 4, 5, 2, 0, 7, 1, 7, 6, 3, 4, 5,
+	0, 2, 7, 3, 5, 4, 0, 6, 7, 3, 2, 5, 6, 1, 4, 3,
+};
+
+enum syncobj_stage {
+	STAGE_UNSUBMITTED,
+	STAGE_SUBMITTED,
+	STAGE_SIGNALED,
+	STAGE_RESET,
+	STAGE_RESUBMITTED,
+};
+
+static const char *test_wait_complex_desc =
+	"Verifies timeline syncobj at different signal/operations stages &"
+	" between different threads.";
+static void
+test_wait_complex(int fd, uint32_t test_flags)
+{
+	struct wait_thread_data wait = {};
+	uint32_t syncobjs[8];
+	uint64_t points[8] = {1, 1, 1, 1, 1, 1, 1, 1};
+	enum syncobj_stage stage[8];
+	int i, j, timelines[8];
+	uint32_t first_signaled = -1, num_signaled = 0;
+	pthread_t thread;
+
+	for (i = 0; i < 8; i++) {
+		stage[i] = STAGE_UNSUBMITTED;
+		syncobjs[i] = syncobj_create(fd, 0);
+	}
+
+	if (test_flags & WAIT_FOR_SUBMIT) {
+		for (i = 0; i < 8; i++)
+			timelines[i] = -1;
+	} else {
+		for (i = 0; i < 8; i++)
+			timelines[i] = syncobj_attach_sw_sync(fd, syncobjs[i],
+							      points[i]);
+	}
+
+	wait.fd = fd;
+	wait.wait.handles = to_user_pointer(syncobjs);
+	wait.wait.count_handles = 2;
+	wait.wait.points = to_user_pointer(points);
+	wait.wait.timeout_nsec = gettime_ns() + NSECS_PER_SEC;
+	wait.wait.flags = flags_for_test_flags(test_flags);
+
+	igt_assert_eq(pthread_create(&thread, NULL, wait_thread_func, &wait), 0);
+
+	sleep_nsec(NSECS_PER_SEC / 50);
+
+	num_signaled = 0;
+	for (j = 0; j < ARRAY_SIZE(shuffled_0_7_x4); j++) {
+		i = shuffled_0_7_x4[j];
+		igt_assert_lt(i, ARRAY_SIZE(syncobjs));
+
+		switch (stage[i]++) {
+		case STAGE_UNSUBMITTED:
+			/* We need to submit attach a fence */
+			if (!(test_flags & WAIT_FOR_SUBMIT)) {
+				/* We had to attach one up-front */
+				igt_assert_neq(timelines[i], -1);
+				break;
+			}
+			timelines[i] = syncobj_attach_sw_sync(fd, syncobjs[i],
+							      points[i]);
+			break;
+
+		case STAGE_SUBMITTED:
+			/* We have a fence, trigger it */
+			igt_assert_neq(timelines[i], -1);
+			sw_sync_timeline_inc(timelines[i], 1);
+			close(timelines[i]);
+			timelines[i] = -1;
+			if (num_signaled == 0)
+				first_signaled = i;
+			num_signaled++;
+			break;
+
+		case STAGE_SIGNALED:
+			/* We're already signaled, reset */
+			syncobj_reset(fd, &syncobjs[i], 1);
+			break;
+
+		case STAGE_RESET:
+			/* We're reset, submit and don't signal */
+			timelines[i] = syncobj_attach_sw_sync(fd, syncobjs[i],
+							      points[i]);
+			break;
+
+		case STAGE_RESUBMITTED:
+			igt_assert(!"Should not reach this stage");
+			break;
+		}
+
+		if (test_flags & WAIT_ALL) {
+			if (num_signaled == ARRAY_SIZE(syncobjs))
+				break;
+		} else {
+			if (num_signaled > 0)
+				break;
+		}
+
+		sleep_nsec(NSECS_PER_SEC / 100);
+	}
+
+	pthread_join(thread, NULL);
+
+	if (test_flags & WAIT_ALL) {
+		igt_assert_eq(num_signaled, ARRAY_SIZE(syncobjs));
+	} else {
+		igt_assert_eq(num_signaled, 1);
+		igt_assert_eq(wait.wait.first_signaled, first_signaled);
+	}
+
+	for (i = 0; i < 8; i++) {
+		close(timelines[i]);
+		syncobj_destroy(fd, syncobjs[i]);
+	}
+}
+
+static const char *test_wait_interrupted_desc =
+	"Verifies timeline syncobj waits interaction with signals.";
+static void
+test_wait_interrupted(int fd, uint32_t test_flags)
+{
+	struct drm_syncobj_timeline_wait wait = {};
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint64_t point = 1;
+	int timeline;
+
+	wait.handles = to_user_pointer(&syncobj);
+	wait.points = to_user_pointer(&point);
+	wait.count_handles = 1;
+	wait.flags = flags_for_test_flags(test_flags);
+
+	if (test_flags & WAIT_FOR_SUBMIT) {
+		wait.timeout_nsec = short_timeout();
+		igt_while_interruptible(true)
+			igt_assert_eq(__syncobj_timeline_wait_ioctl(fd, &wait), -ETIME);
+	}
+
+	timeline = syncobj_attach_sw_sync(fd, syncobj, point);
+
+	wait.timeout_nsec = short_timeout();
+	igt_while_interruptible(true)
+		igt_assert_eq(__syncobj_timeline_wait_ioctl(fd, &wait), -ETIME);
+
+	syncobj_destroy(fd, syncobj);
+	close(timeline);
+}
+
+static bool
+has_syncobj_timeline_wait(int fd)
+{
+	struct drm_syncobj_timeline_wait wait = {};
+	uint32_t handle = 0;
+	uint64_t value;
+	int ret;
+
+	if (drmGetCap(fd, DRM_CAP_SYNCOBJ_TIMELINE, &value))
+		return false;
+	if (!value)
+		return false;
+
+	/* Try waiting for zero sync objects should fail with EINVAL */
+	wait.count_handles = 1;
+	wait.handles = to_user_pointer(&handle);
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &wait);
+	return ret == -1 && errno == ENOENT;
+}
+
+igt_main
+{
+	int fd = -1;
+
+	igt_fixture {
+		fd = drm_open_driver(DRIVER_ANY);
+		igt_require(has_syncobj_timeline_wait(fd));
+		igt_require_sw_sync();
+	}
+
+	igt_describe(test_wait_bad_flags_desc);
+	igt_subtest("invalid-wait-bad-flags")
+		test_wait_bad_flags(fd);
+
+	igt_describe(test_wait_zero_handles_desc);
+	igt_subtest("invalid-wait-zero-handles")
+		test_wait_zero_handles(fd);
+
+	igt_describe(test_wait_illegal_handle_desc);
+	igt_subtest("invalid-wait-illegal-handle")
+		test_wait_illegal_handle(fd);
+
+	igt_describe(test_query_zero_handles_desc);
+	igt_subtest("invalid-query-zero-handles")
+		test_query_zero_handles(fd);
+
+	igt_describe(test_query_illegal_handle_desc);
+	igt_subtest("invalid-query-illegal-handle")
+		test_query_illegal_handle(fd);
+
+	igt_describe(test_query_one_illegal_handle_desc);
+	igt_subtest("invalid-query-one-illegal-handle")
+		test_query_one_illegal_handle(fd);
+
+	igt_describe(test_query_bad_pad_desc);
+	igt_subtest("invalid-query-bad-pad")
+		test_query_bad_pad(fd);
+
+	igt_describe(test_signal_zero_handles_desc);
+	igt_subtest("invalid-signal-zero-handles")
+		test_signal_zero_handles(fd);
+
+	igt_describe(test_signal_illegal_handle_desc);
+	igt_subtest("invalid-signal-illegal-handle")
+		test_signal_illegal_handle(fd);
+
+	igt_subtest("invalid-signal-illegal-point")
+		test_signal_illegal_point(fd);
+
+	igt_describe(test_signal_one_illegal_handle_desc);
+	igt_subtest("invalid-signal-one-illegal-handle")
+		test_signal_one_illegal_handle(fd);
+
+	igt_describe(test_signal_bad_pad_desc);
+	igt_subtest("invalid-signal-bad-pad")
+		test_signal_bad_pad(fd);
+
+	igt_describe(test_signal_array_desc);
+	igt_subtest("signal-array")
+		test_signal_array(fd);
+
+	igt_describe(test_transfer_illegal_handle_desc);
+	igt_subtest("invalid-transfer-illegal-handle")
+		test_transfer_illegal_handle(fd);
+
+	igt_describe(test_transfer_bad_pad_desc);
+	igt_subtest("invalid-transfer-bad-pad")
+		test_transfer_bad_pad(fd);
+
+	for (unsigned flags = 0; flags < WAIT_FLAGS_MAX; flags++) {
+		int err;
+
+		/* Only one wait mode for single-wait tests */
+		if (__builtin_popcount(flags & (WAIT_UNSUBMITTED |
+						WAIT_SUBMITTED |
+						WAIT_SIGNALED)) != 1)
+			continue;
+
+		if ((flags & WAIT_UNSUBMITTED) && !(flags & WAIT_FOR_SUBMIT))
+			err = -EINVAL;
+		else if (!(flags & WAIT_SIGNALED) && !((flags & WAIT_SUBMITTED) && (flags & WAIT_AVAILABLE)))
+			err = -ETIME;
+		else
+			err = 0;
+
+		igt_describe(test_signal_wait_desc);
+		igt_subtest_f("%ssingle-wait%s%s%s%s%s%s",
+			      err == -EINVAL ? "invalid-" : err == -ETIME ? "etime-" : "",
+			      (flags & WAIT_ALL) ? "-all" : "",
+			      (flags & WAIT_FOR_SUBMIT) ? "-for-submit" : "",
+			      (flags & WAIT_AVAILABLE) ? "-available" : "",
+			      (flags & WAIT_UNSUBMITTED) ? "-unsubmitted" : "",
+			      (flags & WAIT_SUBMITTED) ? "-submitted" : "",
+			      (flags & WAIT_SIGNALED) ? "-signaled" : "")
+			test_single_wait(fd, flags, err);
+	}
+
+	igt_describe(test_wait_delayed_signal_desc);
+	igt_subtest("wait-delayed-signal")
+		test_wait_delayed_signal(fd, 0);
+
+	igt_describe(test_wait_delayed_signal_desc);
+	igt_subtest("wait-for-submit-delayed-submit")
+		test_wait_delayed_signal(fd, WAIT_FOR_SUBMIT);
+
+	igt_describe(test_wait_delayed_signal_desc);
+	igt_subtest("wait-all-delayed-signal")
+		test_wait_delayed_signal(fd, WAIT_ALL);
+
+	igt_describe(test_wait_delayed_signal_desc);
+	igt_subtest("wait-all-for-submit-delayed-submit")
+		test_wait_delayed_signal(fd, WAIT_ALL | WAIT_FOR_SUBMIT);
+
+	igt_describe(test_reset_unsignaled_desc);
+	igt_subtest("reset-unsignaled")
+		test_reset_unsignaled(fd);
+
+	igt_describe(test_reset_signaled_desc);
+	igt_subtest("reset-signaled")
+		test_reset_signaled(fd);
+
+	igt_describe(test_reset_multiple_signaled_desc);
+	igt_subtest("reset-multiple-signaled")
+		test_reset_multiple_signaled(fd);
+
+	igt_describe(test_reset_during_wait_for_submit_desc);
+	igt_subtest("reset-during-wait-for-submit")
+		test_reset_during_wait_for_submit(fd);
+
+	igt_describe(test_signal_desc);
+	igt_subtest("signal")
+		test_signal(fd);
+
+	for (unsigned flags = 0; flags < WAIT_FLAGS_MAX; flags++) {
+		int err;
+
+		/* At least one wait mode for multi-wait tests */
+		if (!(flags & (WAIT_UNSUBMITTED |
+			       WAIT_SUBMITTED |
+			       WAIT_SIGNALED)))
+			continue;
+
+		err = 0;
+		if ((flags & WAIT_UNSUBMITTED) && !(flags & WAIT_FOR_SUBMIT)) {
+			err = -EINVAL;
+		} else if (flags & WAIT_ALL) {
+			if (flags & (WAIT_UNSUBMITTED | WAIT_SUBMITTED))
+				err = -ETIME;
+			if (!(flags & WAIT_UNSUBMITTED) && (flags & WAIT_SUBMITTED) && (flags & WAIT_AVAILABLE))
+				err = 0;
+		} else {
+			if (!(flags & WAIT_SIGNALED) && !((flags & WAIT_SUBMITTED) && (flags & WAIT_AVAILABLE)))
+				err = -ETIME;
+		}
+
+		igt_describe(test_multi_wait_desc);
+		igt_subtest_f("%smulti-wait%s%s%s%s%s%s",
+			      err == -EINVAL ? "invalid-" : err == -ETIME ? "etime-" : "",
+			      (flags & WAIT_ALL) ? "-all" : "",
+			      (flags & WAIT_FOR_SUBMIT) ? "-for-submit" : "",
+			      (flags & WAIT_AVAILABLE) ? "-available" : "",
+			      (flags & WAIT_UNSUBMITTED) ? "-unsubmitted" : "",
+			      (flags & WAIT_SUBMITTED) ? "-submitted" : "",
+			      (flags & WAIT_SIGNALED) ? "-signaled" : "")
+			test_multi_wait(fd, flags, err);
+	}
+
+	igt_describe(test_wait_snapshot_desc);
+	igt_subtest("wait-any-snapshot")
+		test_wait_snapshot(fd, 0);
+
+	igt_describe(test_wait_snapshot_desc);
+	igt_subtest("wait-all-snapshot")
+		test_wait_snapshot(fd, WAIT_ALL);
+
+	igt_describe(test_wait_snapshot_desc);
+	igt_subtest("wait-for-submit-snapshot")
+		test_wait_snapshot(fd, WAIT_FOR_SUBMIT);
+
+	igt_describe(test_wait_snapshot_desc);
+	igt_subtest("wait-all-for-submit-snapshot")
+		test_wait_snapshot(fd, WAIT_ALL | WAIT_FOR_SUBMIT);
+
+	igt_describe(test_wait_complex_desc);
+	igt_subtest("wait-any-complex")
+		test_wait_complex(fd, 0);
+
+	igt_describe(test_wait_complex_desc);
+	igt_subtest("wait-all-complex")
+		test_wait_complex(fd, WAIT_ALL);
+
+	igt_describe(test_wait_complex_desc);
+	igt_subtest("wait-for-submit-complex")
+		test_wait_complex(fd, WAIT_FOR_SUBMIT);
+
+	igt_describe(test_wait_complex_desc);
+	igt_subtest("wait-all-for-submit-complex")
+		test_wait_complex(fd, WAIT_ALL | WAIT_FOR_SUBMIT);
+
+	igt_describe(test_wait_interrupted_desc);
+	igt_subtest("wait-any-interrupted")
+		test_wait_interrupted(fd, 0);
+
+	igt_describe(test_wait_interrupted_desc);
+	igt_subtest("wait-all-interrupted")
+		test_wait_interrupted(fd, WAIT_ALL);
+}
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 04/10] tests/syncobj_timeline: add more timeline tests
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (2 preceding siblings ...)
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 03/10] igt: add timeline test cases Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 05/10] tests/i915/exec_fence: switch to internal headers Lionel Landwerlin
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

Including ordering tests and 32bit limit.

v2: add point 0 signaling test (Lionel)

v3: Use READ_ONCE() in thread checker (Chris)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/igt_syncobj.c        |  73 ++++----
 lib/igt_syncobj.h        |   3 +
 tests/syncobj_timeline.c | 387 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 426 insertions(+), 37 deletions(-)

diff --git a/lib/igt_syncobj.c b/lib/igt_syncobj.c
index b211dfef..a24ed10b 100644
--- a/lib/igt_syncobj.c
+++ b/lib/igt_syncobj.c
@@ -459,17 +459,19 @@ syncobj_timeline_query(int fd, uint32_t *handles, uint64_t *points,
 }
 
 static int
-__syncobj_binary_to_timeline(int fd, uint32_t timeline_handle,
-			     uint64_t point, uint32_t binary_handle)
+__syncobj_transfer(int fd,
+		   uint32_t handle_dst, uint64_t point_dst,
+		   uint32_t handle_src, uint64_t point_src,
+		   uint32_t flags)
 {
 	struct drm_syncobj_transfer args;
 	int ret;
 
-	args.src_handle = binary_handle;
-	args.dst_handle = timeline_handle;
-	args.src_point = 0;
-	args.dst_point = point;
-	args.flags = 0;
+	args.src_handle = handle_src;
+	args.dst_handle = handle_dst;
+	args.src_point = point_src;
+	args.dst_point = point_dst;
+	args.flags = flags;
 	args.pad = 0;
 	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args);
 	if (ret) {
@@ -495,33 +497,9 @@ void
 syncobj_binary_to_timeline(int fd, uint32_t timeline_handle,
 			   uint64_t point, uint32_t binary_handle)
 {
-	igt_assert_eq(__syncobj_binary_to_timeline(fd, timeline_handle, point,
-						   binary_handle), 0);
-}
-
-static int
-__syncobj_timeline_to_binary(int fd, uint32_t binary_handle,
-			     uint32_t timeline_handle,
-			     uint64_t point,
-			     uint32_t flags)
-{
-	struct drm_syncobj_transfer args;
-	int ret;
-
-	args.dst_handle = binary_handle;
-	args.src_handle = timeline_handle;
-	args.dst_point = 0;
-	args.src_point = point;
-	args.flags = flags;
-	args.pad = 0;
-	ret = drmIoctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &args);
-	if (ret) {
-		ret = -errno;
-		igt_assert(ret);
-	}
-
-	errno = 0;
-	return ret;
+	igt_assert_eq(__syncobj_transfer(fd,
+					 timeline_handle, point,
+					 binary_handle, 0, 0), 0);
 }
 
 /**
@@ -540,7 +518,28 @@ syncobj_timeline_to_binary(int fd, uint32_t binary_handle,
 			   uint64_t point,
 			   uint32_t flags)
 {
-	igt_assert_eq(__syncobj_timeline_to_binary(fd, binary_handle,
-						   timeline_handle, point,
-						   flags), 0);
+	igt_assert_eq(__syncobj_transfer(fd,
+					 binary_handle, 0,
+					 timeline_handle, point,
+					 flags), 0);
+}
+
+/**
+ * syncobj_timeline_to_timeline:
+ * @fd: The DRM file descriptor.
+ * @timeline_src: A timeline syncobj handle
+ * @timeline_dst: A timeline syncobj handle
+ * @point_src: A point on the source timeline syncobj
+ * @point_dst: A point on the destination timeline syncobj
+ *
+ * query a set of syncobjs.
+ */
+void
+syncobj_timeline_to_timeline(int fd,
+			     uint64_t timeline_dst, uint32_t point_dst,
+			     uint64_t timeline_src, uint32_t point_src)
+{
+	igt_assert_eq(__syncobj_transfer(fd,
+					 timeline_dst, point_dst,
+					 timeline_src, point_src, 0), 0);
 }
diff --git a/lib/igt_syncobj.h b/lib/igt_syncobj.h
index 20f1f18f..e6725671 100644
--- a/lib/igt_syncobj.h
+++ b/lib/igt_syncobj.h
@@ -60,6 +60,9 @@ void syncobj_timeline_to_binary(int fd, uint32_t binary_handle,
 				uint32_t timeline_handle,
 				uint64_t point,
 				uint32_t flags);
+void syncobj_timeline_to_timeline(int fd,
+				  uint64_t timeline_dst, uint32_t point_dst,
+				  uint64_t timeline_src, uint32_t point_src);
 void syncobj_timeline_signal(int fd, uint32_t *handles, uint64_t *points,
 			     uint32_t count);
 
diff --git a/tests/syncobj_timeline.c b/tests/syncobj_timeline.c
index 82fc08aa..319dc1bd 100644
--- a/tests/syncobj_timeline.c
+++ b/tests/syncobj_timeline.c
@@ -406,6 +406,29 @@ test_transfer_bad_pad(int fd)
 	igt_assert(ret == -1 && errno == EINVAL);
 }
 
+static const char *test_transfer_nonexistent_point_desc =
+	"Verifies that transfering a point from a syncobj timeline is to"
+	" another point in the same timeline works";
+static void
+test_transfer_nonexistent_point(int fd)
+{
+	struct drm_syncobj_transfer arg = {};
+	uint32_t handle = syncobj_create(fd, 0);
+	uint64_t value = 63;
+	int ret;
+
+	syncobj_timeline_signal(fd, &handle, &value, 1);
+
+	arg.src_handle = handle;
+	arg.dst_handle = handle;
+	arg.src_point = value; /* Point doesn't exist */
+	arg.dst_point = value + 11;
+	ret = igt_ioctl(fd, DRM_IOCTL_SYNCOBJ_TRANSFER, &arg);
+	igt_assert(ret == 0);
+
+	syncobj_destroy(fd, handle);
+}
+
 #define WAIT_FOR_SUBMIT		(1 << 0)
 #define WAIT_ALL		(1 << 1)
 #define WAIT_AVAILABLE		(1 << 2)
@@ -414,6 +437,53 @@ test_transfer_bad_pad(int fd)
 #define WAIT_SIGNALED		(1 << 5)
 #define WAIT_FLAGS_MAX		(1 << 6) - 1
 
+static const char *test_transfer_point_desc =
+	"Verifies that transfering a point from a syncobj timeline is to"
+	" another point in the same timeline works for signal/wait operations";
+static void
+test_transfer_point(int fd)
+{
+	int timeline = sw_sync_timeline_create();
+	uint32_t handle = syncobj_create(fd, 0);
+	uint64_t value;
+
+	{
+		int sw_fence = sw_sync_timeline_create_fence(timeline, 1);
+		uint32_t tmp_syncobj = syncobj_create(fd, 0);
+
+		syncobj_import_sync_file(fd, tmp_syncobj, sw_fence);
+		syncobj_binary_to_timeline(fd, handle, 1, tmp_syncobj);
+		close(sw_fence);
+		syncobj_destroy(fd, tmp_syncobj);
+	}
+
+	syncobj_timeline_query(fd, &handle, &value, 1);
+	igt_assert_eq(value, 0);
+
+	value = 1;
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &handle, &value,
+						1, 0, WAIT_ALL), -ETIME);
+
+	sw_sync_timeline_inc(timeline, 1);
+
+	syncobj_timeline_query(fd, &handle, &value, 1);
+	igt_assert_eq(value, 1);
+
+	igt_assert(syncobj_timeline_wait(fd, &handle, &value,
+					 1, 0, WAIT_ALL, NULL));
+
+	value = 2;
+	syncobj_timeline_signal(fd, &handle, &value, 1);
+
+	syncobj_timeline_to_timeline(fd, handle, 3, handle, 2);
+
+	syncobj_timeline_query(fd, &handle, &value, 1);
+	igt_assert_eq(value, 3);
+
+	syncobj_destroy(fd, handle);
+	close(timeline);
+}
+
 static uint32_t
 flags_for_test_flags(uint32_t test_flags)
 {
@@ -619,6 +689,24 @@ test_signal(int fd)
 	syncobj_destroy(fd, syncobj);
 }
 
+static const char *test_signal_point_0_desc =
+	"Verifies that signaling point 0 of a timline syncobj works with both"
+	" timeline & legacy wait operations";
+static void
+test_signal_point_0(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint32_t flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;
+	uint64_t point = 0;
+
+	syncobj_timeline_signal(fd, &syncobj, &point, 1);
+
+	igt_assert(syncobj_timeline_wait(fd, &syncobj, &point, 1, 0, 0, NULL));
+	igt_assert(syncobj_wait(fd, &syncobj, 1, 0, flags, NULL));
+
+	syncobj_destroy(fd, syncobj);
+}
+
 static const char *test_multi_wait_desc =
 	"Verifies waiting on a list of timeline syncobjs";
 static void
@@ -921,6 +1009,273 @@ test_wait_interrupted(int fd, uint32_t test_flags)
 	close(timeline);
 }
 
+const char *test_host_signal_points_desc =
+	"Verifies that as we signal points from the host, the syncobj timeline"
+	" value increments and that waits for submits/signals works properly.";
+static void
+test_host_signal_points(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint64_t value = 0;
+	int i;
+
+	for (i = 0; i < 100; i++) {
+		uint64_t query_value = 0;
+
+		value += rand();
+
+		syncobj_timeline_signal(fd, &syncobj, &value, 1);
+
+		syncobj_timeline_query(fd, &syncobj, &query_value, 1);
+		igt_assert_eq(query_value, value);
+
+		igt_assert(syncobj_timeline_wait(fd, &syncobj, &query_value,
+						 1, 0, WAIT_FOR_SUBMIT, NULL));
+
+		query_value -= 1;
+		igt_assert(syncobj_timeline_wait(fd, &syncobj, &query_value,
+						 1, 0, WAIT_ALL, NULL));
+	}
+
+	syncobj_destroy(fd, syncobj);
+}
+
+const char *test_device_signal_unordered_desc =
+	"Verifies that a device signaling fences out of order on the timeline"
+	" still increments the timeline monotonically and that waits work"
+	" properly.";
+static void
+test_device_signal_unordered(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	int point_indices[] = { 0, 2, 1, 4, 3 };
+	bool signaled[ARRAY_SIZE(point_indices)] = {};
+	int fences[ARRAY_SIZE(point_indices)];
+	int timeline = sw_sync_timeline_create();
+	uint64_t value = 0;
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(fences); i++) {
+		fences[point_indices[i]] = sw_sync_timeline_create_fence(timeline, i + 1);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(fences); i++) {
+		uint32_t tmp_syncobj = syncobj_create(fd, 0);
+
+		syncobj_import_sync_file(fd, tmp_syncobj, fences[i]);
+		syncobj_binary_to_timeline(fd, syncobj, i + 1, tmp_syncobj);
+		syncobj_destroy(fd, tmp_syncobj);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(fences); i++) {
+		uint64_t query_value = 0;
+		uint64_t min_value = 0;
+
+		sw_sync_timeline_inc(timeline, 1);
+
+		signaled[point_indices[i]] = true;
+
+		/*
+		 * Compute a minimum value of the timeline based of
+		 * the smallest signaled point.
+		 */
+		for (j = 0; j < ARRAY_SIZE(signaled); j++) {
+			if (!signaled[j])
+				break;
+			min_value = j;
+		}
+
+		syncobj_timeline_query(fd, &syncobj, &query_value, 1);
+		igt_assert(query_value >= min_value);
+		igt_assert(query_value >= value);
+
+		igt_debug("signaling point %i, timeline value = %" PRIu64 "\n",
+			  point_indices[i] + 1, query_value);
+
+		value = max(query_value, value);
+
+		igt_assert(syncobj_timeline_wait(fd, &syncobj, &query_value,
+						 1, 0, WAIT_FOR_SUBMIT, NULL));
+
+		igt_assert(syncobj_timeline_wait(fd, &syncobj, &query_value,
+						 1, 0, WAIT_ALL, NULL));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(fences); i++)
+		close(fences[i]);
+
+	syncobj_destroy(fd, syncobj);
+	close(timeline);
+}
+
+const char *test_device_submit_unordered_desc =
+	"Verifies that submitting out of order doesn't break the timeline.";
+static void
+test_device_submit_unordered(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	uint64_t points[] = { 1, 5, 3, 6, 7 };
+	int timeline = sw_sync_timeline_create();
+	uint64_t query_value;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(points); i++) {
+		int fence = sw_sync_timeline_create_fence(timeline, i + 1);
+		uint32_t tmp_syncobj = syncobj_create(fd, 0);
+
+		syncobj_import_sync_file(fd, tmp_syncobj, fence);
+		syncobj_binary_to_timeline(fd, syncobj, points[i], tmp_syncobj);
+		close(fence);
+		syncobj_destroy(fd, tmp_syncobj);
+	}
+
+	/*
+	 * Signal points 1, 5 & 3. There are no other points <= 5 so
+	 * waiting on 5 should return immediately for submission &
+	 * signaling.
+	 */
+	sw_sync_timeline_inc(timeline, 3);
+
+	syncobj_timeline_query(fd, &syncobj, &query_value, 1);
+	igt_assert_eq(query_value, 5);
+
+	igt_assert(syncobj_timeline_wait(fd, &syncobj, &query_value,
+					 1, 0, WAIT_FOR_SUBMIT, NULL));
+
+	igt_assert(syncobj_timeline_wait(fd, &syncobj, &query_value,
+					 1, 0, WAIT_ALL, NULL));
+
+	syncobj_destroy(fd, syncobj);
+	close(timeline);
+}
+
+const char *test_host_signal_ordered_desc =
+	"Verifies that the host signaling fences out of order on the timeline"
+	" still increments the timeline monotonically and that waits work"
+	" properly.";
+static void
+test_host_signal_ordered(int fd)
+{
+	uint32_t syncobj = syncobj_create(fd, 0);
+	int timeline = sw_sync_timeline_create();
+	uint64_t host_signal_value = 8, query_value;
+	int i;
+
+	for (i = 0; i < 5; i++) {
+		int fence = sw_sync_timeline_create_fence(timeline, i + 1);
+		uint32_t tmp_syncobj = syncobj_create(fd, 0);
+
+		syncobj_import_sync_file(fd, tmp_syncobj, fence);
+		syncobj_binary_to_timeline(fd, syncobj, i + 1, tmp_syncobj);
+		syncobj_destroy(fd, tmp_syncobj);
+		close(fence);
+	}
+
+	sw_sync_timeline_inc(timeline, 3);
+
+	syncobj_timeline_query(fd, &syncobj, &query_value, 1);
+	igt_assert_eq(query_value, 3);
+
+	syncobj_timeline_signal(fd, &syncobj, &host_signal_value, 1);
+
+	syncobj_timeline_query(fd, &syncobj, &query_value, 1);
+	igt_assert_eq(query_value, 3);
+
+	sw_sync_timeline_inc(timeline, 5);
+
+	syncobj_timeline_query(fd, &syncobj, &query_value, 1);
+	igt_assert_eq(query_value, 8);
+
+	syncobj_destroy(fd, syncobj);
+	close(timeline);
+}
+
+struct checker_thread_data {
+	int fd;
+	uint32_t syncobj;
+	bool running;
+	bool started;
+};
+
+static void *
+checker_thread_func(void *_data)
+{
+	struct checker_thread_data *data = _data;
+	uint64_t value, last_value = 0;
+
+	while (READ_ONCE(data->running)) {
+		syncobj_timeline_query(data->fd, &data->syncobj, &value, 1);
+
+		data->started = true;
+
+		igt_assert(last_value <= value);
+		last_value = value;
+	}
+
+	return NULL;
+}
+
+const char *test_32bits_limit_desc =
+	"Verifies that signaling around the int32_t limit. For compatibility"
+	" reason, the handling of seqnos in the dma-fences can consider a seqnoA"
+	" is prior seqnoB even though seqnoA > seqnoB.";
+/*
+ * Fixed in kernel commit :
+ *
+ * commit b312d8ca3a7cebe19941d969a51f2b7f899b81e2
+ * Author: Christian König <christian.koenig@amd.com>
+ * Date:   Wed Nov 14 16:11:06 2018 +0100
+ *
+ *    dma-buf: make fence sequence numbers 64 bit v2
+ *
+ */
+static void
+test_32bits_limit(int fd)
+{
+	struct checker_thread_data thread_data = {
+		.fd = fd,
+		.syncobj = syncobj_create(fd, 0),
+		.running = true,
+		.started = false,
+	};
+	int timeline = sw_sync_timeline_create();
+	uint64_t limit_diff = (1ull << 31) - 1;
+	uint64_t points[] = { 1, 5, limit_diff + 5, limit_diff + 6, limit_diff * 2, };
+	pthread_t thread;
+	uint64_t value, last_value;
+	int i;
+
+	igt_assert_eq(pthread_create(&thread, NULL, checker_thread_func, &thread_data), 0);
+
+	while (!thread_data.started);
+
+	for (i = 0; i < ARRAY_SIZE(points); i++) {
+		int fence = sw_sync_timeline_create_fence(timeline, i + 1);
+		uint32_t tmp_syncobj = syncobj_create(fd, 0);
+
+		syncobj_import_sync_file(fd, tmp_syncobj, fence);
+		syncobj_binary_to_timeline(fd, thread_data.syncobj, points[i], tmp_syncobj);
+		close(fence);
+		syncobj_destroy(fd, tmp_syncobj);
+	}
+
+	last_value = 0;
+	for (i = 0; i < ARRAY_SIZE(points); i++) {
+		sw_sync_timeline_inc(timeline, 1);
+
+		syncobj_timeline_query(fd, &thread_data.syncobj, &value, 1);
+		igt_assert(last_value <= value);
+
+		last_value = value;
+	}
+
+	thread_data.running = false;
+	pthread_join(thread, NULL);
+
+	syncobj_destroy(fd, thread_data.syncobj);
+	close(timeline);
+}
+
 static bool
 has_syncobj_timeline_wait(int fd)
 {
@@ -1010,6 +1365,14 @@ igt_main
 	igt_subtest("invalid-transfer-bad-pad")
 		test_transfer_bad_pad(fd);
 
+	igt_describe(test_transfer_nonexistent_point_desc);
+	igt_subtest("invalid-transfer-non-existent-point")
+		test_transfer_nonexistent_point(fd);
+
+	igt_describe(test_transfer_point_desc);
+	igt_subtest("transfer-timeline-point")
+		test_transfer_point(fd);
+
 	for (unsigned flags = 0; flags < WAIT_FLAGS_MAX; flags++) {
 		int err;
 
@@ -1074,6 +1437,10 @@ igt_main
 	igt_subtest("signal")
 		test_signal(fd);
 
+	igt_describe(test_signal_point_0_desc);
+	igt_subtest("signal-point-0")
+		test_signal_point_0(fd);
+
 	for (unsigned flags = 0; flags < WAIT_FLAGS_MAX; flags++) {
 		int err;
 
@@ -1147,4 +1514,24 @@ igt_main
 	igt_describe(test_wait_interrupted_desc);
 	igt_subtest("wait-all-interrupted")
 		test_wait_interrupted(fd, WAIT_ALL);
+
+	igt_describe(test_host_signal_points_desc);
+	igt_subtest("host-signal-points")
+		test_host_signal_points(fd);
+
+	igt_describe(test_device_signal_unordered_desc);
+	igt_subtest("device-signal-unordered")
+		test_device_signal_unordered(fd);
+
+	igt_describe(test_device_submit_unordered_desc);
+	igt_subtest("device-submit-unordered")
+		test_device_submit_unordered(fd);
+
+	igt_describe(test_host_signal_ordered_desc);
+	igt_subtest("host-signal-ordered")
+		test_host_signal_ordered(fd);
+
+	igt_describe(test_32bits_limit_desc);
+	igt_subtest("32bits-limit")
+		test_32bits_limit(fd);
 }
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 05/10] tests/i915/exec_fence: switch to internal headers
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (3 preceding siblings ...)
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 04/10] tests/syncobj_timeline: add more timeline tests Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 06/10] tests/i915/exec_fence: reuse syncobj helpers Lionel Landwerlin
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

Drop local defines etc..

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 tests/i915/gem_exec_fence.c | 122 ++++++++++++++++--------------------
 1 file changed, 55 insertions(+), 67 deletions(-)

diff --git a/tests/i915/gem_exec_fence.c b/tests/i915/gem_exec_fence.c
index fbb11ab2..b8fa1a03 100644
--- a/tests/i915/gem_exec_fence.c
+++ b/tests/i915/gem_exec_fence.c
@@ -33,18 +33,6 @@
 
 IGT_TEST_DESCRIPTION("Check that execbuf waits for explicit fences");
 
-#define LOCAL_EXEC_FENCE_IN (1 << 16)
-#define LOCAL_EXEC_FENCE_OUT (1 << 17)
-#define LOCAL_EXEC_FENCE_SUBMIT (1 << 20)
-
-#define LOCAL_EXEC_FENCE_ARRAY (1 << 19)
-struct local_gem_exec_fence {
-	uint32_t handle;
-	uint32_t flags;
-#define LOCAL_EXEC_FENCE_WAIT (1 << 0)
-#define LOCAL_EXEC_FENCE_SIGNAL (1 << 1)
-};
-
 #ifndef SYNC_IOC_MERGE
 struct sync_merge_data {
 	char    name[32];
@@ -71,7 +59,7 @@ static void store(int fd, unsigned ring, int fence, uint32_t target, unsigned of
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(obj);
 	execbuf.buffer_count = 2;
-	execbuf.flags = ring | LOCAL_EXEC_FENCE_IN;
+	execbuf.flags = ring | I915_EXEC_FENCE_IN;
 	execbuf.rsvd2 = fence;
 	if (gen < 6)
 		execbuf.flags |= I915_EXEC_SECURE;
@@ -137,7 +125,7 @@ static void test_fence_busy(int fd, unsigned ring, unsigned flags)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = ring | LOCAL_EXEC_FENCE_OUT;
+	execbuf.flags = ring | I915_EXEC_FENCE_OUT;
 
 	memset(&obj, 0, sizeof(obj));
 	obj.handle = gem_create(fd, 4096);
@@ -270,7 +258,7 @@ static void test_fence_busy_all(int fd, unsigned flags)
 
 		if ((flags & HANG) == 0)
 			igt_require(gem_engine_has_mutable_submission(fd, eb_ring(e)));
-		execbuf.flags = eb_ring(e) | LOCAL_EXEC_FENCE_OUT;
+		execbuf.flags = eb_ring(e) | I915_EXEC_FENCE_OUT;
 		execbuf.rsvd2 = -1;
 		gem_execbuf_wr(fd, &execbuf);
 		fence = execbuf.rsvd2 >> 32;
@@ -435,7 +423,7 @@ static void test_parallel(int fd, unsigned int master)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(obj);
 	execbuf.buffer_count = 2;
-	execbuf.flags = master | LOCAL_EXEC_FENCE_OUT;
+	execbuf.flags = master | I915_EXEC_FENCE_OUT;
 	if (gen < 6)
 		execbuf.flags |= I915_EXEC_SECURE;
 
@@ -508,7 +496,7 @@ static void test_parallel(int fd, unsigned int master)
 		if (eb_ring(e) == master)
 			continue;
 
-		execbuf.flags = eb_ring(e) | LOCAL_EXEC_FENCE_SUBMIT;
+		execbuf.flags = eb_ring(e) | I915_EXEC_FENCE_SUBMIT;
 		if (gen < 6)
 			execbuf.flags |= I915_EXEC_SECURE;
 
@@ -604,7 +592,7 @@ static void test_keep_in_fence(int fd, unsigned int engine, unsigned int flags)
 	struct drm_i915_gem_execbuffer2 execbuf = {
 		.buffers_ptr = to_user_pointer(&obj),
 		.buffer_count = 1,
-		.flags = engine | LOCAL_EXEC_FENCE_OUT,
+		.flags = engine | I915_EXEC_FENCE_OUT,
 	};
 	unsigned long count, last;
 	struct itimerval itv;
@@ -623,7 +611,7 @@ static void test_keep_in_fence(int fd, unsigned int engine, unsigned int flags)
 	itv.it_value.tv_usec = 10000;
 	setitimer(ITIMER_REAL, &itv, NULL);
 
-	execbuf.flags |= LOCAL_EXEC_FENCE_IN;
+	execbuf.flags |= I915_EXEC_FENCE_IN;
 	execbuf.rsvd2 = fence;
 
 	last = -1;
@@ -692,7 +680,7 @@ static void test_long_history(int fd, long ring_size, unsigned flags)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj[1]);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_OUT;
+	execbuf.flags = I915_EXEC_FENCE_OUT;
 
 	gem_execbuf_wr(fd, &execbuf);
 	all_fences = execbuf.rsvd2 >> 32;
@@ -708,7 +696,7 @@ static void test_long_history(int fd, long ring_size, unsigned flags)
 		for (n = 0; n < nengine; n++) {
 			struct sync_merge_data merge;
 
-			execbuf.flags = engines[n] | LOCAL_EXEC_FENCE_OUT;
+			execbuf.flags = engines[n] | I915_EXEC_FENCE_OUT;
 			if (__gem_execbuf_wr(fd, &execbuf))
 				continue;
 
@@ -742,7 +730,7 @@ static void test_long_history(int fd, long ring_size, unsigned flags)
 
 	for (s = 0; s < ring_size; s++) {
 		for (n = 0; n < nengine; n++) {
-			execbuf.flags = engines[n] | LOCAL_EXEC_FENCE_IN;
+			execbuf.flags = engines[n] | I915_EXEC_FENCE_IN;
 			if (__gem_execbuf_wr(fd, &execbuf))
 				continue;
 		}
@@ -766,7 +754,7 @@ static bool has_submit_fence(int fd)
 	int value = 0;
 
 	memset(&gp, 0, sizeof(gp));
-	gp.param = 0xdeadbeef ^ 51; /* I915_PARAM_HAS_EXEC_SUBMIT_FENCE */
+	gp.param = 0xdeadbeef ^ I915_PARAM_HAS_EXEC_SUBMIT_FENCE;
 	gp.value = &value;
 
 	ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp));
@@ -777,7 +765,7 @@ static bool has_submit_fence(int fd)
 
 static bool has_syncobj(int fd)
 {
-	struct drm_get_cap cap = { .capability = 0x13 };
+	struct drm_get_cap cap = { .capability = DRM_CAP_SYNCOBJ };
 	ioctl(fd, DRM_IOCTL_GET_CAP, &cap);
 	return cap.value;
 }
@@ -788,7 +776,7 @@ static bool exec_has_fence_array(int fd)
 	int value = 0;
 
 	memset(&gp, 0, sizeof(gp));
-	gp.param = 49; /* I915_PARAM_HAS_EXEC_FENCE_ARRAY */
+	gp.param = I915_PARAM_HAS_EXEC_FENCE_ARRAY;
 	gp.value = &value;
 
 	ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp));
@@ -802,7 +790,7 @@ static void test_invalid_fence_array(int fd)
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_object2 obj;
-	struct local_gem_exec_fence fence;
+	struct drm_i915_gem_exec_fence fence;
 	void *ptr;
 
 	/* create an otherwise valid execbuf */
@@ -814,7 +802,7 @@ static void test_invalid_fence_array(int fd)
 	execbuf.buffer_count = 1;
 	gem_execbuf(fd, &execbuf);
 
-	execbuf.flags |= LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags |= I915_EXEC_FENCE_ARRAY;
 	gem_execbuf(fd, &execbuf);
 
 	/* Now add a few invalid fence-array pointers */
@@ -1026,7 +1014,7 @@ static void test_syncobj_unused_fence(int fd)
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
-	struct local_gem_exec_fence fence = {
+	struct drm_i915_gem_exec_fence fence = {
 		.handle = syncobj_create(fd),
 	};
 	igt_spin_t *spin = igt_spin_new(fd);
@@ -1037,7 +1025,7 @@ static void test_syncobj_unused_fence(int fd)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY;
 	execbuf.cliprects_ptr = to_user_pointer(&fence);
 	execbuf.num_cliprects = 1;
 
@@ -1062,14 +1050,14 @@ static void test_syncobj_invalid_wait(int fd)
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
-	struct local_gem_exec_fence fence = {
+	struct drm_i915_gem_exec_fence fence = {
 		.handle = syncobj_create(fd),
 	};
 
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY;
 	execbuf.cliprects_ptr = to_user_pointer(&fence);
 	execbuf.num_cliprects = 1;
 
@@ -1078,7 +1066,7 @@ static void test_syncobj_invalid_wait(int fd)
 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
 
 	/* waiting before the fence is set is invalid */
-	fence.flags = LOCAL_EXEC_FENCE_WAIT;
+	fence.flags = I915_EXEC_FENCE_WAIT;
 	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
 
 	gem_close(fd, obj.handle);
@@ -1090,14 +1078,14 @@ static void test_syncobj_invalid_flags(int fd)
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
-	struct local_gem_exec_fence fence = {
+	struct drm_i915_gem_exec_fence fence = {
 		.handle = syncobj_create(fd),
 	};
 
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY;
 	execbuf.cliprects_ptr = to_user_pointer(&fence);
 	execbuf.num_cliprects = 1;
 
@@ -1118,7 +1106,7 @@ static void test_syncobj_signal(int fd)
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
-	struct local_gem_exec_fence fence = {
+	struct drm_i915_gem_exec_fence fence = {
 		.handle = syncobj_create(fd),
 	};
 	igt_spin_t *spin = igt_spin_new(fd);
@@ -1128,7 +1116,7 @@ static void test_syncobj_signal(int fd)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY;
 	execbuf.cliprects_ptr = to_user_pointer(&fence);
 	execbuf.num_cliprects = 1;
 
@@ -1136,7 +1124,7 @@ static void test_syncobj_signal(int fd)
 	obj.handle = gem_create(fd, 4096);
 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
 
-	fence.flags = LOCAL_EXEC_FENCE_SIGNAL;
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
 	gem_execbuf(fd, &execbuf);
 
 	igt_assert(gem_bo_busy(fd, obj.handle));
@@ -1157,7 +1145,7 @@ static void test_syncobj_wait(int fd)
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
-	struct local_gem_exec_fence fence = {
+	struct drm_i915_gem_exec_fence fence = {
 		.handle = syncobj_create(fd),
 	};
 	igt_spin_t *spin;
@@ -1181,10 +1169,10 @@ static void test_syncobj_wait(int fd)
 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
 
 	/* Queue a signaler from the blocked engine */
-	execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY;
 	execbuf.cliprects_ptr = to_user_pointer(&fence);
 	execbuf.num_cliprects = 1;
-	fence.flags = LOCAL_EXEC_FENCE_SIGNAL;
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
 	gem_execbuf(fd, &execbuf);
 	igt_assert(gem_bo_busy(fd, spin->handle));
 
@@ -1209,10 +1197,10 @@ static void test_syncobj_wait(int fd)
 		igt_assert(gem_bo_busy(fd, spin->handle));
 
 		/* Now wait upon the blocked engine */
-		execbuf.flags = LOCAL_EXEC_FENCE_ARRAY | eb_ring(e);
+		execbuf.flags = I915_EXEC_FENCE_ARRAY | eb_ring(e);
 		execbuf.cliprects_ptr = to_user_pointer(&fence);
 		execbuf.num_cliprects = 1;
-		fence.flags = LOCAL_EXEC_FENCE_WAIT;
+		fence.flags = I915_EXEC_FENCE_WAIT;
 		gem_execbuf(fd, &execbuf);
 
 		igt_assert(gem_bo_busy(fd, obj.handle));
@@ -1236,7 +1224,7 @@ static void test_syncobj_export(int fd)
 	const uint32_t bbe = MI_BATCH_BUFFER_END;
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
-	struct local_gem_exec_fence fence = {
+	struct drm_i915_gem_exec_fence fence = {
 		.handle = syncobj_create(fd),
 	};
 	int export[2];
@@ -1253,7 +1241,7 @@ static void test_syncobj_export(int fd)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY;
 	execbuf.cliprects_ptr = to_user_pointer(&fence);
 	execbuf.num_cliprects = 1;
 
@@ -1261,7 +1249,7 @@ static void test_syncobj_export(int fd)
 	obj.handle = gem_create(fd, 4096);
 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
 
-	fence.flags = LOCAL_EXEC_FENCE_SIGNAL;
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
 	gem_execbuf(fd, &execbuf);
 
 	igt_assert(syncobj_busy(fd, fence.handle));
@@ -1296,7 +1284,7 @@ static void test_syncobj_repeat(int fd)
 	const unsigned nfences = 4096;
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
-	struct local_gem_exec_fence *fence;
+	struct drm_i915_gem_exec_fence *fence;
 	int export;
 	igt_spin_t *spin = igt_spin_new(fd);
 
@@ -1311,7 +1299,7 @@ static void test_syncobj_repeat(int fd)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY;
 	execbuf.cliprects_ptr = to_user_pointer(fence);
 	execbuf.num_cliprects = nfences;
 
@@ -1320,13 +1308,13 @@ static void test_syncobj_repeat(int fd)
 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
 
 	for (int i = 0; i < nfences; i++)
-		fence[i].flags = LOCAL_EXEC_FENCE_SIGNAL;
+		fence[i].flags = I915_EXEC_FENCE_SIGNAL;
 
 	gem_execbuf(fd, &execbuf);
 
 	for (int i = 0; i < nfences; i++) {
 		igt_assert(syncobj_busy(fd, fence[i].handle));
-		fence[i].flags |= LOCAL_EXEC_FENCE_WAIT;
+		fence[i].flags |= I915_EXEC_FENCE_WAIT;
 	}
 	igt_assert(gem_bo_busy(fd, obj.handle));
 
@@ -1364,7 +1352,7 @@ static void test_syncobj_import(int fd)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_OUT;
+	execbuf.flags = I915_EXEC_FENCE_OUT;
 	execbuf.rsvd2 = -1;
 
 	memset(&obj, 0, sizeof(obj));
@@ -1409,7 +1397,7 @@ static void test_syncobj_channel(int fd)
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj);
 	execbuf.buffer_count = 1;
-	execbuf.flags = LOCAL_EXEC_FENCE_OUT;
+	execbuf.flags = I915_EXEC_FENCE_OUT;
 	execbuf.rsvd2 = -1;
 
 	memset(&obj, 0, sizeof(obj));
@@ -1417,15 +1405,15 @@ static void test_syncobj_channel(int fd)
 	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
 
 	for (int i = 0; i < ARRAY_SIZE(syncobj); i++) {
-		struct local_gem_exec_fence fence;
+		struct drm_i915_gem_exec_fence fence;
 
-		execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+		execbuf.flags = I915_EXEC_FENCE_ARRAY;
 		execbuf.cliprects_ptr = to_user_pointer(&fence);
 		execbuf.num_cliprects = 1;
 
 		/* Create a primed fence */
 		fence.handle = syncobj_create(fd);
-		fence.flags = LOCAL_EXEC_FENCE_SIGNAL;
+		fence.flags = I915_EXEC_FENCE_SIGNAL;
 
 		gem_execbuf(fd, &execbuf);
 
@@ -1434,21 +1422,21 @@ static void test_syncobj_channel(int fd)
 
 	/* Two processes in ping-pong unison (pipe), one out of sync */
 	igt_fork(child, 1) {
-		struct local_gem_exec_fence fence[3];
+		struct drm_i915_gem_exec_fence fence[3];
 		unsigned long count;
 
-		execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+		execbuf.flags = I915_EXEC_FENCE_ARRAY;
 		execbuf.cliprects_ptr = to_user_pointer(fence);
 		execbuf.num_cliprects = 3;
 
 		fence[0].handle = syncobj[0];
-		fence[0].flags = LOCAL_EXEC_FENCE_SIGNAL;
+		fence[0].flags = I915_EXEC_FENCE_SIGNAL;
 
 		fence[1].handle = syncobj[1];
-		fence[1].flags = LOCAL_EXEC_FENCE_WAIT;
+		fence[1].flags = I915_EXEC_FENCE_WAIT;
 
 		fence[2].handle = syncobj[2];
-		fence[2].flags = LOCAL_EXEC_FENCE_WAIT;
+		fence[2].flags = I915_EXEC_FENCE_WAIT;
 
 		count = 0;
 		while (!*(volatile unsigned *)control) {
@@ -1459,21 +1447,21 @@ static void test_syncobj_channel(int fd)
 		control[1] = count;
 	}
 	igt_fork(child, 1) {
-		struct local_gem_exec_fence fence[3];
+		struct drm_i915_gem_exec_fence fence[3];
 		unsigned long count;
 
-		execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+		execbuf.flags = I915_EXEC_FENCE_ARRAY;
 		execbuf.cliprects_ptr = to_user_pointer(fence);
 		execbuf.num_cliprects = 3;
 
 		fence[0].handle = syncobj[0];
-		fence[0].flags = LOCAL_EXEC_FENCE_WAIT;
+		fence[0].flags = I915_EXEC_FENCE_WAIT;
 
 		fence[1].handle = syncobj[1];
-		fence[1].flags = LOCAL_EXEC_FENCE_SIGNAL;
+		fence[1].flags = I915_EXEC_FENCE_SIGNAL;
 
 		fence[2].handle = syncobj[2];
-		fence[2].flags = LOCAL_EXEC_FENCE_WAIT;
+		fence[2].flags = I915_EXEC_FENCE_WAIT;
 
 		count = 0;
 		while (!*(volatile unsigned *)control) {
@@ -1483,15 +1471,15 @@ static void test_syncobj_channel(int fd)
 		control[2] = count;
 	}
 	igt_fork(child, 1) {
-		struct local_gem_exec_fence fence;
+		struct drm_i915_gem_exec_fence fence;
 		unsigned long count;
 
-		execbuf.flags = LOCAL_EXEC_FENCE_ARRAY;
+		execbuf.flags = I915_EXEC_FENCE_ARRAY;
 		execbuf.cliprects_ptr = to_user_pointer(&fence);
 		execbuf.num_cliprects = 1;
 
 		fence.handle = syncobj[2];
-		fence.flags = LOCAL_EXEC_FENCE_SIGNAL;
+		fence.flags = I915_EXEC_FENCE_SIGNAL;
 
 		count = 0;
 		while (!*(volatile unsigned *)control) {
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 06/10] tests/i915/exec_fence: reuse syncobj helpers
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (4 preceding siblings ...)
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 05/10] tests/i915/exec_fence: switch to internal headers Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 07/10] include: bump drm headers for i915 timeline semaphores Lionel Landwerlin
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

v2: Fix mistake in syncobj_busy() (Lionel)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 tests/i915/gem_exec_fence.c | 182 ++++--------------------------------
 1 file changed, 20 insertions(+), 162 deletions(-)

diff --git a/tests/i915/gem_exec_fence.c b/tests/i915/gem_exec_fence.c
index b8fa1a03..a9e29889 100644
--- a/tests/i915/gem_exec_fence.c
+++ b/tests/i915/gem_exec_fence.c
@@ -22,6 +22,7 @@
  */
 
 #include "igt.h"
+#include "igt_syncobj.h"
 #include "igt_sysfs.h"
 #include "igt_vgem.h"
 #include "sw_sync.h"
@@ -833,168 +834,24 @@ static void test_invalid_fence_array(int fd)
 	munmap(ptr, 4096);
 }
 
-static uint32_t __syncobj_create(int fd)
-{
-	struct local_syncobj_create {
-		uint32_t handle, flags;
-	} arg;
-#define LOCAL_IOCTL_SYNCOBJ_CREATE        DRM_IOWR(0xBF, struct local_syncobj_create)
-
-	memset(&arg, 0, sizeof(arg));
-	igt_ioctl(fd, LOCAL_IOCTL_SYNCOBJ_CREATE, &arg);
-
-	return arg.handle;
-}
-
-static uint32_t syncobj_create(int fd)
-{
-	uint32_t ret;
-
-	igt_assert_neq((ret = __syncobj_create(fd)), 0);
-
-	return ret;
-}
-
-static int __syncobj_destroy(int fd, uint32_t handle)
-{
-	struct local_syncobj_destroy {
-		uint32_t handle, flags;
-	} arg;
-#define LOCAL_IOCTL_SYNCOBJ_DESTROY        DRM_IOWR(0xC0, struct local_syncobj_destroy)
-	int err = 0;
-
-	memset(&arg, 0, sizeof(arg));
-	arg.handle = handle;
-	if (igt_ioctl(fd, LOCAL_IOCTL_SYNCOBJ_DESTROY, &arg))
-		err = -errno;
-
-	errno = 0;
-	return err;
-}
-
-static void syncobj_destroy(int fd, uint32_t handle)
-{
-	igt_assert_eq(__syncobj_destroy(fd, handle), 0);
-}
-
 static int __syncobj_to_sync_file(int fd, uint32_t handle)
 {
-	struct local_syncobj_handle {
-		uint32_t handle;
-		uint32_t flags;
-		int32_t fd;
-		uint32_t pad;
-	} arg;
-#define LOCAL_IOCTL_SYNCOBJ_HANDLE_TO_FD  DRM_IOWR(0xC1, struct local_syncobj_handle)
-
-	memset(&arg, 0, sizeof(arg));
-	arg.handle = handle;
-	arg.flags = 1 << 0; /* EXPORT_SYNC_FILE */
-	if (igt_ioctl(fd, LOCAL_IOCTL_SYNCOBJ_HANDLE_TO_FD, &arg))
-		arg.fd = -errno;
-
-	errno = 0;
-	return arg.fd;
-}
-
-static int syncobj_to_sync_file(int fd, uint32_t handle)
-{
-	int ret;
-
-	igt_assert_lte(0, (ret = __syncobj_to_sync_file(fd, handle)));
-
-	return ret;
-}
-
-static int __syncobj_from_sync_file(int fd, uint32_t handle, int sf)
-{
-	struct local_syncobj_handle {
-		uint32_t handle;
-		uint32_t flags;
-		int32_t fd;
-		uint32_t pad;
-	} arg;
-#define LOCAL_IOCTL_SYNCOBJ_FD_TO_HANDLE  DRM_IOWR(0xC2, struct local_syncobj_handle)
-	int err = 0;
-
-	memset(&arg, 0, sizeof(arg));
-	arg.handle = handle;
-	arg.fd = sf;
-	arg.flags = 1 << 0; /* IMPORT_SYNC_FILE */
-	if (igt_ioctl(fd, LOCAL_IOCTL_SYNCOBJ_FD_TO_HANDLE, &arg))
-		err = -errno;
-
-	errno = 0;
-	return err;
-}
-
-static void syncobj_from_sync_file(int fd, uint32_t handle, int sf)
-{
-	igt_assert_eq(__syncobj_from_sync_file(fd, handle, sf), 0);
-}
-
-static int __syncobj_export(int fd, uint32_t handle, int *syncobj)
-{
-	struct local_syncobj_handle {
-		uint32_t handle;
-		uint32_t flags;
-		int32_t fd;
-		uint32_t pad;
-	} arg;
-	int err;
-
-	memset(&arg, 0, sizeof(arg));
-	arg.handle = handle;
-
-	err = 0;
-	if (igt_ioctl(fd, LOCAL_IOCTL_SYNCOBJ_HANDLE_TO_FD, &arg))
-		err = -errno;
+	struct drm_syncobj_handle arg = {
+		.handle = handle,
+		.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
+	};
 
-	errno = 0;
-	*syncobj = arg.fd;
-	return err;
+	return __syncobj_handle_to_fd(fd, &arg);
 }
 
 static int syncobj_export(int fd, uint32_t handle)
 {
-	int syncobj;
-
-	igt_assert_eq(__syncobj_export(fd, handle, &syncobj), 0);
-
-	return syncobj;
-}
-
-static int __syncobj_import(int fd, int syncobj, uint32_t *handle)
-{
-	struct local_syncobj_handle {
-		uint32_t handle;
-		uint32_t flags;
-		int32_t fd;
-		uint32_t pad;
-	} arg;
-#define LOCAL_IOCTL_SYNCOBJ_FD_TO_HANDLE  DRM_IOWR(0xC2, struct local_syncobj_handle)
-	int err;
-
-	memset(&arg, 0, sizeof(arg));
-	arg.fd = syncobj;
-
-	err = 0;
-	if (igt_ioctl(fd, LOCAL_IOCTL_SYNCOBJ_FD_TO_HANDLE, &arg))
-		err = -errno;
-
-	errno = 0;
-	*handle = arg.handle;
-	return err;
+	return syncobj_handle_to_fd(fd, handle, 0);
 }
 
 static uint32_t syncobj_import(int fd, int syncobj)
 {
-	uint32_t handle;
-
-	igt_assert_eq(__syncobj_import(fd, syncobj, &handle), 0);
-
-
-	return handle;
+	return syncobj_fd_to_handle(fd, syncobj, 0);
 }
 
 static bool syncobj_busy(int fd, uint32_t handle)
@@ -1002,7 +859,8 @@ static bool syncobj_busy(int fd, uint32_t handle)
 	bool result;
 	int sf;
 
-	sf = syncobj_to_sync_file(fd, handle);
+	sf = syncobj_handle_to_fd(fd, handle,
+				  DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE);
 	result = poll(&(struct pollfd){sf, POLLIN}, 1, 0) == 0;
 	close(sf);
 
@@ -1015,7 +873,7 @@ static void test_syncobj_unused_fence(int fd)
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_fence fence = {
-		.handle = syncobj_create(fd),
+		.handle = syncobj_create(fd, 0),
 	};
 	igt_spin_t *spin = igt_spin_new(fd);
 
@@ -1051,7 +909,7 @@ static void test_syncobj_invalid_wait(int fd)
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_fence fence = {
-		.handle = syncobj_create(fd),
+		.handle = syncobj_create(fd, 0),
 	};
 
 	memset(&execbuf, 0, sizeof(execbuf));
@@ -1079,7 +937,7 @@ static void test_syncobj_invalid_flags(int fd)
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_fence fence = {
-		.handle = syncobj_create(fd),
+		.handle = syncobj_create(fd, 0),
 	};
 
 	memset(&execbuf, 0, sizeof(execbuf));
@@ -1107,7 +965,7 @@ static void test_syncobj_signal(int fd)
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_fence fence = {
-		.handle = syncobj_create(fd),
+		.handle = syncobj_create(fd, 0),
 	};
 	igt_spin_t *spin = igt_spin_new(fd);
 
@@ -1146,7 +1004,7 @@ static void test_syncobj_wait(int fd)
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_fence fence = {
-		.handle = syncobj_create(fd),
+		.handle = syncobj_create(fd, 0),
 	};
 	igt_spin_t *spin;
 	unsigned handle[16];
@@ -1225,7 +1083,7 @@ static void test_syncobj_export(int fd)
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	struct drm_i915_gem_exec_fence fence = {
-		.handle = syncobj_create(fd),
+		.handle = syncobj_create(fd, 0),
 	};
 	int export[2];
 	igt_spin_t *spin = igt_spin_new(fd);
@@ -1290,7 +1148,7 @@ static void test_syncobj_repeat(int fd)
 
 	/* Check that we can wait on the same fence multiple times */
 	fence = calloc(nfences, sizeof(*fence));
-	fence->handle = syncobj_create(fd);
+	fence->handle = syncobj_create(fd, 0);
 	export = syncobj_export(fd, fence->handle);
 	for (int i = 1; i < nfences; i++)
 		fence[i].handle = syncobj_import(fd, export);
@@ -1342,7 +1200,7 @@ static void test_syncobj_import(int fd)
 	struct drm_i915_gem_exec_object2 obj;
 	struct drm_i915_gem_execbuffer2 execbuf;
 	igt_spin_t *spin = igt_spin_new(fd);
-	uint32_t sync = syncobj_create(fd);
+	uint32_t sync = syncobj_create(fd, 0);
 	int fence;
 
 	/* Check that we can create a syncobj from an explicit fence (which
@@ -1363,7 +1221,7 @@ static void test_syncobj_import(int fd)
 
 	fence = execbuf.rsvd2 >> 32;
 	igt_assert(fence_busy(fence));
-	syncobj_from_sync_file(fd, sync, fence);
+	syncobj_import_sync_file(fd, sync, fence);
 	close(fence);
 
 	igt_assert(gem_bo_busy(fd, obj.handle));
@@ -1412,7 +1270,7 @@ static void test_syncobj_channel(int fd)
 		execbuf.num_cliprects = 1;
 
 		/* Create a primed fence */
-		fence.handle = syncobj_create(fd);
+		fence.handle = syncobj_create(fd, 0);
 		fence.flags = I915_EXEC_FENCE_SIGNAL;
 
 		gem_execbuf(fd, &execbuf);
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 07/10] include: bump drm headers for i915 timeline semaphores
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (5 preceding siblings ...)
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 06/10] tests/i915/exec_fence: reuse syncobj helpers Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests Lionel Landwerlin
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

Commit to be update with proper drm-next reference once merged.
---
 include/drm-uapi/drm.h      | 17 ++++++++++
 include/drm-uapi/i915_drm.h | 64 +++++++++++++++++++++++++++++++++++--
 2 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/include/drm-uapi/drm.h b/include/drm-uapi/drm.h
index ab940339..5a2f7f7e 100644
--- a/include/drm-uapi/drm.h
+++ b/include/drm-uapi/drm.h
@@ -780,6 +780,22 @@ struct drm_syncobj_timeline_array {
 	__u32 flags;
 };
 
+struct drm_syncobj_binary_array {
+	/* A pointer to an array of u32 syncobj handles. */
+	__u64 handles;
+	/* A pointer to an array of u32 access flags for each handle. */
+	__u64 access_flags;
+	/* The binary value of a syncobj is read before it is incremented. */
+#define DRM_SYNCOBJ_BINARY_VALUE_READ (1u << 0)
+#define DRM_SYNCOBJ_BINARY_VALUE_INC  (1u << 1)
+	/* A pointer to an array of u64 values written to by the kernel if the
+	 * handle is flagged for reading.
+	 */
+	__u64 values;
+	/* The length of the 3 arrays above. */
+	__u32 count_handles;
+	__u32 pad;
+};
 
 /* Query current scanout sequence number */
 struct drm_crtc_get_sequence {
@@ -941,6 +957,7 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_QUERY		DRM_IOWR(0xCB, struct drm_syncobj_timeline_array)
 #define DRM_IOCTL_SYNCOBJ_TRANSFER	DRM_IOWR(0xCC, struct drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL	DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
+#define DRM_IOCTL_SYNCOBJ_BINARY	DRM_IOWR(0xCE, struct drm_syncobj_binary_array)
 
 /**
  * Device specific ioctls should only be in their respective headers
diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
index ab899abb..4ac9d735 100644
--- a/include/drm-uapi/i915_drm.h
+++ b/include/drm-uapi/i915_drm.h
@@ -618,6 +618,12 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_PERF_REVISION	54
 
+/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
+ * timeline syncobj through drm_i915_gem_execbuf_ext_timeline_fences. See
+ * I915_EXEC_USE_EXTENSIONS.
+ */
+#define I915_PARAM_HAS_EXEC_TIMELINE_FENCES 55
+
 /* Must be kept compact -- no holes and well documented */
 
 typedef struct drm_i915_getparam {
@@ -1014,6 +1020,42 @@ struct drm_i915_gem_exec_fence {
 	__u32 flags;
 };
 
+enum drm_i915_gem_execbuffer_ext {
+	/**
+	 * See drm_i915_gem_execbuf_ext_timeline_fences.
+	 */
+	DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES = 1,
+
+	DRM_I915_GEM_EXECBUFFER_EXT_MAX /* non-ABI */
+};
+
+/**
+ * This structure describes an array of drm_syncobj and associated points for
+ * timeline variants of drm_syncobj. It is invalid to append this structure to
+ * the execbuf if I915_EXEC_FENCE_ARRAY is set.
+ */
+struct drm_i915_gem_execbuffer_ext_timeline_fences {
+	struct i915_user_extension base;
+
+	/**
+	 * Number of element in the handles_ptr & value_ptr arrays.
+	 */
+	__u64 fence_count;
+
+	/**
+	 * Pointer to an array of struct drm_i915_gem_exec_fence of length
+	 * fence_count.
+	 */
+	__u64 handles_ptr;
+
+	/**
+	 * Pointer to an array of u64 values of length fence_count. Values
+	 * must be 0 for a binary drm_syncobj. A Value of 0 for a timeline
+	 * drm_syncobj is invalid as it turns a drm_syncobj into a binary one.
+	 */
+	__u64 values_ptr;
+};
+
 struct drm_i915_gem_execbuffer2 {
 	/**
 	 * List of gem_exec_object2 structs
@@ -1030,8 +1072,15 @@ struct drm_i915_gem_execbuffer2 {
 	__u32 num_cliprects;
 	/**
 	 * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
-	 * is not set.  If I915_EXEC_FENCE_ARRAY is set, then this is a
-	 * struct drm_i915_gem_exec_fence *fences.
+	 * & I915_EXEC_USE_EXTENSIONS are not set.
+	 *
+	 * If I915_EXEC_FENCE_ARRAY is set, then this is a pointer to an array
+	 * of struct drm_i915_gem_exec_fence and num_cliprects is the length
+	 * of the array.
+	 *
+	 * If I915_EXEC_USE_EXTENSIONS is set, then this is a pointer to a
+	 * single struct drm_i915_gem_base_execbuffer_ext and num_cliprects is
+	 * 0.
 	 */
 	__u64 cliprects_ptr;
 #define I915_EXEC_RING_MASK              (0x3f)
@@ -1149,7 +1198,16 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_FENCE_SUBMIT		(1 << 20)
 
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
+/*
+ * Setting I915_EXEC_USE_EXTENSIONS implies that
+ * drm_i915_gem_execbuffer2.cliprects_ptr is treated as a pointer to an linked
+ * list of i915_user_extension. Each i915_user_extension node is the base of a
+ * larger structure. The list of supported structures are listed in the
+ * drm_i915_gem_execbuffer_ext enum.
+ */
+#define I915_EXEC_USE_EXTENSIONS	(1 << 21)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_USE_EXTENSIONS<<1))
 
 #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (6 preceding siblings ...)
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 07/10] include: bump drm headers for i915 timeline semaphores Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 15:13   ` Chris Wilson
  2019-11-22 15:26   ` Chris Wilson
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 09/10] lib/i915: Parse mmio base from debugfs Lionel Landwerlin
                   ` (4 subsequent siblings)
  12 siblings, 2 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

We can now give a tuple (handle, point_value) for timeline semaphores.

v2: Fix up syncobj-timeline-repeat test (Lionel)
    Update following kernel rename

v3: Add more ordering tests for syncobj/buffer handle state (Chris)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 tests/i915/gem_exec_fence.c | 678 ++++++++++++++++++++++++++++++++++++
 1 file changed, 678 insertions(+)

diff --git a/tests/i915/gem_exec_fence.c b/tests/i915/gem_exec_fence.c
index a9e29889..b27337ff 100644
--- a/tests/i915/gem_exec_fence.c
+++ b/tests/i915/gem_exec_fence.c
@@ -1362,6 +1362,640 @@ static void test_syncobj_channel(int fd)
 		syncobj_destroy(fd, syncobj[i]);
 }
 
+static bool has_syncobj_timeline(int fd)
+{
+	struct drm_get_cap cap = { .capability = DRM_CAP_SYNCOBJ_TIMELINE };
+	ioctl(fd, DRM_IOCTL_GET_CAP, &cap);
+	return cap.value;
+}
+
+static bool exec_has_timeline_fences(int fd)
+{
+	struct drm_i915_getparam gp;
+	int value = 0;
+
+	memset(&gp, 0, sizeof(gp));
+	gp.param = I915_PARAM_HAS_EXEC_TIMELINE_FENCES;
+	gp.value = &value;
+
+	ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp, sizeof(gp));
+	errno = 0;
+
+	return value;
+}
+
+static const char *test_invalid_timeline_fence_array_desc =
+	"Verifies invalid execbuf parameters in"
+	" drm_i915_gem_execbuffer_ext_timeline_fences are rejected";
+static void test_invalid_timeline_fence_array(int fd)
+{
+	const uint32_t bbe = MI_BATCH_BUFFER_END;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence fence;
+	uint64_t value;
+	void *ptr;
+
+	/* create an otherwise valid execbuf */
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	gem_execbuf(fd, &execbuf);
+
+	/* Invalid num_cliprects value */
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 1;
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
+
+	fence.handle = syncobj_create(fd, 0);
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
+	value = 1;
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+
+	/* Invalid fence array & i915 ext */
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+	execbuf.flags = I915_EXEC_FENCE_ARRAY | I915_EXEC_USE_EXTENSIONS;
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
+
+	syncobj_create(fd, fence.handle);
+
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+
+	/* Invalid handles_ptr */
+	value = 1;
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = -1;
+	timeline_fences.values_ptr = to_user_pointer(&value);
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EFAULT);
+
+	/* Invalid values_ptr */
+	value = 1;
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = -1;
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EFAULT);
+
+	/* Invalid syncobj handle */
+	memset(&fence, 0, sizeof(fence));
+	fence.handle = 0;
+	fence.flags = I915_EXEC_FENCE_WAIT;
+	value = 1;
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOENT);
+
+	/* Invalid syncobj timeline point */
+	memset(&fence, 0, sizeof(fence));
+	fence.handle = syncobj_create(fd, 0);
+	fence.flags = I915_EXEC_FENCE_WAIT;
+	value = 1;
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
+	syncobj_destroy(fd, fence.handle);
+
+	/* Invalid handles_ptr */
+	ptr = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(ptr != MAP_FAILED);
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(ptr);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOENT);
+
+	do_or_die(mprotect(ptr, 4096, PROT_READ));
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOENT);
+
+	do_or_die(mprotect(ptr, 4096, PROT_NONE));
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EFAULT);
+
+	munmap(ptr, 4096);
+
+	/* Invalid values_ptr */
+	ptr = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
+	igt_assert(ptr != MAP_FAILED);
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(ptr);
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOENT);
+
+	do_or_die(mprotect(ptr, 4096, PROT_READ));
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -ENOENT);
+
+	do_or_die(mprotect(ptr, 4096, PROT_NONE));
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EFAULT);
+
+	munmap(ptr, 4096);
+}
+
+static const char *test_syncobj_timeline_unused_fence_desc =
+	"Verifies that a timeline syncobj passed into"
+	" drm_i915_gem_execbuffer_ext_timeline_fences but with no signal/wait"
+	" flag is left untouched";
+static void test_syncobj_timeline_unused_fence(int fd)
+{
+	const uint32_t bbe = MI_BATCH_BUFFER_END;
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence fence = {
+		.handle = syncobj_create(fd, 0),
+	};
+	igt_spin_t *spin = igt_spin_new(fd);
+	uint64_t value = 1;
+
+	/* sanity check our syncobj_to_sync_file interface */
+	igt_assert_eq(__syncobj_to_sync_file(fd, 0), -ENOENT);
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
+
+	gem_execbuf(fd, &execbuf);
+
+	/* no flags, the fence isn't created */
+	igt_assert_eq(__syncobj_to_sync_file(fd, fence.handle), -EINVAL);
+	igt_assert(gem_bo_busy(fd, obj.handle));
+
+	gem_close(fd, obj.handle);
+	syncobj_destroy(fd, fence.handle);
+
+	igt_spin_free(fd, spin);
+}
+
+static const char *test_syncobj_timeline_invalid_wait_desc =
+	"Verifies that submitting an execbuf with a wait on a timeline syncobj"
+	" point that does not exists is rejected";
+static void test_syncobj_timeline_invalid_wait(int fd)
+{
+	const uint32_t bbe = MI_BATCH_BUFFER_END;
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence fence = {
+		.handle = syncobj_create(fd, 0),
+	};
+	uint64_t value = 1;
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
+
+	/* waiting before the fence point 1 is set is invalid */
+	fence.flags = I915_EXEC_FENCE_WAIT;
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
+
+	/* Now set point 1. */
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
+	gem_execbuf(fd, &execbuf);
+
+	/* waiting before the fence point 2 is set is invalid */
+	value = 2;
+	fence.flags = I915_EXEC_FENCE_WAIT;
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
+
+	gem_close(fd, obj.handle);
+	syncobj_destroy(fd, fence.handle);
+}
+
+static const char *test_syncobj_timeline_invalid_flags_desc =
+	"Verifies that invalid fence flags in"
+	" drm_i915_gem_execbuffer_ext_timeline_fences are rejected";
+static void test_syncobj_timeline_invalid_flags(int fd)
+{
+	const uint32_t bbe = MI_BATCH_BUFFER_END;
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence fence = {
+		.handle = syncobj_create(fd, 0),
+	};
+	uint64_t value = 1;
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
+
+	/* set all flags to hit an invalid one */
+	fence.flags = ~0;
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
+
+	gem_close(fd, obj.handle);
+	syncobj_destroy(fd, fence.handle);
+}
+
+static const char *test_syncobj_timeline_signal_desc =
+	"Verifies proper signaling of a timeline syncobj through execbuf";
+static void test_syncobj_timeline_signal(int fd)
+{
+	const uint32_t bbe = MI_BATCH_BUFFER_END;
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence fence = {
+		.handle = syncobj_create(fd, 0),
+	};
+	uint64_t value = 42, query_value;
+	igt_spin_t *spin;
+
+	/* Check that the syncobj is signaled only when our request/fence is */
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, &bbe, sizeof(bbe));
+
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
+
+	/* Check syncobj after waiting on the buffer handle. */
+	spin = igt_spin_new(fd);
+	gem_execbuf(fd, &execbuf);
+
+	igt_assert(gem_bo_busy(fd, obj.handle));
+	igt_assert(syncobj_busy(fd, fence.handle));
+	igt_assert(syncobj_timeline_wait(fd, &fence.handle, &value, 1, 0,
+					 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, NULL));
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &fence.handle, &value,
+						1, 0, 0), -ETIME);
+
+	igt_spin_free(fd, spin);
+
+	gem_sync(fd, obj.handle);
+	igt_assert(!syncobj_busy(fd, fence.handle));
+	igt_assert(!gem_bo_busy(fd, obj.handle));
+
+	syncobj_timeline_query(fd, &fence.handle, &query_value, 1);
+	igt_assert_eq(query_value, value);
+
+	spin = igt_spin_new(fd);
+
+	/*
+	 * Wait on the syncobj and verify the state of the buffer
+	 * handle.
+	 */
+	value = 84;
+	gem_execbuf(fd, &execbuf);
+
+	igt_assert(gem_bo_busy(fd, obj.handle));
+	igt_assert(gem_bo_busy(fd, obj.handle));
+	igt_assert(syncobj_busy(fd, fence.handle));
+	igt_assert(syncobj_timeline_wait(fd, &fence.handle, &value, 1, 0,
+					 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE, NULL));
+	igt_assert_eq(syncobj_timeline_wait_err(fd, &fence.handle, &value,
+						1, 0, 0), -ETIME);
+
+	igt_spin_free(fd, spin);
+
+	igt_assert(syncobj_timeline_wait(fd, &fence.handle, &value, 1, NSEC_PER_SEC,
+					 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, NULL));
+
+	igt_assert(!gem_bo_busy(fd, obj.handle));
+	igt_assert(!syncobj_busy(fd, fence.handle));
+
+	syncobj_timeline_query(fd, &fence.handle, &query_value, 1);
+	igt_assert_eq(query_value, value);
+
+	gem_close(fd, obj.handle);
+	syncobj_destroy(fd, fence.handle);
+}
+
+static const char *test_syncobj_timeline_wait_desc =
+	"Verifies that waiting on a timeline syncobj point between engines"
+	" works";
+static void test_syncobj_timeline_wait(int fd)
+{
+	const uint32_t bbe[2] = {
+		MI_BATCH_BUFFER_END,
+		MI_NOOP,
+	};
+	uint32_t gem_context = gem_context_create(fd);
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence fence = {
+		.handle = syncobj_create(fd, 0),
+	};
+	uint64_t value = 1;
+	igt_spin_t *spin;
+	unsigned handle[16];
+	int n;
+
+	/* Check that we can use the syncobj to asynchronous wait prior to
+	 * execution.
+	 */
+
+	gem_quiescent_gpu(fd);
+
+	spin = igt_spin_new(fd);
+
+	gem_context_set_all_engines(fd, gem_context);
+
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	execbuf.batch_len = sizeof(bbe);
+	execbuf.rsvd1 = gem_context;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, bbe, sizeof(bbe));
+
+	/* Queue a signaler from the blocked engine */
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
+	gem_execbuf(fd, &execbuf);
+	igt_assert(gem_bo_busy(fd, spin->handle));
+
+	gem_close(fd, obj.handle);
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, bbe, sizeof(bbe));
+
+	n = 0;
+	for_each_engine(engine, fd) {
+		obj.handle = gem_create(fd, 4096);
+		gem_write(fd, obj.handle, 0, bbe, sizeof(bbe));
+
+		/* No inter-engine synchronisation, will complete */
+		if (engine->flags == I915_EXEC_BLT) {
+			execbuf.flags = engine->flags;
+			execbuf.cliprects_ptr = 0;
+			execbuf.num_cliprects = 0;
+			gem_execbuf(fd, &execbuf);
+			gem_sync(fd, obj.handle);
+			igt_assert(gem_bo_busy(fd, spin->handle));
+		}
+		igt_assert(gem_bo_busy(fd, spin->handle));
+
+		/* Now wait upon the blocked engine */
+		execbuf.flags = I915_EXEC_USE_EXTENSIONS | engine->flags;
+		execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+		execbuf.num_cliprects = 0;
+		fence.flags = I915_EXEC_FENCE_WAIT;
+		gem_execbuf(fd, &execbuf);
+
+		igt_assert(gem_bo_busy(fd, obj.handle));
+		handle[n++] = obj.handle;
+	}
+	syncobj_destroy(fd, fence.handle);
+
+	for (int i = 0; i < n; i++)
+		igt_assert(gem_bo_busy(fd, handle[i]));
+
+	igt_spin_free(fd, spin);
+
+	for (int i = 0; i < n; i++) {
+		gem_sync(fd, handle[i]);
+		gem_close(fd, handle[i]);
+	}
+
+	gem_context_destroy(fd, gem_context);
+}
+
+static const char *test_syncobj_timeline_export_desc =
+	"Verify exporting of timeline syncobj signaled by i915";
+static void test_syncobj_timeline_export(int fd)
+{
+	const uint32_t bbe[2] = {
+		MI_BATCH_BUFFER_END,
+		MI_NOOP,
+	};
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence fence = {
+		.handle = syncobj_create(fd, 0),
+	};
+	uint64_t value = 1;
+	int export[2];
+	igt_spin_t *spin = igt_spin_new(fd);
+
+	/* Check that if we export the syncobj prior to use it picks up
+	 * the later fence. This allows a syncobj to establish a channel
+	 * between clients that may be updated to a later fence by either
+	 * end.
+	 */
+	for (int n = 0; n < ARRAY_SIZE(export); n++)
+		export[n] = syncobj_export(fd, fence.handle);
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(&fence);
+	timeline_fences.values_ptr = to_user_pointer(&value);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, bbe, sizeof(bbe));
+
+	fence.flags = I915_EXEC_FENCE_SIGNAL;
+	gem_execbuf(fd, &execbuf);
+
+	igt_assert(syncobj_busy(fd, fence.handle));
+	igt_assert(gem_bo_busy(fd, obj.handle));
+
+	for (int n = 0; n < ARRAY_SIZE(export); n++) {
+		uint32_t import = syncobj_import(fd, export[n]);
+		igt_assert(syncobj_busy(fd, import));
+		syncobj_destroy(fd, import);
+	}
+
+	igt_spin_free(fd, spin);
+
+	gem_sync(fd, obj.handle);
+	igt_assert(!gem_bo_busy(fd, obj.handle));
+	igt_assert(!syncobj_busy(fd, fence.handle));
+
+	gem_close(fd, obj.handle);
+	syncobj_destroy(fd, fence.handle);
+
+	for (int n = 0; n < ARRAY_SIZE(export); n++) {
+		uint32_t import = syncobj_import(fd, export[n]);
+		igt_assert(!syncobj_busy(fd, import));
+		syncobj_destroy(fd, import);
+		close(export[n]);
+	}
+}
+
+static const char *test_syncobj_timeline_repeat_desc =
+	"Verifies that waiting & signaling a same timeline syncobj point within"
+	" the same execbuf fworks";
+static void test_syncobj_timeline_repeat(int fd)
+{
+	const uint32_t bbe[2] = {
+		MI_BATCH_BUFFER_END,
+		MI_NOOP,
+	};
+	const unsigned nfences = 4096;
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences;
+	struct drm_i915_gem_exec_fence *fence;
+	uint64_t *values;
+	int export;
+	igt_spin_t *spin = igt_spin_new(fd);
+
+	/* Check that we can wait on the same fence multiple times */
+	fence = calloc(nfences, sizeof(*fence));
+	values = calloc(nfences, sizeof(*values));
+	fence->handle = syncobj_create(fd, 0);
+	values[0] = 1;
+	export = syncobj_export(fd, fence->handle);
+	for (int i = 1; i < nfences; i++) {
+		fence[i].handle = syncobj_import(fd, export);
+		values[i] = i + 1;
+	}
+	close(export);
+
+	memset(&timeline_fences, 0, sizeof(timeline_fences));
+	timeline_fences.base.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES;
+	timeline_fences.fence_count = 1;
+	timeline_fences.handles_ptr = to_user_pointer(fence);
+	timeline_fences.values_ptr = to_user_pointer(values);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(&obj);
+	execbuf.buffer_count = 1;
+	execbuf.flags = I915_EXEC_USE_EXTENSIONS;
+	execbuf.cliprects_ptr = to_user_pointer(&timeline_fences);
+	execbuf.num_cliprects = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.handle = gem_create(fd, 4096);
+	gem_write(fd, obj.handle, 0, bbe, sizeof(bbe));
+
+	for (int i = 0; i < nfences; i++)
+		fence[i].flags = I915_EXEC_FENCE_SIGNAL;
+
+	gem_execbuf(fd, &execbuf);
+
+	for (int i = 0; i < nfences; i++) {
+		igt_assert(syncobj_busy(fd, fence[i].handle));
+		/*
+		 * Timeline syncobj cannot resignal the same point
+		 * again.
+		 */
+		fence[i].flags |= I915_EXEC_FENCE_WAIT;
+	}
+	igt_assert(gem_bo_busy(fd, obj.handle));
+
+	igt_assert_eq(__gem_execbuf(fd, &execbuf), -EINVAL);
+
+	for (int i = 0; i < nfences; i++) {
+		igt_assert(syncobj_busy(fd, fence[i].handle));
+		fence[i].flags = I915_EXEC_FENCE_WAIT;
+	}
+	igt_assert(gem_bo_busy(fd, obj.handle));
+
+	gem_execbuf(fd, &execbuf);
+
+	for (int i = 0; i < nfences; i++)
+		igt_assert(syncobj_busy(fd, fence[i].handle));
+	igt_assert(gem_bo_busy(fd, obj.handle));
+
+	igt_spin_free(fd, spin);
+
+	gem_sync(fd, obj.handle);
+	gem_close(fd, obj.handle);
+
+	for (int i = 0; i < nfences; i++) {
+		igt_assert(!syncobj_busy(fd, fence[i].handle));
+		syncobj_destroy(fd, fence[i].handle);
+	}
+	free(fence);
+	free(values);
+}
+
 igt_main
 {
 	const struct intel_execution_engine *e;
@@ -1536,6 +2170,50 @@ igt_main
 		}
 	}
 
+	igt_subtest_group { /* syncobj timeline */
+		igt_fixture {
+			igt_require(exec_has_timeline_fences(i915));
+			igt_assert(has_syncobj_timeline(i915));
+			igt_fork_hang_detector(i915);
+		}
+
+		igt_describe(test_invalid_timeline_fence_array_desc);
+		igt_subtest("invalid-timeline-fence-array")
+			test_invalid_timeline_fence_array(i915);
+
+		igt_describe(test_syncobj_timeline_unused_fence_desc);
+		igt_subtest("syncobj-timeline-unused-fence")
+			test_syncobj_timeline_unused_fence(i915);
+
+		igt_describe(test_syncobj_timeline_invalid_wait_desc);
+		igt_subtest("syncobj-timeline-invalid-wait")
+			test_syncobj_timeline_invalid_wait(i915);
+
+		igt_describe(test_syncobj_timeline_invalid_flags_desc);
+		igt_subtest("syncobj-timeline-invalid-flags")
+			test_syncobj_timeline_invalid_flags(i915);
+
+		igt_describe(test_syncobj_timeline_signal_desc);
+		igt_subtest("syncobj-timeline-signal")
+			test_syncobj_timeline_signal(i915);
+
+		igt_describe(test_syncobj_timeline_wait_desc);
+		igt_subtest("syncobj-timeline-wait")
+			test_syncobj_timeline_wait(i915);
+
+		igt_describe(test_syncobj_timeline_export_desc);
+		igt_subtest("syncobj-timeline-export")
+			test_syncobj_timeline_export(i915);
+
+		igt_describe(test_syncobj_timeline_repeat_desc);
+		igt_subtest("syncobj-timeline-repeat")
+			test_syncobj_timeline_repeat(i915);
+
+		igt_fixture {
+			igt_stop_hang_detector();
+		}
+	}
+
 	igt_fixture {
 		close(i915);
 	}
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 09/10] lib/i915: Parse mmio base from debugfs
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (7 preceding siblings ...)
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests Lionel Landwerlin
@ 2019-11-22 13:02 ` Lionel Landwerlin
  2019-11-22 13:03 ` [igt-dev] [PATCH i-g-t v2 10/10] tests/i915/gem_exec_fence: add engine chaining tests Lionel Landwerlin
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:02 UTC (permalink / raw)
  To: igt-dev

Useful on gen8/9 when you need the mmio of a register on a particular
engine.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/i915/gem_engine_topology.c | 62 ++++++++++++++++++++++++++++++++++
 lib/i915/gem_engine_topology.h |  5 +++
 tests/i915/gem_ctx_shared.c    | 38 ++++++---------------
 tests/i915/gem_exec_latency.c  | 17 ++++++----
 4 files changed, 89 insertions(+), 33 deletions(-)

diff --git a/lib/i915/gem_engine_topology.c b/lib/i915/gem_engine_topology.c
index 790d455f..d2920bb5 100644
--- a/lib/i915/gem_engine_topology.c
+++ b/lib/i915/gem_engine_topology.c
@@ -21,7 +21,12 @@
  * IN THE SOFTWARE.
  */
 
+#include <fcntl.h>
+#include <unistd.h>
+
 #include "drmtest.h"
+#include "igt_sysfs.h"
+#include "intel_chipset.h"
 #include "ioctl_wrappers.h"
 
 #include "i915/gem_engine_topology.h"
@@ -337,3 +342,60 @@ bool gem_engine_is_equal(const struct intel_execution_engine2 *e1,
 {
 	return e1->class == e2->class && e1->instance == e2->instance;
 }
+
+static bool is_engine_name_line(const char *line)
+{
+	static const char *engine_prefixes[] = {
+		"rcs",
+		"bcs",
+		"vcs",
+		"vecs",
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(engine_prefixes); i++) {
+		if (!strncmp(engine_prefixes[i], line, strlen(engine_prefixes[i])))
+			return true;
+	}
+
+	return false;
+}
+
+uint32_t gem_engine_mmio_base(int i915, const char *engine)
+{
+	int fd = igt_debugfs_open(i915, "i915_engine_info", O_RDONLY);
+	FILE *f;
+	char *line = NULL;
+	size_t len = 0;
+	bool in_engine_desc = false;
+	uint32_t mmio_base = 0;
+
+	if (fd < 0)
+		return mmio_base;
+
+	f = fdopen(fd, "r");
+	if (!f) {
+		close(fd);
+		return mmio_base;
+	}
+
+	while (getline(&line, &len, f) >= 0) {
+
+		if (is_engine_name_line(line)) {
+			if (!strncmp(line, engine, strlen(engine)))
+				in_engine_desc = true;
+			else
+				in_engine_desc = false;
+		}
+
+		if (in_engine_desc) {
+			if (sscanf(line, "\tMMIO base:\t0x%x", &mmio_base))
+				break;
+		}
+	}
+
+	free(line);
+	fclose(f);
+
+	return mmio_base;
+}
diff --git a/lib/i915/gem_engine_topology.h b/lib/i915/gem_engine_topology.h
index d98773e0..e728ebd9 100644
--- a/lib/i915/gem_engine_topology.h
+++ b/lib/i915/gem_engine_topology.h
@@ -74,4 +74,9 @@ struct intel_execution_engine2 gem_eb_flags_to_engine(unsigned int flags);
 	     ((e__) = intel_get_current_physical_engine(&i__)); \
 	     intel_next_engine(&i__))
 
+__attribute__((format(scanf, 4, 5)))
+int gem_engine_property_scanf(int i915, const char *engine, const char *attr,
+			      const char *fmt, ...);
+uint32_t gem_engine_mmio_base(int i915, const char *engine);
+
 #endif /* GEM_ENGINE_TOPOLOGY_H */
diff --git a/tests/i915/gem_ctx_shared.c b/tests/i915/gem_ctx_shared.c
index a6eee16d..949e1f3d 100644
--- a/tests/i915/gem_ctx_shared.c
+++ b/tests/i915/gem_ctx_shared.c
@@ -38,6 +38,7 @@
 
 #include <drm.h>
 
+#include "i915/gem_engine_topology.h"
 #include "igt_rand.h"
 #include "igt_vgem.h"
 #include "sync_file.h"
@@ -556,6 +557,14 @@ static uint32_t store_timestamp(int i915,
 	return obj.handle;
 }
 
+static uint32_t ring_base(int i915, unsigned ring)
+{
+	if (ring == I915_EXEC_DEFAULT)
+		ring = I915_EXEC_RENDER; /* XXX */
+
+	return gem_engine_mmio_base(i915, gem_eb_flags_to_engine(ring).name);
+}
+
 static void independent(int i915, unsigned ring, unsigned flags)
 {
 	const int TIMESTAMP = 1023;
@@ -563,33 +572,8 @@ static void independent(int i915, unsigned ring, unsigned flags)
 	igt_spin_t *spin[MAX_ELSP_QLEN];
 	unsigned int mmio_base;
 
-	/* XXX i915_query()! */
-	switch (ring) {
-	case I915_EXEC_DEFAULT:
-	case I915_EXEC_RENDER:
-		mmio_base = 0x2000;
-		break;
-#if 0
-	case I915_EXEC_BSD:
-		mmio_base = 0x12000;
-		break;
-#endif
-	case I915_EXEC_BLT:
-		mmio_base = 0x22000;
-		break;
-
-#define GEN11_VECS0_BASE 0x1c8000
-#define GEN11_VECS1_BASE 0x1d8000
-	case I915_EXEC_VEBOX:
-		if (intel_gen(intel_get_drm_devid(i915)) >= 11)
-			mmio_base = GEN11_VECS0_BASE;
-		else
-			mmio_base = 0x1a000;
-		break;
-
-	default:
-		igt_skip("mmio base not known\n");
-	}
+	mmio_base = ring_base(i915, ring);
+	igt_require_f(mmio_base, "mmio base not known\n");
 
 	for (int n = 0; n < ARRAY_SIZE(spin); n++) {
 		const struct igt_spin_factory opts = {
diff --git a/tests/i915/gem_exec_latency.c b/tests/i915/gem_exec_latency.c
index 3d99182a..d2159f31 100644
--- a/tests/i915/gem_exec_latency.c
+++ b/tests/i915/gem_exec_latency.c
@@ -109,7 +109,7 @@ poll_ring(int fd, unsigned ring, const char *name)
 	igt_spin_free(fd, spin[0]);
 }
 
-#define RCS_TIMESTAMP (0x2000 + 0x358)
+#define TIMESTAMP (0x358)
 static void latency_on_ring(int fd,
 			    unsigned ring, const char *name,
 			    unsigned flags)
@@ -119,6 +119,7 @@ static void latency_on_ring(int fd,
 	struct drm_i915_gem_exec_object2 obj[3];
 	struct drm_i915_gem_relocation_entry reloc;
 	struct drm_i915_gem_execbuffer2 execbuf;
+	const uint32_t mmio_base = gem_engine_mmio_base(fd, name);
 	igt_spin_t *spin = NULL;
 	IGT_CORK_HANDLE(c);
 	volatile uint32_t *reg;
@@ -128,7 +129,8 @@ static void latency_on_ring(int fd,
 	double gpu_latency;
 	int i, j;
 
-	reg = (volatile uint32_t *)((volatile char *)igt_global_mmio + RCS_TIMESTAMP);
+	igt_require(mmio_base);
+	reg = (volatile uint32_t *)((volatile char *)igt_global_mmio + mmio_base + TIMESTAMP);
 
 	memset(&execbuf, 0, sizeof(execbuf));
 	execbuf.buffers_ptr = to_user_pointer(&obj[1]);
@@ -176,7 +178,7 @@ static void latency_on_ring(int fd,
 		map[i++] = 0x24 << 23 | 1;
 		if (has_64bit_reloc)
 			map[i-1]++;
-		map[i++] = RCS_TIMESTAMP; /* ring local! */
+		map[i++] = mmio_base + TIMESTAMP;
 		map[i++] = offset;
 		if (has_64bit_reloc)
 			map[i++] = offset >> 32;
@@ -266,11 +268,14 @@ static void latency_from_ring(int fd,
 	struct drm_i915_gem_exec_object2 obj[3];
 	struct drm_i915_gem_relocation_entry reloc;
 	struct drm_i915_gem_execbuffer2 execbuf;
+	const uint32_t mmio_base = gem_engine_mmio_base(fd, name);
 	const unsigned int repeats = ring_size / 2;
 	uint32_t *map, *results;
 	uint32_t ctx[2] = {};
 	int i, j;
 
+	igt_require(mmio_base);
+
 	if (flags & PREEMPT) {
 		ctx[0] = gem_context_create(fd);
 		gem_context_set_priority(fd, ctx[0], -1023);
@@ -351,7 +356,7 @@ static void latency_from_ring(int fd,
 			map[i++] = 0x24 << 23 | 1;
 			if (has_64bit_reloc)
 				map[i-1]++;
-			map[i++] = RCS_TIMESTAMP; /* ring local! */
+			map[i++] = mmio_base + TIMESTAMP;
 			map[i++] = offset;
 			if (has_64bit_reloc)
 				map[i++] = offset >> 32;
@@ -376,7 +381,7 @@ static void latency_from_ring(int fd,
 			map[i++] = 0x24 << 23 | 1;
 			if (has_64bit_reloc)
 				map[i-1]++;
-			map[i++] = RCS_TIMESTAMP; /* ring local! */
+			map[i++] = mmio_base + TIMESTAMP;
 			map[i++] = offset;
 			if (has_64bit_reloc)
 				map[i++] = offset >> 32;
@@ -669,7 +674,7 @@ igt_main
 			ring_size = 1024;
 
 		intel_register_access_init(&mmio_data, intel_get_pci_device(), false, device);
-		rcs_clock = clockrate(device, RCS_TIMESTAMP);
+		rcs_clock = clockrate(device, 0x2000 + TIMESTAMP);
 		igt_info("RCS timestamp clock: %.0fKHz, %.1fns\n",
 			 rcs_clock / 1e3, 1e9 / rcs_clock);
 		rcs_clock = 1e9 / rcs_clock;
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] [PATCH i-g-t v2 10/10] tests/i915/gem_exec_fence: add engine chaining tests
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (8 preceding siblings ...)
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 09/10] lib/i915: Parse mmio base from debugfs Lionel Landwerlin
@ 2019-11-22 13:03 ` Lionel Landwerlin
  2019-11-22 14:10 ` [igt-dev] ✗ GitLab.Pipeline: warning for tests: Add timeline syncobj testing (rev2) Patchwork
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 13:03 UTC (permalink / raw)
  To: igt-dev

Those tests are meant to verify the ordering while messing around with
the timeline points.

v2: Add munmap() (Chris)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 lib/intel_reg.h             |   2 +
 tests/i915/gem_exec_fence.c | 637 ++++++++++++++++++++++++++++++++++++
 2 files changed, 639 insertions(+)

diff --git a/lib/intel_reg.h b/lib/intel_reg.h
index 96236828..f01933c1 100644
--- a/lib/intel_reg.h
+++ b/lib/intel_reg.h
@@ -2594,6 +2594,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* Batch */
 #define MI_BATCH_BUFFER		((0x30 << 23) | 1)
 #define MI_BATCH_BUFFER_START	(0x31 << 23)
+#define MI_BATCH_BUFFER_START_GEN8 ((0x31 << 13) | 1)
+#define   MI_BATCH_PREDICATE       (1 << 15) /* HSW+ on RCS only*/
 #define MI_BATCH_BUFFER_END	(0xA << 23)
 #define MI_COND_BATCH_BUFFER_END	(0x36 << 23)
 #define MI_DO_COMPARE                   (1 << 21)
diff --git a/tests/i915/gem_exec_fence.c b/tests/i915/gem_exec_fence.c
index b27337ff..8b740442 100644
--- a/tests/i915/gem_exec_fence.c
+++ b/tests/i915/gem_exec_fence.c
@@ -1996,6 +1996,619 @@ static void test_syncobj_timeline_repeat(int fd)
 	free(values);
 }
 
+#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
+
+/* #define MI_LOAD_REGISTER_MEM	   (MI_INSTR(0x29, 1) */
+/* #define MI_LOAD_REGISTER_MEM_GEN8  MI_INSTR(0x29, 2) */
+
+#define MI_LOAD_REGISTER_REG       MI_INSTR(0x2A, 1)
+
+#define MI_STORE_REGISTER_MEM      MI_INSTR(0x24, 1)
+#define MI_STORE_REGISTER_MEM_GEN8 MI_INSTR(0x24, 2)
+
+#define MI_MATH(x)                 MI_INSTR(0x1a, (x) - 1)
+#define MI_MATH_INSTR(opcode, op1, op2) ((opcode) << 20 | (op1) << 10 | (op2))
+/* Opcodes for MI_MATH_INSTR */
+#define   MI_MATH_NOOP			MI_MATH_INSTR(0x00,  0x0, 0x0)
+#define   MI_MATH_LOAD(op1, op2)	MI_MATH_INSTR(0x80,  op1, op2)
+#define   MI_MATH_LOADINV(op1, op2)	MI_MATH_INSTR(0x480, op1, op2)
+#define   MI_MATH_ADD			MI_MATH_INSTR(0x100, 0x0, 0x0)
+#define   MI_MATH_SUB			MI_MATH_INSTR(0x101, 0x0, 0x0)
+#define   MI_MATH_AND			MI_MATH_INSTR(0x102, 0x0, 0x0)
+#define   MI_MATH_OR			MI_MATH_INSTR(0x103, 0x0, 0x0)
+#define   MI_MATH_XOR			MI_MATH_INSTR(0x104, 0x0, 0x0)
+#define   MI_MATH_STORE(op1, op2)	MI_MATH_INSTR(0x180, op1, op2)
+#define   MI_MATH_STOREINV(op1, op2)	MI_MATH_INSTR(0x580, op1, op2)
+/* Registers used as operands in MI_MATH_INSTR */
+#define   MI_MATH_REG(x)		(x)
+#define   MI_MATH_REG_SRCA		0x20
+#define   MI_MATH_REG_SRCB		0x21
+#define   MI_MATH_REG_ACCU		0x31
+#define   MI_MATH_REG_ZF		0x32
+#define   MI_MATH_REG_CF		0x33
+
+#define HSW_CS_GPR(n)                   (0x600 + 8*(n))
+#define RING_TIMESTAMP                  (0x358)
+#define MI_PREDICATE_RESULT_1           (0x41c)
+
+struct inter_engine_context {
+	int fd;
+
+	struct {
+		uint32_t context;
+	} iterations[9];
+
+	struct intel_engine_data *engines;
+
+	struct inter_engine_batches {
+		void *increment_bb;
+		uint32_t increment_bb_len;
+		uint32_t increment_bb_handle;
+
+		uint32_t timeline;
+
+		void *read0_ptrs[2];
+		void *read1_ptrs[2];
+		void *write_ptrs[2];
+	} *batches;
+
+	void *wait_bb;
+	uint32_t wait_bb_len;
+	uint32_t wait_bb_handle;
+
+	void *jump_ptr;
+	void *timestamp2_ptr;
+
+	uint32_t wait_context;
+	uint32_t wait_timeline;
+
+	struct drm_i915_gem_exec_object2 engine_counter_object;
+};
+
+static void submit_timeline_execbuf(struct inter_engine_context *context,
+				    struct drm_i915_gem_execbuffer2 *execbuf,
+				    uint32_t run_engine_idx,
+				    uint32_t wait_syncobj,
+				    uint64_t wait_value,
+				    uint32_t signal_syncobj,
+				    uint64_t signal_value)
+{
+	uint64_t values[2] = { 0, };
+	struct drm_i915_gem_exec_fence fences[2] = { 0, };
+	struct drm_i915_gem_execbuffer_ext_timeline_fences fence_list = {
+		.base = {
+			.name = DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES,
+		},
+		.handles_ptr = to_user_pointer(fences),
+		.values_ptr = to_user_pointer(values),
+	};
+
+	if (wait_syncobj) {
+		fences[fence_list.fence_count] = (struct drm_i915_gem_exec_fence) {
+			.handle = wait_syncobj,
+			.flags = I915_EXEC_FENCE_WAIT,
+		};
+		values[fence_list.fence_count] = wait_value;
+		fence_list.fence_count++;
+	}
+
+	if (signal_syncobj) {
+		fences[fence_list.fence_count] = (struct drm_i915_gem_exec_fence) {
+			.handle = signal_syncobj,
+			.flags = I915_EXEC_FENCE_SIGNAL,
+		};
+		values[fence_list.fence_count] = signal_value;
+		fence_list.fence_count++;
+	}
+
+	if (wait_syncobj || signal_syncobj) {
+		execbuf->flags |= I915_EXEC_USE_EXTENSIONS;
+		execbuf->cliprects_ptr = to_user_pointer(&fence_list);
+	}
+
+	execbuf->flags |= context->engines->engines[run_engine_idx].flags;
+
+	gem_execbuf(context->fd, execbuf);
+}
+
+static void build_wait_bb(struct inter_engine_context *context,
+			  uint64_t delay,
+			  uint64_t timestamp_frequency)
+{
+	uint32_t *bb = context->wait_bb = calloc(1, 4096);
+	uint64_t wait_value =
+		0xffffffffffffffff - (delay * timestamp_frequency) / NSEC_PER_SEC;
+
+	igt_debug("wait_value=0x%lx\n", wait_value);
+
+	*bb++ = MI_LOAD_REGISTER_IMM;
+	*bb++ = 0x2000 + HSW_CS_GPR(0);
+	*bb++ = wait_value & 0xffffffff;
+	*bb++ = MI_LOAD_REGISTER_IMM;
+	*bb++ = 0x2000 + HSW_CS_GPR(0) + 4;
+	*bb++ = wait_value >> 32;
+
+	*bb++ = MI_LOAD_REGISTER_REG;
+	*bb++ = 0x2000 + RING_TIMESTAMP;
+	*bb++ = 0x2000 + HSW_CS_GPR(1);
+	*bb++ = MI_LOAD_REGISTER_IMM;
+	*bb++ = 0x2000 + HSW_CS_GPR(1) + 4;
+	*bb++ = 0;
+
+	context->timestamp2_ptr = bb;
+	*bb++ = MI_LOAD_REGISTER_REG;
+	*bb++ = 0x2000 + RING_TIMESTAMP;
+	*bb++ = 0x2000 + HSW_CS_GPR(2);
+	*bb++ = MI_LOAD_REGISTER_IMM;
+	*bb++ = 0x2000 + HSW_CS_GPR(2) + 4;
+	*bb++ = 0;
+
+	*bb++ = MI_MATH(4);
+	*bb++ = MI_MATH_LOAD(MI_MATH_REG_SRCA, MI_MATH_REG(2));
+	*bb++ = MI_MATH_LOAD(MI_MATH_REG_SRCB, MI_MATH_REG(1));
+	*bb++ = MI_MATH_SUB;
+	*bb++ = MI_MATH_STORE(MI_MATH_REG(3), MI_MATH_REG_ACCU);
+
+	*bb++ = MI_MATH(4);
+	*bb++ = MI_MATH_LOAD(MI_MATH_REG_SRCA, MI_MATH_REG(0));
+	*bb++ = MI_MATH_LOAD(MI_MATH_REG_SRCB, MI_MATH_REG(3));
+	*bb++ = MI_MATH_ADD;
+	*bb++ = MI_MATH_STOREINV(MI_MATH_REG(4), MI_MATH_REG_CF);
+
+	*bb++ = MI_LOAD_REGISTER_REG;
+	*bb++ = 0x2000 + HSW_CS_GPR(4);
+	*bb++ = 0x2000 + MI_PREDICATE_RESULT_1;
+
+	*bb++ = MI_BATCH_BUFFER_START | MI_BATCH_PREDICATE | 1;
+	context->jump_ptr = bb;
+	*bb++ = 0;
+	*bb++ = 0;
+
+	*bb++ = MI_BATCH_BUFFER_END;
+
+	context->wait_bb_len = ALIGN((void *) bb - context->wait_bb, 8);
+}
+
+static void wait_engine(struct inter_engine_context *context,
+			uint32_t run_engine_idx,
+			uint32_t signal_syncobj,
+			uint64_t signal_value)
+{
+	struct drm_i915_gem_relocation_entry relocs[1];
+	struct drm_i915_gem_exec_object2 objects[2] = {
+		context->engine_counter_object,
+		{
+			.handle = context->wait_bb_handle,
+			.relocs_ptr = to_user_pointer(&relocs),
+			.relocation_count = ARRAY_SIZE(relocs),
+		},
+	};
+	struct drm_i915_gem_execbuffer2 execbuf = {
+		.buffers_ptr = to_user_pointer(&objects[0]),
+		.buffer_count = 2,
+		.flags = I915_EXEC_HANDLE_LUT,
+		.rsvd1 = context->wait_context,
+		.batch_len = context->wait_bb_len,
+	};
+
+	memset(&relocs, 0, sizeof(relocs));
+
+	/* MI_BATCH_BUFFER_START */
+	relocs[0].target_handle = 1;
+	relocs[0].delta = context->timestamp2_ptr - context->wait_bb;
+	relocs[0].offset = context->jump_ptr - context->wait_bb;
+	relocs[0].presumed_offset = -1;
+
+	submit_timeline_execbuf(context, &execbuf, run_engine_idx,
+				0, 0,
+				signal_syncobj, signal_value);
+}
+
+static void build_increment_engine_bb(struct inter_engine_batches *batch,
+				      uint32_t mmio_base)
+{
+	uint32_t *bb = batch->increment_bb = calloc(1, 4096);
+
+	*bb++ = MI_LOAD_REGISTER_MEM_GEN8;
+	*bb++ = mmio_base + HSW_CS_GPR(0);
+	batch->read0_ptrs[0] = bb;
+	*bb++ = 0;
+	*bb++ = 0;
+	*bb++ = MI_LOAD_REGISTER_MEM_GEN8;
+	*bb++ = mmio_base + HSW_CS_GPR(0) + 4;
+	batch->read0_ptrs[1] = bb;
+	*bb++ = 0;
+	*bb++ = 0;
+
+	*bb++ = MI_LOAD_REGISTER_MEM_GEN8;
+	*bb++ = mmio_base + HSW_CS_GPR(1);
+	batch->read1_ptrs[0] = bb;
+	*bb++ = 0;
+	*bb++ = 0;
+	*bb++ = MI_LOAD_REGISTER_MEM_GEN8;
+	*bb++ = mmio_base + HSW_CS_GPR(1) + 4;
+	batch->read1_ptrs[1] = bb;
+	*bb++ = 0;
+	*bb++ = 0;
+
+	*bb++ = MI_MATH(4);
+	*bb++ = MI_MATH_LOAD(MI_MATH_REG_SRCA, MI_MATH_REG(0));
+	*bb++ = MI_MATH_LOAD(MI_MATH_REG_SRCB, MI_MATH_REG(1));
+	*bb++ = MI_MATH_ADD;
+	*bb++ = MI_MATH_STORE(MI_MATH_REG(0), MI_MATH_REG_ACCU);
+
+	*bb++ = MI_STORE_REGISTER_MEM_GEN8;
+	*bb++ = mmio_base + HSW_CS_GPR(0);
+	batch->write_ptrs[0] = bb;
+	*bb++ = 0;
+	*bb++ = 0;
+	*bb++ = MI_STORE_REGISTER_MEM_GEN8;
+	*bb++ = mmio_base + HSW_CS_GPR(0) + 4;
+	batch->write_ptrs[1] = bb;
+	*bb++ = 0;
+	*bb++ = 0;
+
+	*bb++ = MI_BATCH_BUFFER_END;
+
+	batch->increment_bb_len = ALIGN((void *) bb - batch->increment_bb, 8);
+}
+
+static void increment_engine(struct inter_engine_context *context,
+			     uint32_t gem_context,
+			     uint32_t read0_engine_idx,
+			     uint32_t read1_engine_idx,
+			     uint32_t write_engine_idx,
+			     uint32_t wait_syncobj,
+			     uint64_t wait_value,
+			     uint32_t signal_syncobj,
+			     uint64_t signal_value)
+{
+	struct inter_engine_batches *batch = &context->batches[write_engine_idx];
+	struct drm_i915_gem_relocation_entry relocs[3 * 2];
+	struct drm_i915_gem_exec_object2 objects[2] = {
+		context->engine_counter_object,
+		{
+			.handle = batch->increment_bb_handle,
+			.relocs_ptr = to_user_pointer(relocs),
+			.relocation_count = ARRAY_SIZE(relocs),
+		},
+	};
+	struct drm_i915_gem_execbuffer2 execbuf = {
+		.buffers_ptr = to_user_pointer(&objects[0]),
+		.buffer_count = ARRAY_SIZE(objects),
+		.flags = I915_EXEC_HANDLE_LUT,
+		.rsvd1 = gem_context,
+		.batch_len = batch->increment_bb_len,
+	};
+
+	memset(relocs, 0, sizeof(relocs));
+
+	/* MI_LOAD_REGISTER_MEM */
+	relocs[0].target_handle = 0;
+	relocs[0].delta = read0_engine_idx * 8;
+	relocs[0].offset = batch->read0_ptrs[0] - batch->increment_bb;
+	relocs[0].presumed_offset = -1;
+	relocs[1].target_handle = 0;
+	relocs[1].delta = read0_engine_idx * 8 + 4;
+	relocs[1].offset = batch->read0_ptrs[1] - batch->increment_bb;
+	relocs[1].presumed_offset = -1;
+
+	/* MI_LOAD_REGISTER_MEM */
+	relocs[2].target_handle = 0;
+	relocs[2].delta = read1_engine_idx * 8;
+	relocs[2].offset = batch->read1_ptrs[0] - batch->increment_bb;
+	relocs[2].presumed_offset = -1;
+	relocs[3].target_handle = 0;
+	relocs[3].delta = read1_engine_idx * 8 + 4;
+	relocs[3].offset = batch->read1_ptrs[1] - batch->increment_bb;
+	relocs[3].presumed_offset = -1;
+
+	/* MI_STORE_REGISTER_MEM */
+	relocs[4].target_handle = 0;
+	relocs[4].delta = write_engine_idx * 8;
+	relocs[4].offset = batch->write_ptrs[0] - batch->increment_bb;
+	relocs[4].presumed_offset = -1;
+	relocs[5].target_handle = 0;
+	relocs[5].delta = write_engine_idx * 8 + 4;
+	relocs[5].offset = batch->write_ptrs[1] - batch->increment_bb;
+	relocs[5].presumed_offset = -1;
+
+	submit_timeline_execbuf(context, &execbuf, write_engine_idx,
+				wait_syncobj, wait_value,
+				signal_syncobj, signal_value);
+
+	context->engine_counter_object = objects[0];
+}
+
+static uint64_t fib(uint32_t iters)
+{
+	uint64_t last_value = 0;
+	uint64_t value = 1;
+	uint32_t i = 0;
+
+	while (i < iters) {
+		uint64_t new_value = value + last_value;
+
+		last_value = value;
+		value = new_value;
+		i++;
+	}
+
+	return last_value;
+}
+
+static uint64_t
+get_cs_timestamp_frequency(int fd)
+{
+	int cs_ts_freq = 0;
+	drm_i915_getparam_t gp;
+
+	gp.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY;
+	gp.value = &cs_ts_freq;
+	if (igt_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) == 0)
+		return cs_ts_freq;
+
+	igt_skip("Kernel with PARAM_CS_TIMESTAMP_FREQUENCY support required\n");
+}
+
+static void setup_timeline_chain_engines(struct inter_engine_context *context, int fd, struct intel_engine_data *engines)
+{
+	memset(context, 0, sizeof(*context));
+
+	context->fd = fd;
+	context->engines = engines;
+
+	context->wait_context = gem_context_create(fd);
+	context->wait_timeline = syncobj_create(fd, 0);
+
+	context->engine_counter_object.handle = gem_create(fd, 4096);
+
+	for (uint32_t i = 0; i < ARRAY_SIZE(context->iterations); i++) {
+		context->iterations[i].context = gem_context_create(fd);
+
+		gem_context_set_all_engines(fd, context->iterations[i].context);
+
+		/* Give a different priority to all contexts. */
+		gem_context_set_priority(fd, context->iterations[i].context,
+					 I915_CONTEXT_MAX_USER_PRIORITY - ARRAY_SIZE(context->iterations) + i);
+	}
+
+	build_wait_bb(context, 20 * 1000 * 1000ull /* 20ms */, get_cs_timestamp_frequency(fd));
+	context->wait_bb_handle = gem_create(fd, 4096);
+	gem_write(fd, context->wait_bb_handle, 0,
+		  context->wait_bb, context->wait_bb_len);
+
+	context->batches = calloc(engines->nengines, sizeof(*context->batches));
+	for (uint32_t e = 0; e < engines->nengines; e++) {
+		struct inter_engine_batches *batches = &context->batches[e];
+
+		batches->timeline = syncobj_create(fd, 0);
+
+		build_increment_engine_bb(
+			batches,
+			gem_engine_mmio_base(fd, engines->engines[e].name));
+		batches->increment_bb_handle = gem_create(fd, 4096);
+		gem_write(fd, batches->increment_bb_handle, 0,
+			  batches->increment_bb, batches->increment_bb_len);
+	}
+
+	for (uint32_t i = 0; i < 10; i++)
+		igt_debug("%u = %lu\n", i, fib(i));
+
+	/* Bootstrap the fibonacci sequence */
+	{
+		uint64_t dword = 1;
+		gem_write(fd, context->engine_counter_object.handle,
+			  sizeof(dword) * (context->engines->nengines - 1),
+			  &dword, sizeof(dword));
+	}
+}
+
+static void teardown_timeline_chain_engines(struct inter_engine_context *context)
+{
+	gem_close(context->fd, context->engine_counter_object.handle);
+
+	for (uint32_t i = 0; i < ARRAY_SIZE(context->iterations); i++) {
+		gem_context_destroy(context->fd, context->iterations[i].context);
+	}
+
+	gem_context_destroy(context->fd, context->wait_context);
+	syncobj_destroy(context->fd, context->wait_timeline);
+	gem_close(context->fd, context->wait_bb_handle);
+	free(context->wait_bb);
+
+	for (uint32_t e = 0; e < context->engines->nengines; e++) {
+		struct inter_engine_batches *batches = &context->batches[e];
+
+		syncobj_destroy(context->fd, batches->timeline);
+		gem_close(context->fd, batches->increment_bb_handle);
+		free(batches->increment_bb);
+	}
+	free(context->batches);
+}
+
+static void test_syncobj_timeline_chain_engines(int fd, struct intel_engine_data *engines)
+{
+	struct inter_engine_context ctx;
+	uint64_t *counter_output;
+
+	setup_timeline_chain_engines(&ctx, fd, engines);
+
+	/*
+	 * Delay all the other operations by making them depend on an
+	 * active wait on the RCS.
+	 */
+	wait_engine(&ctx, 0, ctx.wait_timeline, 1);
+
+	for (uint32_t iter = 0; iter < ARRAY_SIZE(ctx.iterations); iter++) {
+		for (uint32_t engine = 0; engine < engines->nengines; engine++) {
+			uint32_t prev_prev_engine =
+				(engines->nengines + engine - 2) % engines->nengines;
+			uint32_t prev_engine =
+				(engines->nengines + engine - 1) % engines->nengines;
+			/*
+			 * Pick up the wait engine semaphore for the
+			 * first increment, then pick up the previous
+			 * engine's timeline.
+			 */
+			uint32_t wait_syncobj =
+				iter == 0 && engine == 0 ?
+				ctx.wait_timeline : ctx.batches[prev_engine].timeline;
+			uint32_t wait_value =
+				iter == 0 && engine == 0 ?
+				1 : (engine == 0 ? iter : (iter + 1));
+
+			increment_engine(&ctx, ctx.iterations[iter].context,
+					 prev_prev_engine /* read0 engine */,
+					 prev_engine /* read1 engine */,
+					 engine /* write engine */,
+					 wait_syncobj, wait_value,
+					 ctx.batches[engine].timeline, iter + 1);
+		}
+	}
+
+	gem_sync(fd, ctx.engine_counter_object.handle);
+
+	counter_output = gem_mmap__wc(fd, ctx.engine_counter_object.handle, 0, 4096, PROT_READ);
+
+	for (uint32_t i = 0; i < ctx.engines->nengines; i++)
+		igt_debug("engine %i (%s)\t= %016lx\n", i,
+			  ctx.engines->engines[i].name, counter_output[i]);
+
+	/*
+	 * Verify that we get the fibonacci number expected (we start
+	 * at the sequence on the second number : 1).
+	 */
+	igt_assert_eq(counter_output[engines->nengines - 1],
+		      fib(ARRAY_SIZE(ctx.iterations) * engines->nengines + 1));
+
+	munmap(counter_output, 4096);
+
+	teardown_timeline_chain_engines(&ctx);
+}
+
+static void test_syncobj_stationary_timeline_chain_engines(int fd, struct intel_engine_data *engines)
+{
+	struct inter_engine_context ctx;
+	uint64_t *counter_output;
+
+	setup_timeline_chain_engines(&ctx, fd, engines);
+
+	/*
+	 * Delay all the other operations by making them depend on an
+	 * active wait on the RCS.
+	 */
+	wait_engine(&ctx, 0, ctx.wait_timeline, 1);
+
+	for (uint32_t iter = 0; iter < ARRAY_SIZE(ctx.iterations); iter++) {
+		for (uint32_t engine = 0; engine < engines->nengines; engine++) {
+			uint32_t prev_prev_engine =
+				(engines->nengines + engine - 2) % engines->nengines;
+			uint32_t prev_engine =
+				(engines->nengines + engine - 1) % engines->nengines;
+			/*
+			 * Pick up the wait engine semaphore for the
+			 * first increment, then pick up the previous
+			 * engine's timeline.
+			 */
+			uint32_t wait_syncobj =
+				iter == 0 && engine == 0 ?
+				ctx.wait_timeline : ctx.batches[prev_engine].timeline;
+			/*
+			 * Always signal the value 10. Because the
+			 * signal operations are submitted in order,
+			 * we should always pickup the right
+			 * dma-fence.
+			 */
+			uint32_t wait_value =
+				iter == 0 && engine == 0 ?
+				1 : 10;
+
+			increment_engine(&ctx, ctx.iterations[iter].context,
+					 prev_prev_engine /* read0 engine */,
+					 prev_engine /* read1 engine */,
+					 engine /* write engine */,
+					 wait_syncobj, wait_value,
+					 ctx.batches[engine].timeline, 10);
+		}
+	}
+
+	gem_sync(fd, ctx.engine_counter_object.handle);
+
+	counter_output = gem_mmap__wc(fd, ctx.engine_counter_object.handle, 0, 4096, PROT_READ);
+
+	for (uint32_t i = 0; i < ctx.engines->nengines; i++)
+		igt_debug("engine %i (%s)\t= %016lx\n", i,
+			  ctx.engines->engines[i].name, counter_output[i]);
+	igt_assert_eq(counter_output[engines->nengines - 1],
+		      fib(ARRAY_SIZE(ctx.iterations) * engines->nengines + 1));
+
+	munmap(counter_output, 4096);
+
+	teardown_timeline_chain_engines(&ctx);
+}
+
+static void test_syncobj_backward_timeline_chain_engines(int fd, struct intel_engine_data *engines)
+{
+	struct inter_engine_context ctx;
+	uint64_t *counter_output;
+
+	setup_timeline_chain_engines(&ctx, fd, engines);
+
+	/*
+	 * Delay all the other operations by making them depend on an
+	 * active wait on the RCS.
+	 */
+	wait_engine(&ctx, 0, ctx.wait_timeline, 1);
+
+	for (uint32_t iter = 0; iter < ARRAY_SIZE(ctx.iterations); iter++) {
+		for (uint32_t engine = 0; engine < engines->nengines; engine++) {
+			uint32_t prev_prev_engine =
+				(engines->nengines + engine - 2) % engines->nengines;
+			uint32_t prev_engine =
+				(engines->nengines + engine - 1) % engines->nengines;
+			/*
+			 * Pick up the wait engine semaphore for the
+			 * first increment, then pick up the previous
+			 * engine's timeline.
+			 */
+			uint32_t wait_syncobj =
+				iter == 0 && engine == 0 ?
+				ctx.wait_timeline : ctx.batches[prev_engine].timeline;
+			/*
+			 * Always signal the value 10. Because the
+			 * signal operations are submitted in order,
+			 * we should always pickup the right
+			 * dma-fence.
+			 */
+			uint32_t wait_value =
+				iter == 0 && engine == 0 ?
+				1 : 1;
+
+			increment_engine(&ctx, ctx.iterations[iter].context,
+					 prev_prev_engine /* read0 engine */,
+					 prev_engine /* read1 engine */,
+					 engine /* write engine */,
+					 wait_syncobj, wait_value,
+					 ctx.batches[engine].timeline, ARRAY_SIZE(ctx.iterations) - iter);
+		}
+	}
+
+	gem_sync(fd, ctx.engine_counter_object.handle);
+
+	counter_output = gem_mmap__wc(fd, ctx.engine_counter_object.handle, 0, 4096, PROT_READ);
+
+	for (uint32_t i = 0; i < ctx.engines->nengines; i++)
+		igt_debug("engine %i (%s)\t= %016lx\n", i,
+			  ctx.engines->engines[i].name, counter_output[i]);
+	igt_assert_eq(counter_output[engines->nengines - 1],
+		      fib(ARRAY_SIZE(ctx.iterations) * engines->nengines + 1));
+
+	munmap(counter_output, 4096);
+
+	teardown_timeline_chain_engines(&ctx);
+}
+
 igt_main
 {
 	const struct intel_execution_engine *e;
@@ -2209,6 +2822,30 @@ igt_main
 		igt_subtest("syncobj-timeline-repeat")
 			test_syncobj_timeline_repeat(i915);
 
+		igt_subtest_group { /* syncobj timeline engine chaining */
+			struct intel_engine_data engines;
+
+			igt_fixture {
+				/*
+				 * We need support for MI_ALU on all
+				 * engines which seems to be there
+				 * only on Gen8+
+				 */
+				igt_require(intel_gen(intel_get_drm_devid(i915)) >= 8);
+				igt_require(engines.nengines > 1);
+				engines = intel_init_engine_list(i915, 0);
+			}
+
+			igt_subtest("syncobj-timeline-chain-engines")
+				test_syncobj_timeline_chain_engines(i915, &engines);
+
+			igt_subtest("syncobj-stationary-timeline-chain-engines")
+				test_syncobj_stationary_timeline_chain_engines(i915, &engines);
+
+			igt_subtest("syncobj-backward-timeline-chain-engines")
+				test_syncobj_backward_timeline_chain_engines(i915, &engines);
+		}
+
 		igt_fixture {
 			igt_stop_hang_detector();
 		}
-- 
2.24.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [igt-dev] ✗ GitLab.Pipeline: warning for tests: Add timeline syncobj testing (rev2)
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (9 preceding siblings ...)
  2019-11-22 13:03 ` [igt-dev] [PATCH i-g-t v2 10/10] tests/i915/gem_exec_fence: add engine chaining tests Lionel Landwerlin
@ 2019-11-22 14:10 ` Patchwork
  2019-11-22 14:16 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
  2019-11-23 21:15 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2019-11-22 14:10 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: igt-dev

== Series Details ==

Series: tests: Add timeline syncobj testing (rev2)
URL   : https://patchwork.freedesktop.org/series/69782/
State : warning

== Summary ==

Did not get list of undocumented tests for this run, something is wrong!

Other than that, pipeline status: FAILED.

see https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/pipelines/81889 for the overview.

== Logs ==

For more details see: https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/pipelines/81889
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for tests: Add timeline syncobj testing (rev2)
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (10 preceding siblings ...)
  2019-11-22 14:10 ` [igt-dev] ✗ GitLab.Pipeline: warning for tests: Add timeline syncobj testing (rev2) Patchwork
@ 2019-11-22 14:16 ` Patchwork
  2019-11-23 21:15 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2019-11-22 14:16 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: igt-dev

== Series Details ==

Series: tests: Add timeline syncobj testing (rev2)
URL   : https://patchwork.freedesktop.org/series/69782/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_7405 -> IGTPW_3750
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/index.html

Known issues
------------

  Here are the changes found in IGTPW_3750 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_selftest@live_gem_contexts:
    - fi-bsw-nick:        [PASS][1] -> [INCOMPLETE][2] ([fdo# 111542])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/fi-bsw-nick/igt@i915_selftest@live_gem_contexts.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/fi-bsw-nick/igt@i915_selftest@live_gem_contexts.html
    - fi-cfl-guc:         [PASS][3] -> [INCOMPLETE][4] ([fdo#106070] / [fdo#111700])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/fi-cfl-guc/igt@i915_selftest@live_gem_contexts.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/fi-cfl-guc/igt@i915_selftest@live_gem_contexts.html

  * igt@prime_vgem@basic-fence-read:
    - fi-icl-dsi:         [PASS][5] -> [DMESG-WARN][6] ([fdo#106107])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/fi-icl-dsi/igt@prime_vgem@basic-fence-read.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/fi-icl-dsi/igt@prime_vgem@basic-fence-read.html

  
#### Possible fixes ####

  * igt@i915_module_load@reload-no-display:
    - fi-skl-lmem:        [DMESG-WARN][7] ([fdo#112261]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/fi-skl-lmem/igt@i915_module_load@reload-no-display.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/fi-skl-lmem/igt@i915_module_load@reload-no-display.html

  * igt@i915_selftest@live_hangcheck:
    - fi-hsw-4770r:       [DMESG-FAIL][9] ([fdo#111991]) -> [PASS][10]
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/fi-hsw-4770r/igt@i915_selftest@live_hangcheck.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/fi-hsw-4770r/igt@i915_selftest@live_hangcheck.html

  
#### Warnings ####

  * igt@gem_exec_suspend@basic-s0:
    - fi-kbl-x1275:       [DMESG-WARN][11] ([fdo#103558] / [fdo#105602] / [fdo#105763]) -> [DMESG-WARN][12] ([fdo#103558] / [fdo#105602]) +6 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/fi-kbl-x1275/igt@gem_exec_suspend@basic-s0.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/fi-kbl-x1275/igt@gem_exec_suspend@basic-s0.html

  * igt@kms_cursor_legacy@basic-flip-after-cursor-atomic:
    - fi-kbl-x1275:       [DMESG-WARN][13] ([fdo#103558] / [fdo#105602]) -> [DMESG-WARN][14] ([fdo#103558] / [fdo#105602] / [fdo#105763]) +5 similar issues
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/fi-kbl-x1275/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/fi-kbl-x1275/igt@kms_cursor_legacy@basic-flip-after-cursor-atomic.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo# 111542]: https://bugs.freedesktop.org/show_bug.cgi?id= 111542
  [fdo#103558]: https://bugs.freedesktop.org/show_bug.cgi?id=103558
  [fdo#105602]: https://bugs.freedesktop.org/show_bug.cgi?id=105602
  [fdo#105763]: https://bugs.freedesktop.org/show_bug.cgi?id=105763
  [fdo#106070]: https://bugs.freedesktop.org/show_bug.cgi?id=106070
  [fdo#106107]: https://bugs.freedesktop.org/show_bug.cgi?id=106107
  [fdo#109964]: https://bugs.freedesktop.org/show_bug.cgi?id=109964
  [fdo#111700]: https://bugs.freedesktop.org/show_bug.cgi?id=111700
  [fdo#111991]: https://bugs.freedesktop.org/show_bug.cgi?id=111991
  [fdo#112261]: https://bugs.freedesktop.org/show_bug.cgi?id=112261
  [fdo#112298]: https://bugs.freedesktop.org/show_bug.cgi?id=112298


Participating hosts (49 -> 44)
------------------------------

  Additional (1): fi-snb-2600 
  Missing    (6): fi-ilk-m540 fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 fi-byt-clapper fi-bdw-samus 


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_5301 -> IGTPW_3750

  CI-20190529: 20190529
  CI_DRM_7405: 8a552b51e24ce46814072f99817a64ed3fa35055 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_3750: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/index.html
  IGT_5301: 3fa72891269b16943e6511166aeebee094206791 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools



== Testlist changes ==

+++ 132 lines
--- 0 lines

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests Lionel Landwerlin
@ 2019-11-22 15:13   ` Chris Wilson
  2019-11-22 15:17     ` Lionel Landwerlin
  2019-11-22 15:26   ` Chris Wilson
  1 sibling, 1 reply; 24+ messages in thread
From: Chris Wilson @ 2019-11-22 15:13 UTC (permalink / raw)
  To: Lionel Landwerlin, igt-dev

Quoting Lionel Landwerlin (2019-11-22 13:02:58)
> We can now give a tuple (handle, point_value) for timeline semaphores.
> 
> v2: Fix up syncobj-timeline-repeat test (Lionel)
>     Update following kernel rename
> 
> v3: Add more ordering tests for syncobj/buffer handle state (Chris)

One thing I did not spot was using the syncobj to schedule different
contexts. Is that interesting?
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 15:13   ` Chris Wilson
@ 2019-11-22 15:17     ` Lionel Landwerlin
  2019-11-22 15:23       ` Chris Wilson
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 15:17 UTC (permalink / raw)
  To: Chris Wilson, igt-dev

On 22/11/2019 17:13, Chris Wilson wrote:
> Quoting Lionel Landwerlin (2019-11-22 13:02:58)
>> We can now give a tuple (handle, point_value) for timeline semaphores.
>>
>> v2: Fix up syncobj-timeline-repeat test (Lionel)
>>      Update following kernel rename
>>
>> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
> One thing I did not spot was using the syncobj to schedule different
> contexts. Is that interesting?
> -Chris

The chaining tests are using different context & different engines for 
each point of the timeline.

Is that what you're looking for?


-Lionel

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 15:17     ` Lionel Landwerlin
@ 2019-11-22 15:23       ` Chris Wilson
  2019-11-22 15:47         ` Lionel Landwerlin
  0 siblings, 1 reply; 24+ messages in thread
From: Chris Wilson @ 2019-11-22 15:23 UTC (permalink / raw)
  To: Lionel Landwerlin, igt-dev

Quoting Lionel Landwerlin (2019-11-22 15:17:02)
> On 22/11/2019 17:13, Chris Wilson wrote:
> > Quoting Lionel Landwerlin (2019-11-22 13:02:58)
> >> We can now give a tuple (handle, point_value) for timeline semaphores.
> >>
> >> v2: Fix up syncobj-timeline-repeat test (Lionel)
> >>      Update following kernel rename
> >>
> >> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
> > One thing I did not spot was using the syncobj to schedule different
> > contexts. Is that interesting?
> > -Chris
> 
> The chaining tests are using different context & different engines for 
> each point of the timeline.
> 
> Is that what you're looking for?

Patch 10? Yeah, that probably does more than what I was thinking, which
is just that contexts cannot be rescheduled past their syncpts.

/me goes back to trying to find gaps

Where's gcov when you need it?
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests Lionel Landwerlin
  2019-11-22 15:13   ` Chris Wilson
@ 2019-11-22 15:26   ` Chris Wilson
  2019-11-22 15:43     ` Lionel Landwerlin
  1 sibling, 1 reply; 24+ messages in thread
From: Chris Wilson @ 2019-11-22 15:26 UTC (permalink / raw)
  To: Lionel Landwerlin, igt-dev

Quoting Lionel Landwerlin (2019-11-22 13:02:58)
> We can now give a tuple (handle, point_value) for timeline semaphores.
> 
> v2: Fix up syncobj-timeline-repeat test (Lionel)
>     Update following kernel rename
> 
> v3: Add more ordering tests for syncobj/buffer handle state (Chris)

Another question, do we worry about sw_sync imported fences being
handles differently to native?
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 15:26   ` Chris Wilson
@ 2019-11-22 15:43     ` Lionel Landwerlin
  2019-11-22 15:51       ` Chris Wilson
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 15:43 UTC (permalink / raw)
  To: Chris Wilson, igt-dev

On 22/11/2019 17:26, Chris Wilson wrote:
> Quoting Lionel Landwerlin (2019-11-22 13:02:58)
>> We can now give a tuple (handle, point_value) for timeline semaphores.
>>
>> v2: Fix up syncobj-timeline-repeat test (Lionel)
>>      Update following kernel rename
>>
>> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
> Another question, do we worry about sw_sync imported fences being
> handles differently to native?
> -Chris

What do you mean by differently?


Thing is sw_sync can delay the signaling forever so you could build a 
case exhausting memory if you really wanted.

Whereas my understand of other dma-fences is that they should be short 
lived.


-Lionel

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 15:23       ` Chris Wilson
@ 2019-11-22 15:47         ` Lionel Landwerlin
  0 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 15:47 UTC (permalink / raw)
  To: Chris Wilson, igt-dev

On 22/11/2019 17:23, Chris Wilson wrote:
> Quoting Lionel Landwerlin (2019-11-22 15:17:02)
>> On 22/11/2019 17:13, Chris Wilson wrote:
>>> Quoting Lionel Landwerlin (2019-11-22 13:02:58)
>>>> We can now give a tuple (handle, point_value) for timeline semaphores.
>>>>
>>>> v2: Fix up syncobj-timeline-repeat test (Lionel)
>>>>       Update following kernel rename
>>>>
>>>> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
>>> One thing I did not spot was using the syncobj to schedule different
>>> contexts. Is that interesting?
>>> -Chris
>> The chaining tests are using different context & different engines for
>> each point of the timeline.
>>
>> Is that what you're looking for?
> Patch 10? Yeah, that probably does more than what I was thinking, which
> is just that contexts cannot be rescheduled past their syncpts.


One reason I kind of somewhat confident is that you cannot build 
circular dependencies.

When we create a new node in the timeline, we make it out of existing 
fences and the dma-fence-chain structure does not allow putting new 
nodes anywhere other than the front of the timeline.


-Lionel


>
> /me goes back to trying to find gaps
>
> Where's gcov when you need it?
> -Chris


_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 15:43     ` Lionel Landwerlin
@ 2019-11-22 15:51       ` Chris Wilson
  2019-11-22 16:03         ` Lionel Landwerlin
  0 siblings, 1 reply; 24+ messages in thread
From: Chris Wilson @ 2019-11-22 15:51 UTC (permalink / raw)
  To: Lionel Landwerlin, igt-dev

Quoting Lionel Landwerlin (2019-11-22 15:43:11)
> On 22/11/2019 17:26, Chris Wilson wrote:
> > Quoting Lionel Landwerlin (2019-11-22 13:02:58)
> >> We can now give a tuple (handle, point_value) for timeline semaphores.
> >>
> >> v2: Fix up syncobj-timeline-repeat test (Lionel)
> >>      Update following kernel rename
> >>
> >> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
> > Another question, do we worry about sw_sync imported fences being
> > handles differently to native?
> > -Chris
> 
> What do you mean by differently?

We have is_i915_fence() with branching paths for internal/external, and
within the syncobj timeline mixed fence contexts cause a hard barrier,
so may present interesting effects at the uAPI layer?

> Thing is sw_sync can delay the signaling forever so you could build a 
> case exhausting memory if you really wanted.

Except we don't allow indefinite waits for external fences such as
sw_sync and wrap them in auto-expiring fences.

> Whereas my understand of other dma-fences is that they should be short 
> lived.

Endless. How's that going to end? Badly.
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 15:51       ` Chris Wilson
@ 2019-11-22 16:03         ` Lionel Landwerlin
  2019-11-22 16:11           ` Chris Wilson
  0 siblings, 1 reply; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-22 16:03 UTC (permalink / raw)
  To: Chris Wilson, igt-dev

On 22/11/2019 17:51, Chris Wilson wrote:
> Quoting Lionel Landwerlin (2019-11-22 15:43:11)
>> On 22/11/2019 17:26, Chris Wilson wrote:
>>> Quoting Lionel Landwerlin (2019-11-22 13:02:58)
>>>> We can now give a tuple (handle, point_value) for timeline semaphores.
>>>>
>>>> v2: Fix up syncobj-timeline-repeat test (Lionel)
>>>>       Update following kernel rename
>>>>
>>>> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
>>> Another question, do we worry about sw_sync imported fences being
>>> handles differently to native?
>>> -Chris
>> What do you mean by differently?
> We have is_i915_fence() with branching paths for internal/external, and
> within the syncobj timeline mixed fence contexts cause a hard barrier,
> so may present interesting effects at the uAPI layer?


Well... same issues with an array of i915 fences right?


I guess fence_set_priority() could be adjusted to deal with 
dma-fence-chain like it does with dma-fence-array.


-Lionel


>
>> Thing is sw_sync can delay the signaling forever so you could build a
>> case exhausting memory if you really wanted.
> Except we don't allow indefinite waits for external fences such as
> sw_sync and wrap them in auto-expiring fences.
>
>> Whereas my understand of other dma-fences is that they should be short
>> lived.
> Endless. How's that going to end? Badly.
> -Chris


_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 16:03         ` Lionel Landwerlin
@ 2019-11-22 16:11           ` Chris Wilson
  2019-11-27 16:04             ` Lionel Landwerlin
  0 siblings, 1 reply; 24+ messages in thread
From: Chris Wilson @ 2019-11-22 16:11 UTC (permalink / raw)
  To: Lionel Landwerlin, igt-dev

Quoting Lionel Landwerlin (2019-11-22 16:03:16)
> On 22/11/2019 17:51, Chris Wilson wrote:
> > Quoting Lionel Landwerlin (2019-11-22 15:43:11)
> >> On 22/11/2019 17:26, Chris Wilson wrote:
> >>> Quoting Lionel Landwerlin (2019-11-22 13:02:58)
> >>>> We can now give a tuple (handle, point_value) for timeline semaphores.
> >>>>
> >>>> v2: Fix up syncobj-timeline-repeat test (Lionel)
> >>>>       Update following kernel rename
> >>>>
> >>>> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
> >>> Another question, do we worry about sw_sync imported fences being
> >>> handles differently to native?
> >>> -Chris
> >> What do you mean by differently?
> > We have is_i915_fence() with branching paths for internal/external, and
> > within the syncobj timeline mixed fence contexts cause a hard barrier,
> > so may present interesting effects at the uAPI layer?
> 
> 
> Well... same issues with an array of i915 fences right?
> 
> 
> I guess fence_set_priority() could be adjusted to deal with 
> dma-fence-chain like it does with dma-fence-array.

No, either it's a chain of fence or it's just a list (and shouldn't be
calling itself a chain ;). If it is a chain with dependencies along the
chain, then we already have the information for priority inheritance.
Except dma-fence-chain doesn't _guarantee_ that is the case and leaves
it up to the caller to provide order across fence_contexts (within a
fence_context it the seqno are meant to be ordered, and if the caller
tries to use them out-of-order for syncpts within a dma-fence-chain it
goes into the broken chain path same as for switching fence_contexts).
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [igt-dev] ✓ Fi.CI.IGT: success for tests: Add timeline syncobj testing (rev2)
  2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
                   ` (11 preceding siblings ...)
  2019-11-22 14:16 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
@ 2019-11-23 21:15 ` Patchwork
  12 siblings, 0 replies; 24+ messages in thread
From: Patchwork @ 2019-11-23 21:15 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: igt-dev

== Series Details ==

Series: tests: Add timeline syncobj testing (rev2)
URL   : https://patchwork.freedesktop.org/series/69782/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_7405_full -> IGTPW_3750_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/index.html

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in IGTPW_3750_full:

### IGT changes ###

#### Possible regressions ####

  * {igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-submitted-signaled} (NEW):
    - shard-iclb:         NOTRUN -> [SKIP][1] +119 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb5/igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-submitted-signaled.html

  * {igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-submitted-signaled} (NEW):
    - shard-tglb:         NOTRUN -> [SKIP][2] +82 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-tglb3/igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-submitted-signaled.html

  
New tests
---------

  New tests have been introduced between CI_DRM_7405_full and IGTPW_3750_full:

### New IGT tests (121) ###

  * igt@syncobj_timeline@32bits-limit:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@device-signal-unordered:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@device-submit-unordered:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-available-unsubmitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-available-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-available-unsubmitted-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-for-submit-unsubmitted-submitted-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-all-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-available-unsubmitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-for-submit-unsubmitted-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-multi-wait-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-all-for-submit-available-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-all-for-submit-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-all-for-submit-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-all-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-for-submit-available-unsubmitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-for-submit-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-for-submit-unsubmitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@etime-single-wait-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@host-signal-ordered:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@host-signal-points:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-available-unsubmitted-submitted-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-all-unsubmitted-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-available-unsubmitted-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-multi-wait-unsubmitted-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-query-bad-pad:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-query-illegal-handle:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-query-one-illegal-handle:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-query-zero-handles:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-bad-pad:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-illegal-handle:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-illegal-point:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-one-illegal-handle:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-signal-zero-handles:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-single-wait-all-available-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-single-wait-all-unsubmitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-single-wait-available-unsubmitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-single-wait-unsubmitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-transfer-bad-pad:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-transfer-illegal-handle:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-transfer-non-existent-point:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-wait-bad-flags:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-wait-illegal-handle:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@invalid-wait-zero-handles:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-available-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-available-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-available-submitted-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-available-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-available-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-available-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-for-submit-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-all-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-available-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-available-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-available-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-unsubmitted-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-available-unsubmitted-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-submitted-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-unsubmitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-for-submit-unsubmitted-submitted-signaled:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@multi-wait-submitted-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@reset-during-wait-for-submit:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@reset-multiple-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@reset-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@reset-unsignaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@signal:
    - Statuses : 5 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@signal-array:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@signal-point-0:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-all-available-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-all-available-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-all-for-submit-available-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-all-for-submit-available-submitted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-all-for-submit-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-all-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-available-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-available-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-for-submit-available-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-for-submit-available-submitted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-for-submit-signaled:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@single-wait-signaled:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@transfer-timeline-point:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-all-complex:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-all-delayed-signal:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-all-for-submit-complex:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-all-for-submit-delayed-submit:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-all-for-submit-snapshot:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-all-interrupted:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-all-snapshot:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-any-complex:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-any-interrupted:
    - Statuses : 6 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-any-snapshot:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-delayed-signal:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-for-submit-complex:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-for-submit-delayed-submit:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  * igt@syncobj_timeline@wait-for-submit-snapshot:
    - Statuses : 7 skip(s)
    - Exec time: [0.0] s

  

Known issues
------------

  Here are the changes found in IGTPW_3750_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_busy@busy-vcs1:
    - shard-iclb:         [PASS][3] -> [SKIP][4] ([fdo#112080]) +7 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-iclb1/igt@gem_busy@busy-vcs1.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb8/igt@gem_busy@busy-vcs1.html

  * igt@gem_ctx_isolation@vcs1-clean:
    - shard-iclb:         [PASS][5] -> [SKIP][6] ([fdo#109276] / [fdo#112080]) +1 similar issue
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-iclb2/igt@gem_ctx_isolation@vcs1-clean.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb5/igt@gem_ctx_isolation@vcs1-clean.html

  * igt@gem_exec_create@forked:
    - shard-snb:          [PASS][7] -> [INCOMPLETE][8] ([fdo#105411])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-snb7/igt@gem_exec_create@forked.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-snb1/igt@gem_exec_create@forked.html

  * igt@gem_exec_schedule@preempt-queue-chain-vebox:
    - shard-iclb:         [PASS][9] -> [INCOMPLETE][10] ([fdo#107713])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-iclb3/igt@gem_exec_schedule@preempt-queue-chain-vebox.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb2/igt@gem_exec_schedule@preempt-queue-chain-vebox.html

  * igt@gem_exec_schedule@preempt-self-bsd:
    - shard-iclb:         [PASS][11] -> [SKIP][12] ([fdo#112146])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-iclb8/igt@gem_exec_schedule@preempt-self-bsd.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb1/igt@gem_exec_schedule@preempt-self-bsd.html

  * igt@gem_softpin@noreloc-s3:
    - shard-apl:          [PASS][13] -> [DMESG-WARN][14] ([fdo#108566]) +1 similar issue
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-apl7/igt@gem_softpin@noreloc-s3.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-apl1/igt@gem_softpin@noreloc-s3.html

  * igt@gem_sync@basic-all:
    - shard-tglb:         [PASS][15] -> [INCOMPLETE][16] ([fdo#111880])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-tglb5/igt@gem_sync@basic-all.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-tglb6/igt@gem_sync@basic-all.html

  * igt@gem_userptr_blits@map-fixed-invalidate-busy:
    - shard-hsw:          [PASS][17] -> [DMESG-WARN][18] ([fdo#111870]) +1 similar issue
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-hsw1/igt@gem_userptr_blits@map-fixed-invalidate-busy.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-hsw6/igt@gem_userptr_blits@map-fixed-invalidate-busy.html

  * igt@i915_pm_dc@dc5-dpms:
    - shard-iclb:         [PASS][19] -> [FAIL][20] ([fdo#111795 ])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-iclb2/igt@i915_pm_dc@dc5-dpms.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb3/igt@i915_pm_dc@dc5-dpms.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-iclb:         [PASS][21] -> [FAIL][22] ([fdo#111830 ])
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-iclb5/igt@i915_pm_dc@dc6-psr.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb8/igt@i915_pm_dc@dc6-psr.html

  * igt@i915_suspend@fence-restore-tiled2untiled:
    - shard-iclb:         [PASS][23] -> [DMESG-WARN][24] ([fdo#111764])
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-iclb2/igt@i915_suspend@fence-restore-tiled2untiled.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-iclb1/igt@i915_suspend@fence-restore-tiled2untiled.html

  * igt@kms_cursor_crc@pipe-b-cursor-256x85-onscreen:
    - shard-apl:          [PASS][25] -> [FAIL][26] ([fdo#103232])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-apl8/igt@kms_cursor_crc@pipe-b-cursor-256x85-onscreen.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-apl1/igt@kms_cursor_crc@pipe-b-cursor-256x85-onscreen.html
    - shard-kbl:          [PASS][27] -> [FAIL][28] ([fdo#103232])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-kbl6/igt@kms_cursor_crc@pipe-b-cursor-256x85-onscreen.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-kbl1/igt@kms_cursor_crc@pipe-b-cursor-256x85-onscreen.html

  * igt@kms_fbcon_fbt@fbc-suspend:
    - shard-tglb:         [PASS][29] -> [INCOMPLETE][30] ([fdo#111747] / [fdo#111832] / [fdo#111850])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_7405/shard-tglb5/igt@kms_fbcon_fbt@fbc-suspend.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/shard-tglb8/igt@kms_fbc

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_3750/index.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests
  2019-11-22 16:11           ` Chris Wilson
@ 2019-11-27 16:04             ` Lionel Landwerlin
  0 siblings, 0 replies; 24+ messages in thread
From: Lionel Landwerlin @ 2019-11-27 16:04 UTC (permalink / raw)
  To: Chris Wilson, igt-dev

On 22/11/2019 18:11, Chris Wilson wrote:
> Quoting Lionel Landwerlin (2019-11-22 16:03:16)
>> On 22/11/2019 17:51, Chris Wilson wrote:
>>> Quoting Lionel Landwerlin (2019-11-22 15:43:11)
>>>> On 22/11/2019 17:26, Chris Wilson wrote:
>>>>> Quoting Lionel Landwerlin (2019-11-22 13:02:58)
>>>>>> We can now give a tuple (handle, point_value) for timeline semaphores.
>>>>>>
>>>>>> v2: Fix up syncobj-timeline-repeat test (Lionel)
>>>>>>        Update following kernel rename
>>>>>>
>>>>>> v3: Add more ordering tests for syncobj/buffer handle state (Chris)
>>>>> Another question, do we worry about sw_sync imported fences being
>>>>> handles differently to native?
>>>>> -Chris
>>>> What do you mean by differently?
>>> We have is_i915_fence() with branching paths for internal/external, and
>>> within the syncobj timeline mixed fence contexts cause a hard barrier,
>>> so may present interesting effects at the uAPI layer?
>>
>> Well... same issues with an array of i915 fences right?
>>
>>
>> I guess fence_set_priority() could be adjusted to deal with
>> dma-fence-chain like it does with dma-fence-array.
> No, either it's a chain of fence or it's just a list (and shouldn't be
> calling itself a chain ;). If it is a chain with dependencies along the
> chain, then we already have the information for priority inheritance.
> Except dma-fence-chain doesn't _guarantee_ that is the case and leaves
> it up to the caller to provide order across fence_contexts (within a
> fence_context it the seqno are meant to be ordered, and if the caller
> tries to use them out-of-order for syncpts within a dma-fence-chain it
> goes into the broken chain path same as for switching fence_contexts).
> -Chris

I could walk the chain and peel the dma-chain-fence nodes to add the 
actual underlying fences in the execbuf path.

But it sounds more like optimization than something else.


I'm not sure I follow your point about seqno ordering though.

Within a timeline it's always ordered (because of the new = MAX(old, new)).

Even if the context changes, the seqnos are always increasing.


-Lionel


_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2019-11-27 16:04 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-22 13:02 [igt-dev] [PATCH i-g-t v2 00/10] tests: Add timeline syncobj testing Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 01/10] lib/syncobj: drop local declarations Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 02/10] drm-uapi: Update drm headers to 17cc51390c141662748dbbc2fe98f3ed10f2e13e Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 03/10] igt: add timeline test cases Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 04/10] tests/syncobj_timeline: add more timeline tests Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 05/10] tests/i915/exec_fence: switch to internal headers Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 06/10] tests/i915/exec_fence: reuse syncobj helpers Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 07/10] include: bump drm headers for i915 timeline semaphores Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 08/10] tests/i915/exec_fence: add timeline fence tests Lionel Landwerlin
2019-11-22 15:13   ` Chris Wilson
2019-11-22 15:17     ` Lionel Landwerlin
2019-11-22 15:23       ` Chris Wilson
2019-11-22 15:47         ` Lionel Landwerlin
2019-11-22 15:26   ` Chris Wilson
2019-11-22 15:43     ` Lionel Landwerlin
2019-11-22 15:51       ` Chris Wilson
2019-11-22 16:03         ` Lionel Landwerlin
2019-11-22 16:11           ` Chris Wilson
2019-11-27 16:04             ` Lionel Landwerlin
2019-11-22 13:02 ` [igt-dev] [PATCH i-g-t v2 09/10] lib/i915: Parse mmio base from debugfs Lionel Landwerlin
2019-11-22 13:03 ` [igt-dev] [PATCH i-g-t v2 10/10] tests/i915/gem_exec_fence: add engine chaining tests Lionel Landwerlin
2019-11-22 14:10 ` [igt-dev] ✗ GitLab.Pipeline: warning for tests: Add timeline syncobj testing (rev2) Patchwork
2019-11-22 14:16 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
2019-11-23 21:15 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.