diff mbox

[i-g-t,3/3] tests/query_info: add topology query tests

Message ID 20171108162411.4247-4-lionel.g.landwerlin@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lionel Landwerlin Nov. 8, 2017, 4:24 p.m. UTC
We can verify that topology is consistent with previous getparam like
EU_TOTAL.

We also verify that CS timestamp frequency is always filled.

v2: Use v2 of kernel uapi (Lionel)
    Fix Gen < 8 issue

v3: Use query info uAPI (Lionel)

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

Patch

diff --git a/tests/query_info.c b/tests/query_info.c
index 18a91983..66abc393 100644
--- a/tests/query_info.c
+++ b/tests/query_info.c
@@ -84,6 +84,72 @@  struct local_drm_i915_query_info {
 	__u64 info_ptr;
 };
 
+#ifndef I915_PARAM_SLICE_MASK
+#define I915_PARAM_SLICE_MASK		 46
+#endif
+
+#ifndef I915_PARAM_SUBSLICE_MASK
+#define I915_PARAM_SUBSLICE_MASK	 47
+#endif
+
+#ifndef I915_QUERY_INFO_RCS_TOPOLOGY
+/* Query RCS topology.
+ *
+ * drm_i915_query_info.query_params[0] should be set to one of the
+ * I915_RCS_TOPOLOGY_* define.
+ *
+ * drm_i915_gem_query_info.info_ptr will be written to with
+ * drm_i915_rcs_topology_info.
+ */
+#define I915_QUERY_INFO_RCS_TOPOLOGY	1 /* version 1 */
+
+/* Query RCS slice topology
+ *
+ * The meaning of the drm_i915_rcs_topology_info fields is :
+ *
+ * params[0]: number of slices
+ *
+ * data: Each bit indicates whether a slice is available (1) or fused off (0).
+ * Formula to tell if slice X is available :
+ *
+ *         (data[X / 8] >> (X % 8)) & 1
+ */
+#define I915_RCS_TOPOLOGY_SLICE		0 /* version 1 */
+/* Query RCS subslice topology
+ *
+ * The meaning of the drm_i915_rcs_topology_info fields is :
+ *
+ * params[0]: number of slices
+ * params[1]: slice stride
+ *
+ * data: each bit indicates whether a subslice is available (1) or fused off
+ * (0). Formula to tell if slice X subslice Y is available :
+ *
+ *         (data[(X * params[1]) + Y / 8] >> (Y % 8)) & 1
+ */
+#define I915_RCS_TOPOLOGY_SUBSLICE	1 /* version 1 */
+/* Query RCS EU topology
+ *
+ * The meaning of the drm_i915_rcs_topology_info fields is :
+ *
+ * params[0]: number of slices
+ * params[1]: slice stride
+ * params[2]: subslice stride
+ *
+ * data: Each bit indicates whether a subslice is available (1) or fused off
+ * (0). Formula to tell if slice X subslice Y eu Z is available :
+ *
+ *         (data[X * params[1] + Y * params[2] + Z / 8] >> (Z % 8)) & 1
+ */
+#define I915_RCS_TOPOLOGY_EU		2 /* version 1 */
+#endif /* I915_QUERY_INFO_RCS_TOPOLOGY */
+
+struct local_drm_i915_rcs_topology_info {
+	__u32 params[6];
+
+	__u8 data[];
+};
+
 static bool query_info_supports(int fd, int version)
 {
 	struct local_drm_i915_query_info info = {};
@@ -262,13 +328,149 @@  static void test_query_engine_exec_class_instance(int fd)
 
 }
 
+static bool query_topology_supported(int fd)
+{
+	struct local_drm_i915_query_info info = {};
+
+	info.version = 1;
+	info.query = I915_QUERY_INFO_RCS_TOPOLOGY;
+	info.query_params[0] = I915_RCS_TOPOLOGY_SLICE;
+
+	return igt_ioctl(fd, DRM_IOCTL_I915_QUERY_INFO, &info) == 0;
+}
+
+static void test_query_topology_pre_gen8(int fd)
+{
+	struct local_drm_i915_query_info info = {};
+
+	info.version = 1;
+	info.query = I915_QUERY_INFO_RCS_TOPOLOGY;
+	info.query_params[0] = I915_RCS_TOPOLOGY_SLICE;
+
+	do_ioctl_err(fd, DRM_IOCTL_I915_QUERY_INFO, &info, ENODEV);
+}
+
+static void
+test_query_topology_coherent_slice_mask(int fd)
+{
+	struct local_drm_i915_query_info info;
+	struct local_drm_i915_rcs_topology_info *topology;
+	drm_i915_getparam_t gp;
+	int slice_mask, subslice_mask;
+	int i, topology_slices, topology_subslices_slice0;
+
+	gp.param = I915_PARAM_SLICE_MASK;
+	gp.value = &slice_mask;
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	gp.param = I915_PARAM_SUBSLICE_MASK;
+	gp.value = &subslice_mask;
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	igt_debug("slice_mask=0x%x subslice_mask=0x%x\n", slice_mask, subslice_mask);
+
+	/* Slices */
+	memset(&info, 0, sizeof(info));
+	info.query = I915_QUERY_INFO_RCS_TOPOLOGY;
+	info.query_params[0] = I915_RCS_TOPOLOGY_SLICE;
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	topology = malloc(info.info_ptr_len);
+	memset(topology, 0, info.info_ptr_len);
+	info.info_ptr = to_user_pointer(topology);
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	topology_slices = 0;
+	for (i = 0; i < (topology->params[0] / 8) + 1; i++)
+		topology_slices += __builtin_popcount(topology->data[i]);
+
+	/* These 2 should always match. */
+	igt_assert(__builtin_popcount(slice_mask) == topology_slices);
+
+	free(topology);
+
+	/* Subslices */
+	memset(&info, 0, sizeof(info));
+	info.query = I915_QUERY_INFO_RCS_TOPOLOGY;
+	info.query_params[0] = I915_RCS_TOPOLOGY_SUBSLICE;
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	topology = malloc(info.info_ptr_len);
+	memset(topology, 0, info.info_ptr_len);
+	info.info_ptr = to_user_pointer(topology);
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	topology_subslices_slice0 = 0;
+	for (i = 0; i < topology->params[1]; i++)
+		topology_subslices_slice0 += __builtin_popcount(topology->data[i]);
+
+	/* I915_PARAM_SUBSLICE_MASK returns the value for slice0, we
+	 * should match the values for the first slice of the
+	 * topology.
+	 */
+	igt_assert(__builtin_popcount(subslice_mask) == topology_subslices_slice0);
+
+	free(topology);
+}
+
+static void
+test_query_topology_matches_eu_total(int fd)
+{
+	struct local_drm_i915_query_info info;
+	struct local_drm_i915_rcs_topology_info *topology;
+	drm_i915_getparam_t gp;
+	int n_eus, n_eus_topology, s;
+
+	gp.param = I915_PARAM_EU_TOTAL;
+	gp.value = &n_eus;
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	igt_debug("n_eus=%i\n", n_eus);
+
+	memset(&info, 0, sizeof(info));
+	info.query = I915_QUERY_INFO_RCS_TOPOLOGY;
+	info.query_params[0] = I915_RCS_TOPOLOGY_EU;
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	topology = malloc(info.info_ptr_len);
+	memset(topology, 0, info.info_ptr_len);
+	info.info_ptr = to_user_pointer(topology);
+	do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	n_eus_topology = 0;
+	for (s = 0; s < topology->params[0]; s++) {
+		int ss;
+
+		igt_debug("slice%i:\n", s);
+
+		for (ss = 0; ss < topology->params[1] / topology->params[2]; ss++) {
+			int eu, n_subslice_eus = 0;
+
+			igt_debug("\tsubslice: %i\n", ss);
+
+			igt_debug("\t\teu_mask:");
+			for (eu = 0; eu < topology->params[2]; eu++) {
+				uint8_t val = topology->data[s * topology->params[1] +
+							     ss * topology->params[2] + eu];
+				igt_debug(" 0x%hhx", val);
+				n_subslice_eus += __builtin_popcount(val);
+				n_eus_topology += __builtin_popcount(val);
+			}
+			igt_debug(" (%i)\n", n_subslice_eus);
+		}
+	}
+
+	igt_assert(n_eus_topology == n_eus);
+}
+
 igt_main
 {
 	int fd = -1;
+	int devid;
 
 	igt_fixture {
 		fd = drm_open_driver(DRIVER_INTEL);
 		igt_require(query_info_supports(fd, 1 /* version */));
+		devid = intel_get_drm_devid(fd);
 	}
 
 	igt_subtest("query-version")
@@ -286,6 +488,24 @@  igt_main
 	igt_subtest("query-engine-exec-class-instance")
 		test_query_engine_exec_class_instance(fd);
 
+	igt_subtest("query-topology-pre-gen8") {
+		igt_require(intel_gen(devid) < 8);
+		igt_require(query_topology_supported(fd));
+		test_query_topology_pre_gen8(fd);
+	}
+
+	igt_subtest("query-topology-coherent-slice-mask") {
+		igt_require(AT_LEAST_GEN(devid, 8));
+		igt_require(query_topology_supported(fd));
+		test_query_topology_coherent_slice_mask(fd);
+	}
+
+	igt_subtest("query-topology-matches-eu-total") {
+		igt_require(AT_LEAST_GEN(devid, 8));
+		igt_require(query_topology_supported(fd));
+		test_query_topology_matches_eu_total(fd);
+	}
+
 	igt_fixture {
 		close(fd);
 	}