[PATCH i-g-t] tests: add device information tests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We can verify that topology is consistent with previous getparam like
EU_TOTAL/SLICE_MASK/SUBSLICE_MASK.

We also verify that CS timestamp frequency is always filled.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@xxxxxxxxx>
---
 tests/Makefile.sources    |   1 +
 tests/intel_device_info.c | 324 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/meson.build         |   1 +
 3 files changed, 326 insertions(+)
 create mode 100644 tests/intel_device_info.c

diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 2313c12b..c7538cb6 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -168,6 +168,7 @@ TESTS_progs = \
 	gen3_render_tiledy_blits \
 	gen7_forcewake_mt \
 	gvt_basic \
+	intel_device_info \
 	kms_3d \
 	kms_addfb_basic \
 	kms_atomic \
diff --git a/tests/intel_device_info.c b/tests/intel_device_info.c
new file mode 100644
index 00000000..31e26cee
--- /dev/null
+++ b/tests/intel_device_info.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright © 2017 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 <stdbool.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include "igt.h"
+
+IGT_TEST_DESCRIPTION("Test device information retrieving through i915_getparam.");
+
+static int drm_fd;
+static int devid;
+
+#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_PARAM_CS_TIMESTAMP_FREQUENCY
+#define I915_PARAM_CS_TIMESTAMP_FREQUENCY   50
+#endif
+
+#ifndef I915_PARAM_EU_TOPOLOGY
+#define I915_PARAM_EU_TOPOLOGY           51
+/* List of active slices, subslices & execution units. Starting with CNL we
+ * can have asynmetric slices (for example 3 subslices in slice0 and 2
+ * subslices in slice1+). This means we cannot rely on PARAM_SUBSLICE_MASK
+ * anymore.
+ *
+ * When using this parameter, getparam value should point to a structure of
+ * type drm_i915_eus_enabled_t. Call this once with n_slices,
+ * n_subslices_per_slice, & n_eus_per_subslice set to 0 and the kernel will
+ * fill out only those fields. You can then allocate the
+ * drm_i915_eu_topology_t properly to have enough space to store the full
+ * topology.
+ */
+#define I915_PARAM_EU_TOPOLOGY           51
+typedef struct drm_i915_eu_topology {
+	uint32_t n_slices;
+	uint32_t n_subslices_per_slice;
+	uint32_t n_eus_per_subslice;
+
+	/* We define the following :
+	 *
+	 *      slice_mask_size        = ALIGN(n_slices, 8) / 8
+	 *      subslices_mask_offset  = slice_mask_size
+	 *      sublisces_mask_stride  = ALIGN(n_subslices_per_slice, 8) / 8
+	 *      subslices_mask_size    = n_slices * sublisces_mask_stride
+	 *      eu_mask_offset         = slice_mask_size + subslices_mask_size
+	 *      eu_subslice_stride     = ALIGN(n_eus_per_subslice, 8) / 8
+	 *      eu_slice_stride        = n_subslices_per_slice * eu_subslice_stride
+	 *      eu_mask_size           = n_slices * eu_slice_stride
+	 *      data_size              = slice_mask_size + subslices_mask_size + eu_mask_size
+	 *
+	 * When called with n_slices, n_subslices_per_slice &
+	 * n_eus_per_subslice filled out with the kernel values, the length of
+	 * data should be data_size.
+	 *
+	 * The kernel will write the following into data :
+	 *
+	 *  data[0 .. slice_mask_size - 1] :
+	 *
+	 *      Where each bit represent slices available.
+	 *
+	 *  data[slice_mask_offset .. slice_mask_offset + subslices_mask_size - 1] :
+	 *
+	 *      Where each bit represent the subslices available for each
+	 *      slice. Formula to tell if sliceX-subsliceY is enabled :
+	 *
+	 *           ((data[slice_mask_offset + X * sublisces_mask_stride + Y / 8] >> (Y % 8)) & 1)
+	 *
+	 *  data[eu_mask_offset .. eu_mask_offset + eu_mask_size - 1] :
+	 *
+	 *      Where each bit reports the status of one execution unit. User
+	 *      should use eu_slice_stride & eu_subslice_stride to through the
+	 *      different subslices. Formula to tell if sliceX-subsliceY-euZ
+	 *      is enabled :
+	 *
+	 *           ((data[eu_mask_offset + X * eu_slice_stride + Y * eu_subslice_stride + Z / 8] >> (Z % 8)) & 1)
+	 */
+	uint8_t data[];
+} drm_i915_eu_topology_t;
+#endif /* I915_PARAM_EU_TOPOLOGY */
+
+static bool
+topology_supported(void)
+{
+	drm_i915_eu_topology_t topology;
+	drm_i915_getparam_t gp;
+
+	memset(&topology, 0, sizeof(topology));
+	gp.param = I915_PARAM_EU_TOPOLOGY;
+	gp.value = (int *) &topology;
+
+	return ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp) == 0;
+}
+
+static void
+test_topology_pre_gen8(void)
+{
+	drm_i915_eu_topology_t topology;
+	drm_i915_getparam_t gp;
+
+	gp.param = I915_PARAM_EU_TOPOLOGY;
+	gp.value = (int *) &topology;
+	do_ioctl_err(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp, ENODEV);
+}
+
+static void
+test_topology_invalid_params(void)
+{
+	drm_i915_eu_topology_t topology;
+	drm_i915_getparam_t gp;
+
+	memset(&topology, 0, sizeof(topology));
+
+	gp.param = I915_PARAM_EU_TOPOLOGY;
+	gp.value = (int *) &topology;
+	do_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	topology.n_slices++;
+
+	gp.param = I915_PARAM_EU_TOPOLOGY;
+	gp.value = (int *) &topology;
+	do_ioctl_err(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp, EINVAL);
+}
+
+static void
+test_topology_coherent_slice_mask(void)
+{
+	drm_i915_eu_topology_t topology;
+	drm_i915_getparam_t gp;
+	int slice_mask, subslice_mask;
+
+	gp.param = I915_PARAM_SLICE_MASK;
+	gp.value = &slice_mask;
+	do_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	gp.param = I915_PARAM_SUBSLICE_MASK;
+	gp.value = &subslice_mask;
+	do_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	memset(&topology, 0, sizeof(topology));
+	gp.param = I915_PARAM_EU_TOPOLOGY;
+	gp.value = (int *) &topology;
+	do_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	igt_debug("slice_mask=0x%x subslice_mask=0x%x n_slices=%u n_subslices_per_slice=%u\n",
+		  slice_mask, subslice_mask, topology.n_slices, topology.n_subslices_per_slice);
+
+	igt_assert(__builtin_popcount(slice_mask) <= topology.n_slices);
+	igt_assert(__builtin_popcount(subslice_mask) <= topology.n_subslices_per_slice);
+}
+
+static void
+test_topology_matches_eu_total(void)
+{
+	drm_i915_eu_topology_t *topology = calloc(1, sizeof(*topology));
+	drm_i915_getparam_t gp;
+	int i, n_eus, n_eus_topology, s;
+	int slice_mask_size, subslices_mask_offset, sublisces_mask_stride,
+		subslices_mask_size, eu_mask_offset, eu_subslice_stride,
+		eu_slice_stride, eu_mask_size, data_size;
+
+	gp.param = I915_PARAM_EU_TOTAL;
+	gp.value = &n_eus;
+	do_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	igt_debug("n_eus=%i\n", n_eus);
+
+	gp.param = I915_PARAM_EU_TOPOLOGY;
+	gp.value = (int *) topology;
+	do_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	igt_debug("topology.n_slices=%i\n", topology->n_slices);
+	igt_debug("topology.n_subslices_per_slice=%i\n", topology->n_subslices_per_slice);
+	igt_debug("topology.n_eus_per_subslice=%i\n", topology->n_eus_per_subslice);
+
+	slice_mask_size = ALIGN(topology->n_slices, 8) / 8;
+	subslices_mask_offset = slice_mask_size;
+	sublisces_mask_stride = ALIGN(topology->n_subslices_per_slice, 8) / 8;
+	subslices_mask_size = topology->n_slices * sublisces_mask_stride;
+	eu_mask_offset = slice_mask_size + subslices_mask_size;
+	eu_subslice_stride = ALIGN(topology->n_eus_per_subslice, 8) / 8;
+	eu_slice_stride = topology->n_subslices_per_slice * eu_subslice_stride;
+	eu_mask_size = topology->n_slices * eu_slice_stride;
+	data_size = slice_mask_size + subslices_mask_size + eu_mask_size;
+
+	topology = realloc(topology, sizeof(*topology) + data_size);
+	memset(topology->data, 0, data_size);
+
+	gp.param = I915_PARAM_EU_TOPOLOGY;
+	gp.value = (int *) topology;
+	do_ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+
+	igt_debug("data:");
+	for (i = 0; i < data_size; i++)
+		igt_debug(" 0x%hhx", topology->data[i]);
+	igt_debug("\n");
+
+	n_eus_topology = 0;
+	for (i = eu_mask_offset; i < data_size; i++)
+		n_eus_topology += __builtin_popcount(topology->data[i]);
+
+	igt_debug("slice_mask:");
+	for (i = 0; i < slice_mask_size; i++)
+		igt_debug(" 0x%hhx", topology->data[i]);
+	igt_debug("\n");
+
+	for (s = 0; s < topology->n_slices; s++) {
+		int ss;
+
+		igt_debug("slice%i:\n", s);
+		igt_debug("\tsubslice_mask: 0x%hhx (%i)\n",
+			  topology->data[subslices_mask_offset + s],
+			  __builtin_popcount(topology->data[s]));
+
+		for (ss = 0; ss < topology->n_subslices_per_slice; ss++) {
+			int eu, n_subslice_eus = 0;
+
+			igt_debug("\tsubslice: %i\n", ss);
+
+			igt_debug("\t\teu_mask:");
+			for (eu = 0; eu < ALIGN(topology->n_eus_per_subslice, 8) / 8; eu++) {
+				uint8_t val =
+					topology->data[eu_mask_offset +
+						       s * eu_slice_stride +
+						       ss * eu_subslice_stride + eu];
+				igt_debug(" 0x%hhx", val);
+				n_subslice_eus += __builtin_popcount(val);
+			}
+			igt_debug(" (%i)\n", n_subslice_eus);
+		}
+	}
+
+	igt_assert(n_eus_topology == n_eus);
+}
+
+static void
+test_cs_timestamp_frequency(void)
+{
+	drm_i915_getparam_t gp;
+	int frequency, ret;
+
+	gp.param = I915_PARAM_CS_TIMESTAMP_FREQUENCY;
+	gp.value = &frequency;
+
+	/* Not supported? */
+	ret = ioctl(drm_fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	igt_skip_on(ret != 0);
+
+	igt_debug("cs_timestamp_frequency=%i\n", frequency);
+
+	/* This should be available on all platforms. */
+	igt_assert_neq(frequency, 0);
+}
+
+igt_main
+{
+	igt_skip_on_simulation();
+	igt_fixture {
+		drm_fd = drm_open_driver_render(DRIVER_INTEL);
+		devid = intel_get_drm_devid(drm_fd);
+	}
+
+	igt_subtest("topology-pre-gen8") {
+		igt_require(intel_gen(devid) < 8);
+		test_topology_pre_gen8();
+	}
+
+	igt_subtest("topology-invalid-params") {
+		igt_require(AT_LEAST_GEN(devid, 8));
+		igt_require(topology_supported());
+		test_topology_invalid_params();
+	}
+
+	igt_subtest("topology-coherent-slice-mask") {
+		igt_require(AT_LEAST_GEN(devid, 8));
+		igt_require(topology_supported());
+		test_topology_coherent_slice_mask();
+	}
+
+	igt_subtest("topology-matches-eu-total") {
+		igt_require(AT_LEAST_GEN(devid, 8));
+		igt_require(topology_supported());
+		test_topology_matches_eu_total();
+	}
+
+	igt_subtest("cs-timestamp-frequency") {
+		test_cs_timestamp_frequency();
+	}
+
+	igt_exit();
+}
diff --git a/tests/meson.build b/tests/meson.build
index c3d5372f..54592339 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -20,6 +20,7 @@ test_progs = [
 	'drv_module_reload',
 	'drv_selftest',
 	'drv_suspend',
+	'intel_device_info',
 	'gem_bad_reloc',
 	'gem_basic',
 	'gem_busy',
-- 
2.15.0.rc2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux