summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Makefile.sources2
-rw-r--r--lib/i915/gem_engine_topology.c282
-rw-r--r--lib/i915/gem_engine_topology.h79
-rw-r--r--lib/igt.h1
-rw-r--r--lib/igt_gt.h2
-rw-r--r--lib/meson.build1
6 files changed, 367 insertions, 0 deletions
diff --git a/lib/Makefile.sources b/lib/Makefile.sources
index 97685823..ef96bd09 100644
--- a/lib/Makefile.sources
+++ b/lib/Makefile.sources
@@ -13,6 +13,8 @@ lib_source_list = \
i915/gem_ring.c \
i915/gem_mman.c \
i915/gem_mman.h \
+ i915/gem_engine_topology.c \
+ i915/gem_engine_topology.h \
i915_3d.h \
i915_reg.h \
i915_pciids.h \
diff --git a/lib/i915/gem_engine_topology.c b/lib/i915/gem_engine_topology.c
new file mode 100644
index 00000000..7a4a1760
--- /dev/null
+++ b/lib/i915/gem_engine_topology.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright © 2019 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 "drmtest.h"
+#include "ioctl_wrappers.h"
+
+#include "i915/gem_engine_topology.h"
+
+#define DEFINE_CONTEXT_PARAM(e__, p__, c__, N__) \
+ I915_DEFINE_CONTEXT_PARAM_ENGINES(e__, N__); \
+ struct drm_i915_gem_context_param p__ = { \
+ .param = I915_CONTEXT_PARAM_ENGINES, \
+ .ctx_id = c__, \
+ .size = SIZEOF_CTX_PARAM, \
+ .value = to_user_pointer(&e__), \
+ }
+
+static int __gem_query(int fd, struct drm_i915_query *q)
+{
+ int err = 0;
+
+ if (igt_ioctl(fd, DRM_IOCTL_I915_QUERY, q))
+ err = -errno;
+
+ errno = 0;
+ return err;
+}
+
+static void gem_query(int fd, struct drm_i915_query *q)
+{
+ igt_assert_eq(__gem_query(fd, q), 0);
+}
+
+static void query_engines(int fd,
+ struct drm_i915_query_engine_info *query_engines,
+ int length)
+{
+ struct drm_i915_query_item item = { };
+ struct drm_i915_query query = { };
+
+ item.query_id = DRM_I915_QUERY_ENGINE_INFO;
+ query.items_ptr = to_user_pointer(&item);
+ query.num_items = 1;
+ item.length = length;
+
+ item.data_ptr = to_user_pointer(query_engines);
+
+ gem_query(fd, &query);
+}
+
+static void ctx_map_engines(int fd, struct intel_engine_data *ed,
+ struct drm_i915_gem_context_param *param)
+{
+ struct i915_context_param_engines *engines =
+ (struct i915_context_param_engines *) param->value;
+ int i = 0;
+
+ for (typeof(engines->engines[0]) *p =
+ &engines->engines[0];
+ i < ed->nengines; i++, p++) {
+ p->engine_class = ed->engines[i].class;
+ p->engine_instance = ed->engines[i].instance;
+ }
+
+ param->size = offsetof(typeof(*engines), engines[i]);
+ engines->extensions = 0;
+
+ gem_context_set_param(fd, param);
+}
+
+static void init_engine(struct intel_execution_engine2 *e2,
+ int class, int instance, uint64_t flags)
+{
+ const struct intel_execution_engine2 *__e2;
+ static const char *unknown_name = "unknown",
+ *virtual_name = "virtual";
+
+ e2->class = class;
+ e2->instance = instance;
+ e2->flags = flags;
+
+ /* engine is a virtual engine */
+ if (class == I915_ENGINE_CLASS_INVALID) {
+ e2->name = virtual_name;
+ e2->is_virtual = true;
+ return;
+ }
+
+ __for_each_static_engine(__e2)
+ if (__e2->class == class && __e2->instance == instance)
+ break;
+
+ if (__e2->name) {
+ e2->name = __e2->name;
+ } else {
+ igt_warn("found unknown engine (%d, %d)", class, instance);
+ e2->name = unknown_name;
+ }
+
+ /* just to remark it */
+ e2->is_virtual = false;
+}
+
+static void query_engine_list(int fd, struct intel_engine_data *ed)
+{
+ uint8_t buff[SIZEOF_QUERY] = { };
+ struct drm_i915_query_engine_info *query_engine =
+ (struct drm_i915_query_engine_info *) buff;
+ int i;
+
+ query_engines(fd, query_engine, SIZEOF_QUERY);
+
+ for (i = 0; i < query_engine->num_engines; i++)
+ init_engine(&ed->engines[i],
+ query_engine->engines[i].engine.engine_class,
+ query_engine->engines[i].engine.engine_instance, i);
+
+ ed->nengines = query_engine->num_engines;
+}
+
+struct intel_execution_engine2 *
+intel_get_current_engine(struct intel_engine_data *ed)
+{
+ if (!ed->n)
+ ed->current_engine = &ed->engines[0];
+ else if (ed->n >= ed->nengines)
+ ed->current_engine = NULL;
+
+ return ed->current_engine;
+}
+
+void intel_next_engine(struct intel_engine_data *ed)
+{
+ if (ed->n + 1 < ed->nengines) {
+ ed->n++;
+ ed->current_engine = &ed->engines[ed->n];
+ } else {
+ ed->n = ed->nengines;
+ ed->current_engine = NULL;
+ }
+}
+
+struct intel_execution_engine2 *
+intel_get_current_physical_engine(struct intel_engine_data *ed)
+{
+ struct intel_execution_engine2 *e;
+
+ for (e = intel_get_current_engine(ed);
+ e && e->is_virtual;
+ intel_next_engine(ed))
+ ;
+
+ return e;
+}
+
+static int gem_topology_get_param(int fd,
+ struct drm_i915_gem_context_param *p)
+{
+ if (igt_only_list_subtests())
+ return -ENODEV;
+
+ if (__gem_context_get_param(fd, p))
+ return -1; /* using default engine map */
+
+ if (!p->size)
+ return 0;
+
+ p->size = (p->size - sizeof(struct i915_context_param_engines)) /
+ (offsetof(struct i915_context_param_engines,
+ engines[1]) -
+ sizeof(struct i915_context_param_engines));
+
+ igt_assert_f(p->size <= GEM_MAX_ENGINES, "unsupported engine count\n");
+
+ return 0;
+}
+
+struct intel_engine_data intel_init_engine_list(int fd, uint32_t ctx_id)
+{
+ DEFINE_CONTEXT_PARAM(engines, param, ctx_id, GEM_MAX_ENGINES);
+ struct intel_engine_data engine_data = { };
+ int i;
+
+ if (gem_topology_get_param(fd, &param)) {
+ /* if kernel does not support engine/context mapping */
+ const struct intel_execution_engine2 *e2;
+
+ igt_debug("using pre-allocated engine list\n");
+
+ __for_each_static_engine(e2) {
+ struct intel_execution_engine2 *__e2 =
+ &engine_data.engines[engine_data.nengines];
+
+ if (!igt_only_list_subtests()) {
+ __e2->flags = gem_class_instance_to_eb_flags(fd,
+ e2->class, e2->instance);
+
+ if (!gem_has_ring(fd, __e2->flags))
+ continue;
+ } else {
+ __e2->flags = -1; /* 0xfff... */
+ }
+
+ __e2->name = e2->name;
+ __e2->instance = e2->instance;
+ __e2->class = e2->class;
+ __e2->is_virtual = false;
+
+ engine_data.nengines++;
+ }
+ return engine_data;
+ }
+
+ if (!param.size) {
+ query_engine_list(fd, &engine_data);
+ ctx_map_engines(fd, &engine_data, &param);
+ } else {
+ for (i = 0; i < param.size; i++)
+ init_engine(&engine_data.engines[i],
+ engines.engines[i].engine_class,
+ engines.engines[i].engine_instance,
+ i);
+
+ engine_data.nengines = i;
+ }
+
+ return engine_data;
+}
+
+int gem_context_lookup_engine(int fd, uint64_t engine, uint32_t ctx_id,
+ struct intel_execution_engine2 *e)
+{
+ DEFINE_CONTEXT_PARAM(engines, param, ctx_id, GEM_MAX_ENGINES);
+
+ if (!e || gem_topology_get_param(fd, &param) || !param.size)
+ return -EINVAL;
+
+ e->class = engines.engines[engine].engine_class;
+ e->instance = engines.engines[engine].engine_instance;
+
+ return 0;
+}
+
+void gem_context_set_all_engines(int fd, uint32_t ctx)
+{
+ DEFINE_CONTEXT_PARAM(engines, param, ctx, GEM_MAX_ENGINES);
+ struct intel_engine_data engine_data = { };
+
+ if (!gem_topology_get_param(fd, &param) && !param.size) {
+ query_engine_list(fd, &engine_data);
+ ctx_map_engines(fd, &engine_data, &param);
+ }
+}
+
+bool gem_has_engine_topology(int fd)
+{
+ struct drm_i915_gem_context_param param = {
+ .param = I915_CONTEXT_PARAM_ENGINES,
+ };
+
+ return !__gem_context_get_param(fd, &param);
+}
diff --git a/lib/i915/gem_engine_topology.h b/lib/i915/gem_engine_topology.h
new file mode 100644
index 00000000..b40204b1
--- /dev/null
+++ b/lib/i915/gem_engine_topology.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2019 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.
+ */
+
+#ifndef GEM_ENGINE_TOPOLOGY_H
+#define GEM_ENGINE_TOPOLOGY_H
+
+#include "igt_gt.h"
+#include "i915_drm.h"
+
+/*
+ * Limit what we support for simplicity due limitation in how much we
+ * can address via execbuf2.
+ */
+#define SIZEOF_CTX_PARAM offsetof(struct i915_context_param_engines, \
+ engines[GEM_MAX_ENGINES])
+#define SIZEOF_QUERY offsetof(struct drm_i915_query_engine_info, \
+ engines[GEM_MAX_ENGINES])
+
+#define GEM_MAX_ENGINES I915_EXEC_RING_MASK + 1
+
+struct intel_engine_data {
+ uint32_t nengines;
+ uint32_t n;
+ struct intel_execution_engine2 *current_engine;
+ struct intel_execution_engine2 engines[GEM_MAX_ENGINES];
+};
+
+bool gem_has_engine_topology(int fd);
+struct intel_engine_data intel_init_engine_list(int fd, uint32_t ctx_id);
+
+/* iteration functions */
+struct intel_execution_engine2 *
+intel_get_current_engine(struct intel_engine_data *ed);
+
+struct intel_execution_engine2 *
+intel_get_current_physical_engine(struct intel_engine_data *ed);
+
+void intel_next_engine(struct intel_engine_data *ed);
+
+int gem_context_lookup_engine(int fd, uint64_t engine, uint32_t ctx_id,
+ struct intel_execution_engine2 *e);
+
+void gem_context_set_all_engines(int fd, uint32_t ctx);
+
+#define __for_each_static_engine(e__) \
+ for ((e__) = intel_execution_engines2; (e__)->name; (e__)++)
+
+#define for_each_context_engine(fd__, ctx__, e__) \
+ for (struct intel_engine_data i__ = intel_init_engine_list(fd__, ctx__); \
+ ((e__) = intel_get_current_engine(&i__)); \
+ intel_next_engine(&i__))
+
+/* needs to replace "for_each_physical_engine" when conflicts are fixed */
+#define __for_each_physical_engine(fd__, e__) \
+ for (struct intel_engine_data i__ = intel_init_engine_list(fd__, 0); \
+ ((e__) = intel_get_current_physical_engine(&i__)); \
+ intel_next_engine(&i__))
+
+#endif /* GEM_ENGINE_TOPOLOGY_H */
diff --git a/lib/igt.h b/lib/igt.h
index 5852d557..a3d3edc2 100644
--- a/lib/igt.h
+++ b/lib/igt.h
@@ -54,5 +54,6 @@
#include "media_spin.h"
#include "rendercopy.h"
#include "i915/gem_mman.h"
+#include "i915/gem_engine_topology.h"
#endif /* IGT_H */
diff --git a/lib/igt_gt.h b/lib/igt_gt.h
index 475c0b3c..52b2f1ea 100644
--- a/lib/igt_gt.h
+++ b/lib/igt_gt.h
@@ -95,6 +95,8 @@ extern const struct intel_execution_engine2 {
const char *name;
int class;
int instance;
+ uint64_t flags;
+ bool is_virtual;
} intel_execution_engines2[];
unsigned int
diff --git a/lib/meson.build b/lib/meson.build
index 786e7a26..7375f98b 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -5,6 +5,7 @@ lib_sources = [
'i915/gem_submission.c',
'i915/gem_ring.c',
'i915/gem_mman.c',
+ 'i915/gem_engine_topology.c',
'igt_color_encoding.c',
'igt_debugfs.c',
'igt_device.c',