All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH v19 0/6] new engine discovery interface
@ 2019-04-08 16:15 Andi Shyti
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file Andi Shyti
                   ` (8 more replies)
  0 siblings, 9 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:15 UTC (permalink / raw)
  To: IGT dev; +Cc: Andi Shyti

Hi,

In this patchset I propose an alternative way of engine discovery
thanks to the new interfaces developed by Tvrtko and Chris[4].

The changes to perf_pmu are a proposal, most probably they don't
work (it's anyway an RFC) because the dependency to legacy code
is still too strong.

Thanks Tvrtko, Chris, Antonio and Petri for your comments in the
previous RFCs.

Andi

v18 --> v19
===========
 - integrated Tvrtko's fixup patch [17]. From this patch some
   changes have been moved to gem_engine_topology as a new helper
   for getting the engine's properties.

v17 --> v18
===========
 - three patches have been applied (the ones that add
   gem_context_has_engine() function)
 - few cosmetic fixes
 - and some changes coming from Tvrtko's review on v17

v16 --> v17
===========
amongst many little things, three main changes:
 - improved perf_pmu adaptation to gem_engine_topology
 - removed the exec-ctx test, perf_pmu will be the flag test
 - when creating the engine list, now the
   for_each_engine_physical can be executed safely during subtest
   listing

v15 --> v16
===========
 - few changes to the gem_engine_topology stuff
 - added une more dummy test which loops through the physical
   engines, as well.
 - changes to test/perf_pmu required some more changes than
   expected (the 3 last patches)

v14 --> v15
===========
PATCH v14: [16]

 - virtual engines will be called "virtual" like unrecognised
   engines will be called "unknown"

 - renamed the for_each loops to more meaningful names
   (__for_each_static_engine and for_each_context_engine) and
   moved into gem_engine_topology.h

 - minor changes about data types.

v13 --> v14
===========
PATCH v13: [15]
minor changes this time:
 - squashed patch 2 and 3 (from v13) with a little rename and
   added Chris r-b

 - fixed some index issues and string assignement leaks

 - squashed patches 5, 6, 7 and 8 from v13

v12 --> v13
===========
PATCH v12: [14]
This patch is also very different from the previous other than
some reorganization of the code these are the main changes:

 - the previous version lacked the case when the context had its
   engines mapped. checks in the following order

 if the driver doesn't have the new API
  -> get the engines from the static list
 if the driver has the API but the context has nothing mapped
  -> get the engines from "query" and map them
 if the driver has the API and the context has engines mapped
  -> get the engines from the context

 - the helper functions have been removed as they were of no use.

v11 --> v12
===========
PATCH v11: [13]
This 12th version starts from a completely different thought.
Here's the main differences:

 - The list of engines is provided in an engine_data structure
   which contains an index (useful for looping through and for
   engine/context index mapping) instead of an array of engines.

 - The list of engines is generated every time the init function
   is called and nothing is allocated in heap memory.

 - The ioctl check is done already during the initialization part
   and if the new ioctls are not implemented, then the init
   function still stores only those present in the GPU.

 - The for_each loop is implemented by re-using the previous
   'for_each_engine_class_instance()' implemented by Tvrtko.

 - The gem_topology library offers few helper functions for
   checking the engine presence, checking the implementation of
   the ioctls and executing the buffer, in order to be completely
   unaware of the driver implementation.

Thanks Tvrtko for all your inputs.

v10 --> v11
===========
RFC v10: [12]
few cosmetic changes in v11 and minor architectural details.
Thanks Tvrtko.

- the 'query_engines()' functions are static as no one is using
  them yet.

- removed the 'gem_has_engine_topology()' function because it's
  very little used, 'get_active_engines()' can be used instead.

- a minor ring -> engine renaming coming from Chris. 

v9 --> v10
==========
RFC v9: [11]
also this time quite many changes, thanks Chris for the reviews,
here the most relevant of them.

- gem_query.[ch] have been renamed to gem_engine_topology.[ch]
  and all the functions ended up there as they are referring to
  the topology of the engines.

- the functions 'get_active_engines()',
  'gem_set_context_get_engines()' and
  'igt_require_gem_engine_list()' will be the main interface to
  the gem_engine_topology library, refer to patch 2 for details.

- the define 'for_each_engine2()' doesn't expose anymore the
  iterator.

- 'gem_context_has_engine()' has been moved from ioctl_wrappers.c
  to gem_context.c.

- the gem_exec_basic exec-ctx subtest does not abort if the new
  getparam/setparam and query apis are not implemented as it can
  work with both (as it was done at the beginning).

v8 --> v9
=========
RFC v8: [10]
quite many changes, please refer to the review in [10]. Thanks
Chris for the review. These are the most relevant:

- all the allocation in gem_query have been made in stack, not
  anymore allocated dynamically.

- removed get/set_context as it was already implemented and I
  didn't know.

- renamed some functions and variables to hopefully more
  meaningful names.

V7 --> v8
=========
RFC v7: [9]

- all functions have been moved from lib/igt_gt.{c,h} and
  lib/ioctl_wrappers.{c,h} to lib/i916/gem_query.{c,h}. (thanks
  Chris)

- 'for_each_engine_ctx' has been renamed to 'for_each_engine2' to
  be consistent with the '2' that indicates the new 'struct
  intel_execution_engine2' data structure.

V6 --> V7
=========
RFC v6: [8]

- a new patch has been added (patch 3) which adds a new
  requirement check through the igt_require_gem_engine_list()
  function. (thanks Chris) This function will initialize the
  engine list instead of the instead of igt_require_gem() as it
  was in v6

- all the ioctls have been wrapped (thanks Chris and Antonio) and
  new library functions have been added and assert the ioctls

- gem_init_engine_list() function returns the errno from the
  GETPARAM ioctl in order to be used as a requirement. (thanks
  Chris)

- fixed few requires/asserts

- The engine list "intel_active_engines2" is allocated of the
  number of engines instead of a political 64 (thanks Antonio).

- some parameter renaming in gem_has_ring_by_idx(). (thanks
  Chris).

- the original "intel_execution_engines2" has not been renamed,
  because it is used to create subtests before even executing any
  test/ioctl. By renaming it, some subtest generations failed.
  (thanks Petri)

V5 --> V6
=========
RFC v5: [7]
- Chris implemented the getparam ioctl which allows to the test
  to figure otu whether the new interface has been implemented.
  This way the for_each_engine_ctx() is able to work with new and
  old kernel uapi (thanks Chris)

V4 --> V5
=========
RFC v4: [6]

- the engine list is now built in 'igt_require_gem()' instead of
  '__open_driver()' so that we keep this discovery method
  specific to the i915 driver (thanks Chris).

- All the query/setparam structures dynamic allocation based on
  the number of engines, now are politically allocated 64 times,
  to avoid extra ioctl calls that retrieve the engine number
  (thanks Chris)

- use igt_ioctl instead of ioctl (thanks Chris)

- allocate intel_execution_engines2 dynamically instead of
  statically (thanks Tvrtko)

- simplify the test in 'gem_exec_basic()' so that simply checks
  the presence of the engine instead of executing a buffer
  (thank Chris)

- a new patch has been added (patch 3) that extends the
  'gem_has_ring()' boolean function. The new version sets the
  index as it's mapped in the kernel.The previous function is now
  a wrapper to the new function.

V3 --> V4
=========
PATCH v3: [3]

- re-architectured the discovery mechanism based on Tvrtko's
  sugestion and reviews.. In this version the discovery is done
  during the device opening and stored in a NULL terminated
  array, which replaces the existing intel_execution_engines2
  that is mainly used as a reference.

V2 --> V3
=========
RFC v2: [2]

- removed a standalone gem_query_engines_demo test and added the
  exec-ctx subtest inside gem_exec_basic (thanks Tvrtko).

- fixed most of Tvrtko's comments in [5], which consist in
  putting the mallocs igt_assert and ictls in igt_require and few
  refactoring (thanks Tvrtko).

V1 --> V2
=========
RFC v1: [1]

- added a demo test that simply queries the driver about the
  engines and executes a buffer (thanks Tvrtko)

- refactored the for_each_engine_ctx() macro so that what in the
  previous version was done by the "bind" function, now it's done
  in the first iteration. (Thanks Crhis)

- removed the "gem_has_ring_ctx()" because it was out of the
  scope.

- rename functions to more meaningful names

[1] RFC v1: https://lists.freedesktop.org/archives/igt-dev/2018-November/007025.html
[2] RFC v2: https://lists.freedesktop.org/archives/igt-dev/2018-November/007079.html
[3] PATCH v3: https://lists.freedesktop.org/archives/igt-dev/2018-November/007148.html
[4] https://cgit.freedesktop.org/~tursulin/drm-intel/log/?h=media
[5] https://lists.freedesktop.org/archives/igt-dev/2018-November/007100.html
[6] https://lists.freedesktop.org/archives/igt-dev/2019-January/008029.html
[7] https://lists.freedesktop.org/archives/igt-dev/2019-January/008165.html
[8] https://lists.freedesktop.org/archives/igt-dev/2019-February/008902.html
[9] https://lists.freedesktop.org/archives/igt-dev/2019-February/009185.html
[10] https://lists.freedesktop.org/archives/igt-dev/2019-February/009205.html
[11] https://lists.freedesktop.org/archives/igt-dev/2019-February/009277.html
[12] https://lists.freedesktop.org/archives/igt-dev/2019-March/010197.html
[13] https://lists.freedesktop.org/archives/igt-dev/2019-March/010467.html
[14] https://lists.freedesktop.org/archives/igt-dev/2019-March/010776.html
[15] https://lists.freedesktop.org/archives/igt-dev/2019-March/010827.html
[16] https://lists.freedesktop.org/archives/igt-dev/2019-March/010916.html
[17] https://lists.freedesktop.org/archives/igt-dev/2019-April/011821.html

Andi Shyti (6):
  include/drm-uapi: import i915_drm.h header file
  lib/i915: add gem_engine_topology library and for_each loop definition
  lib: igt_gt: add eb flags to class helper
  lib: igt_gt: make gem_engine_can_store_dword() check engine class
  lib: igt_dummyload: use for_each_context_engine()
  test: perf_pmu: use the gem_engine_topology library

 include/drm-uapi/i915_drm.h    | 361 +++++++++++++++++++++++++++------
 lib/Makefile.sources           |   2 +
 lib/i915/gem_engine_topology.c | 281 +++++++++++++++++++++++++
 lib/i915/gem_engine_topology.h |  78 +++++++
 lib/igt.h                      |   1 +
 lib/igt_dummyload.c            |  34 ++--
 lib/igt_gt.c                   |  29 ++-
 lib/igt_gt.h                   |  12 +-
 lib/meson.build                |   1 +
 tests/perf_pmu.c               | 143 ++++++++-----
 10 files changed, 807 insertions(+), 135 deletions(-)
 create mode 100644 lib/i915/gem_engine_topology.c
 create mode 100644 lib/i915/gem_engine_topology.h

-- 
2.20.1

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

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

* [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
@ 2019-04-08 16:15 ` Andi Shyti
  2019-04-08 16:37   ` Tvrtko Ursulin
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition Andi Shyti
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:15 UTC (permalink / raw)
  To: IGT dev; +Cc: Andi Shyti

This header file is imported in order to include the two new
ioctls DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM,
DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM and DRM_IOCTL_I915_QUERY.

Signed-off-by: Andi Shyti <andi.shyti@intel.com>
---
 include/drm-uapi/i915_drm.h | 361 ++++++++++++++++++++++++++++++------
 1 file changed, 304 insertions(+), 57 deletions(-)

diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
index 4ae1c6ff6ae6..2bbad08eb9d2 100644
--- a/include/drm-uapi/i915_drm.h
+++ b/include/drm-uapi/i915_drm.h
@@ -62,6 +62,26 @@ extern "C" {
 #define I915_ERROR_UEVENT		"ERROR"
 #define I915_RESET_UEVENT		"RESET"
 
+/*
+ * i915_user_extension: Base class for defining a chain of extensions
+ *
+ * Many interfaces need to grow over time. In most cases we can simply
+ * extend the struct and have userspace pass in more data. Another option,
+ * as demonstrated by Vulkan's approach to providing extensions for forward
+ * and backward compatibility, is to use a list of optional structs to
+ * provide those extra details.
+ *
+ * The key advantage to using an extension chain is that it allows us to
+ * redefine the interface more easily than an ever growing struct of
+ * increasing complexity, and for large parts of that interface to be
+ * entirely optional. The downside is more pointer chasing; chasing across
+ * the boundary with pointers encapsulated inside u64.
+ */
+struct i915_user_extension {
+	__u64 next_extension;
+	__u64 name;
+};
+
 /*
  * MOCS indexes used for GPU surfaces, defining the cacheability of the
  * surface data and the coherency for this data wrt. CPU vs. GPU accesses.
@@ -104,6 +124,9 @@ enum drm_i915_gem_engine_class {
 	I915_ENGINE_CLASS_INVALID	= -1
 };
 
+#define I915_ENGINE_CLASS_INVALID_NONE -1
+#define I915_ENGINE_CLASS_INVALID_VIRTUAL 0
+
 /**
  * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
  *
@@ -321,6 +344,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_PERF_ADD_CONFIG	0x37
 #define DRM_I915_PERF_REMOVE_CONFIG	0x38
 #define DRM_I915_QUERY			0x39
+#define DRM_I915_GEM_VM_CREATE		0x3a
+#define DRM_I915_GEM_VM_DESTROY		0x3b
 /* Must be kept compact -- no holes */
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
@@ -370,6 +395,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
 #define DRM_IOCTL_I915_GEM_WAIT		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
 #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
+#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext)
 #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
 #define DRM_IOCTL_I915_REG_READ			DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
 #define DRM_IOCTL_I915_GET_RESET_STATS		DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
@@ -380,6 +406,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_PERF_ADD_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
 #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
 #define DRM_IOCTL_I915_QUERY			DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
+#define DRM_IOCTL_I915_GEM_VM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
+#define DRM_IOCTL_I915_GEM_VM_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -563,6 +591,12 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_MMAP_GTT_COHERENT	52
 
+/*
+ * Query whether DRM_I915_GEM_EXECBUFFER2 supports coordination of parallel
+ * execution through use of explicit fence support.
+ * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
+ */
+#define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
 /* Must be kept compact -- no holes and well documented */
 
 typedef struct drm_i915_getparam {
@@ -1085,7 +1119,16 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_FENCE_ARRAY   (1<<19)
 
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
+/*
+ * Setting I915_EXEC_FENCE_SUBMIT implies that lower_32_bits(rsvd2) represent
+ * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
+ * the batch.
+ *
+ * Returns -EINVAL if the sync_file fd cannot be found.
+ */
+#define I915_EXEC_FENCE_SUBMIT		(1 << 20)
+
+#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
 
 #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
 #define i915_execbuffer2_set_context_id(eb2, context) \
@@ -1421,65 +1464,18 @@ struct drm_i915_gem_wait {
 };
 
 struct drm_i915_gem_context_create {
-	/*  output: id of new context*/
-	__u32 ctx_id;
-	__u32 pad;
-};
-
-struct drm_i915_gem_context_destroy {
-	__u32 ctx_id;
-	__u32 pad;
-};
-
-struct drm_i915_reg_read {
-	/*
-	 * Register offset.
-	 * For 64bit wide registers where the upper 32bits don't immediately
-	 * follow the lower 32bits, the offset of the lower 32bits must
-	 * be specified
-	 */
-	__u64 offset;
-#define I915_REG_READ_8B_WA (1ul << 0)
-
-	__u64 val; /* Return value */
-};
-/* Known registers:
- *
- * Render engine timestamp - 0x2358 + 64bit - gen7+
- * - Note this register returns an invalid value if using the default
- *   single instruction 8byte read, in order to workaround that pass
- *   flag I915_REG_READ_8B_WA in offset field.
- *
- */
-
-struct drm_i915_reset_stats {
-	__u32 ctx_id;
-	__u32 flags;
-
-	/* All resets since boot/module reload, for all contexts */
-	__u32 reset_count;
-
-	/* Number of batches lost when active in GPU, for this context */
-	__u32 batch_active;
-
-	/* Number of batches lost pending for execution, for this context */
-	__u32 batch_pending;
-
+	__u32 ctx_id; /* output: id of new context*/
 	__u32 pad;
 };
 
-struct drm_i915_gem_userptr {
-	__u64 user_ptr;
-	__u64 user_size;
+struct drm_i915_gem_context_create_ext {
+	__u32 ctx_id; /* output: id of new context*/
 	__u32 flags;
-#define I915_USERPTR_READ_ONLY 0x1
-#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
-	/**
-	 * Returned handle for the object.
-	 *
-	 * Object handles are nonzero.
-	 */
-	__u32 handle;
+#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS	(1u << 0)
+#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE	(1u << 1)
+#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \
+	(-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1))
+	__u64 extensions;
 };
 
 struct drm_i915_gem_context_param {
@@ -1520,7 +1516,43 @@ struct drm_i915_gem_context_param {
  * On creation, all new contexts are marked as recoverable.
  */
 #define I915_CONTEXT_PARAM_RECOVERABLE	0x8
+
+	/*
+	 * The id of the associated virtual memory address space (ppGTT) of
+	 * this context. Can be retrieved and passed to another context
+	 * (on the same fd) for both to use the same ppGTT and so share
+	 * address layouts, and avoid reloading the page tables on context
+	 * switches between themselves.
+	 *
+	 * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY.
+	 */
+#define I915_CONTEXT_PARAM_VM		0x9
+
+/*
+ * I915_CONTEXT_PARAM_ENGINES:
+ *
+ * Bind this context to operate on this subset of available engines. Henceforth,
+ * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as
+ * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0]
+ * and upwards. Slots 0...N are filled in using the specified (class, instance).
+ * Use
+ *	engine_class: I915_ENGINE_CLASS_INVALID,
+ *	engine_instance: I915_ENGINE_CLASS_INVALID_NONE
+ * to specify a gap in the array that can be filled in later, e.g. by a
+ * virtual engine used for load balancing.
+ *
+ * Setting the number of engines bound to the context to 0, by passing a zero
+ * sized argument, will revert back to default settings.
+ *
+ * See struct i915_context_param_engines.
+ *
+ * Extensions:
+ *   i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE)
+ *   i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
+ */
+#define I915_CONTEXT_PARAM_ENGINES	0xa
 /* Must be kept compact -- no holes and well documented */
+
 	__u64 value;
 };
 
@@ -1553,9 +1585,10 @@ struct drm_i915_gem_context_param_sseu {
 	__u16 engine_instance;
 
 	/*
-	 * Unused for now. Must be cleared to zero.
+	 * Unknown flags must be cleared to zero.
 	 */
 	__u32 flags;
+#define I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX (1u << 0)
 
 	/*
 	 * Mask of slices to enable for the context. Valid values are a subset
@@ -1583,6 +1616,175 @@ struct drm_i915_gem_context_param_sseu {
 	__u32 rsvd;
 };
 
+/*
+ * i915_context_engines_load_balance:
+ *
+ * Enable load balancing across this set of engines.
+ *
+ * Into the I915_EXEC_DEFAULT slot [0], a virtual engine is created that when
+ * used will proxy the execbuffer request onto one of the set of engines
+ * in such a way as to distribute the load evenly across the set.
+ *
+ * The set of engines must be compatible (e.g. the same HW class) as they
+ * will share the same logical GPU context and ring.
+ *
+ * To intermix rendering with the virtual engine and direct rendering onto
+ * the backing engines (bypassing the load balancing proxy), the context must
+ * be defined to use a single timeline for all engines.
+ */
+struct i915_context_engines_load_balance {
+	struct i915_user_extension base;
+
+	__u16 engine_index;
+	__u16 mbz16; /* reserved for future use; must be zero */
+	__u32 flags; /* all undefined flags must be zero */
+
+	__u64 engines_mask; /* selection mask of engines[] */
+
+	__u64 mbz64[4]; /* reserved for future use; must be zero */
+};
+
+/*
+ * i915_context_engines_bond:
+ *
+ */
+struct i915_context_engines_bond {
+	struct i915_user_extension base;
+
+	__u16 engine_index;
+	__u16 mbz;
+
+	__u16 master_class;
+	__u16 master_instance;
+
+	__u64 sibling_mask;
+	__u64 flags; /* all undefined flags must be zero */
+};
+
+struct i915_context_param_engines {
+	__u64 extensions; /* linked chain of extension blocks, 0 terminates */
+#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0
+#define I915_CONTEXT_ENGINES_EXT_BOND 1
+
+	struct {
+		__u16 engine_class; /* see enum drm_i915_gem_engine_class */
+		__u16 engine_instance;
+	} class_instance[0];
+} __attribute__((packed));
+
+#define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \
+	__u64 extensions; \
+	struct { \
+		__u16 engine_class; \
+		__u16 engine_instance; \
+	} class_instance[N__]; \
+} __attribute__((packed)) name__
+
+struct drm_i915_gem_context_create_ext_setparam {
+#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
+	struct i915_user_extension base;
+	struct drm_i915_gem_context_param setparam;
+};
+
+struct drm_i915_gem_context_create_ext_clone {
+#define I915_CONTEXT_CREATE_EXT_CLONE 1
+	struct i915_user_extension base;
+	__u32 clone_id;
+	__u32 flags;
+#define I915_CONTEXT_CLONE_FLAGS	(1u << 0)
+#define I915_CONTEXT_CLONE_SCHED	(1u << 1)
+#define I915_CONTEXT_CLONE_SSEU		(1u << 2)
+#define I915_CONTEXT_CLONE_TIMELINE	(1u << 3)
+#define I915_CONTEXT_CLONE_VM		(1u << 4)
+#define I915_CONTEXT_CLONE_ENGINES	(1u << 5)
+#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_ENGINES << 1)
+	__u64 rsvd;
+};
+
+struct drm_i915_gem_context_destroy {
+	__u32 ctx_id;
+	__u32 pad;
+};
+
+/*
+ * DRM_I915_GEM_VM_CREATE -
+ *
+ * Create a new virtual memory address space (ppGTT) for use within a context
+ * on the same file. Extensions can be provided to configure exactly how the
+ * address space is setup upon creation.
+ *
+ * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is
+ * returned in the outparam @id.
+ *
+ * No flags are defined, with all bits reserved and must be zero.
+ *
+ * An extension chain maybe provided, starting with @extensions, and terminated
+ * by the @next_extension being 0. Currently, no extensions are defined.
+ *
+ * DRM_I915_GEM_VM_DESTROY -
+ *
+ * Destroys a previously created VM id, specified in @id.
+ *
+ * No extensions or flags are allowed currently, and so must be zero.
+ */
+struct drm_i915_gem_vm_control {
+	__u64 extensions;
+	__u32 flags;
+	__u32 id;
+};
+
+struct drm_i915_reg_read {
+	/*
+	 * Register offset.
+	 * For 64bit wide registers where the upper 32bits don't immediately
+	 * follow the lower 32bits, the offset of the lower 32bits must
+	 * be specified
+	 */
+	__u64 offset;
+#define I915_REG_READ_8B_WA (1ul << 0)
+
+	__u64 val; /* Return value */
+};
+
+/* Known registers:
+ *
+ * Render engine timestamp - 0x2358 + 64bit - gen7+
+ * - Note this register returns an invalid value if using the default
+ *   single instruction 8byte read, in order to workaround that pass
+ *   flag I915_REG_READ_8B_WA in offset field.
+ *
+ */
+
+struct drm_i915_reset_stats {
+	__u32 ctx_id;
+	__u32 flags;
+
+	/* All resets since boot/module reload, for all contexts */
+	__u32 reset_count;
+
+	/* Number of batches lost when active in GPU, for this context */
+	__u32 batch_active;
+
+	/* Number of batches lost pending for execution, for this context */
+	__u32 batch_pending;
+
+	__u32 pad;
+};
+
+struct drm_i915_gem_userptr {
+	__u64 user_ptr;
+	__u64 user_size;
+	__u32 flags;
+#define I915_USERPTR_READ_ONLY 0x1
+#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
+	/**
+	 * Returned handle for the object.
+	 *
+	 * Object handles are nonzero.
+	 */
+	__u32 handle;
+};
+
 enum drm_i915_oa_format {
 	I915_OA_FORMAT_A13 = 1,	    /* HSW only */
 	I915_OA_FORMAT_A29,	    /* HSW only */
@@ -1744,6 +1946,7 @@ struct drm_i915_perf_oa_config {
 struct drm_i915_query_item {
 	__u64 query_id;
 #define DRM_I915_QUERY_TOPOLOGY_INFO    1
+#define DRM_I915_QUERY_ENGINE_INFO	2
 /* Must be kept compact -- no holes and well documented */
 
 	/*
@@ -1842,6 +2045,50 @@ struct drm_i915_query_topology_info {
 	__u8 data[];
 };
 
+/**
+ * struct drm_i915_engine_info
+ *
+ * Describes one engine and it's capabilities as known to the driver.
+ */
+struct drm_i915_engine_info {
+	/** Engine class as in enum drm_i915_gem_engine_class. */
+	__u16 engine_class;
+
+	/** Engine instance number. */
+	__u16 engine_instance;
+
+	/** Reserved field. */
+	__u32 rsvd0;
+
+	/** Engine flags. */
+	__u64 flags;
+
+	/** Capabilities of this engine. */
+	__u64 capabilities;
+#define I915_VIDEO_CLASS_CAPABILITY_HEVC		(1 << 0)
+#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC	(1 << 1)
+
+	/** Reserved fields. */
+	__u64 rsvd1[4];
+};
+
+/**
+ * struct drm_i915_query_engine_info
+ *
+ * Engine info query enumerates all engines known to the driver by filling in
+ * an array of struct drm_i915_engine_info structures.
+ */
+struct drm_i915_query_engine_info {
+	/** Number of struct drm_i915_engine_info structs following. */
+	__u32 num_engines;
+
+	/** MBZ */
+	__u32 rsvd[3];
+
+	/** Marker for drm_i915_engine_info structures. */
+	struct drm_i915_engine_info engines[];
+};
+
 #if defined(__cplusplus)
 }
 #endif
-- 
2.20.1

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

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

* [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file Andi Shyti
@ 2019-04-08 16:15 ` Andi Shyti
  2019-04-08 16:54   ` Tvrtko Ursulin
  2019-04-11 16:03   ` Tvrtko Ursulin
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 3/6] lib: igt_gt: add eb flags to class helper Andi Shyti
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:15 UTC (permalink / raw)
  To: IGT dev; +Cc: Andi Shyti

The gem_engine_topology library is a set of functions that
interface with the query and getparam/setparam ioctls.

The library's access point is the 'intel_init_engine_list()'
function that, everytime is called, generates the list of active
engines and returns them in a 'struct intel_engine_data'. The
structure contains only the engines that are actively present in
the GPU.

The function can work in both the cases that the query and
getparam ioctls are implemented or not by the running kernel. In
case they are implemented, a query is made to the driver to fetch
the list of active engines. In case they are not implemented, the
list is taken from the 'intel_execution_engines2' array and
stored only after checking their presence.

The gem_engine_topology library provides some iteration helpers:

 - intel_get_current_engine(): provides the current engine in the
   iteration.

 - intel_get_current_physical_engine(): provides the current
   physical engine, if the current engine is a virtual engine,
   it moves forward until it finds a physical engine.

 - intel_next_engine() it just increments the counter so that it
   points to the next engine.

Extend the 'for_each_engine_class_instance' so that it can loop
using the new 'intel_init_engine_list()' and rename it to
'for_each_context_engine'.

Move '__for_each_engine_class_instance' to gem_engine_topology.h
and rename it to '__for_each_static_engine'.

Update accordingly tests/perf_pmu.c to use correctly the new
for_each loops.

Signed-off-by: Andi Shyti <andi.shyti@intel.com>
---
 lib/Makefile.sources           |   2 +
 lib/i915/gem_engine_topology.c | 281 +++++++++++++++++++++++++++++++++
 lib/i915/gem_engine_topology.h |  78 +++++++++
 lib/igt.h                      |   1 +
 lib/igt_gt.h                   |   2 +
 lib/meson.build                |   1 +
 6 files changed, 365 insertions(+)
 create mode 100644 lib/i915/gem_engine_topology.c
 create mode 100644 lib/i915/gem_engine_topology.h

diff --git a/lib/Makefile.sources b/lib/Makefile.sources
index e00347f945c5..41331c2f2b80 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 000000000000..06f538372a4d
--- /dev/null
+++ b/lib/i915/gem_engine_topology.c
@@ -0,0 +1,281 @@
+/*
+ * 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"
+
+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->class_instance[0]) *p =
+	     &engines->class_instance[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), class_instance[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_class,
+			    query_engine->engines[i].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->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, uint32_t ctx,
+				  struct drm_i915_gem_context_param *p)
+{
+	int nengines;
+	int ret;
+
+	if (igt_only_list_subtests())
+		return -EPERM;
+
+	ret = __gem_context_get_param(fd, p);
+	if (ret)
+		return ret;
+
+	nengines = p->size > sizeof(struct i915_context_param_engines) ?
+		   (p->size - sizeof(struct i915_context_param_engines)) /
+		   (2 * sizeof(__u16)) :
+		   0;
+
+	igt_assert_f(nengines <= GEM_MAX_ENGINES, "unsupported engine count\n");
+
+	return nengines;
+}
+
+struct intel_engine_data intel_init_engine_list(int fd, uint32_t ctx_id)
+{
+	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, GEM_MAX_ENGINES);
+	struct intel_engine_data engine_data = { };
+	struct drm_i915_gem_context_param param = {
+		.param = I915_CONTEXT_PARAM_ENGINES,
+		.ctx_id = ctx_id,
+		.size = SIZEOF_CTX_PARAM,
+		.value = to_user_pointer(&engines),
+	};
+	int nengines = gem_topology_get_param(fd, ctx_id, &param);
+	int i;
+
+	if (nengines < 0) {
+		/* 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;
+			}
+
+			__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) {
+		/* else if context doesn't have mapped engines */
+		query_engine_list(fd, &engine_data);
+		ctx_map_engines(fd, &engine_data, &param);
+
+	} else {
+		/* context has a list of mapped engines */
+
+		for (i = 0; i < nengines; i++)
+			init_engine(&engine_data.engines[i],
+				    engines.class_instance[i].engine_class,
+				    engines.class_instance[i].engine_instance,
+				    i);
+
+		engine_data.nengines = i;
+	}
+
+	return engine_data;
+}
+
+int gem_ctx_get_engine(int fd, uint32_t engine, uint32_t ctx_id,
+		       struct intel_execution_engine2 *e)
+{
+	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, GEM_MAX_ENGINES);
+	struct drm_i915_gem_context_param param = {
+		.param = I915_CONTEXT_PARAM_ENGINES,
+		.ctx_id = ctx_id,
+		.size = SIZEOF_CTX_PARAM,
+		.value = to_user_pointer(&engines),
+	};
+	int nengines = gem_topology_get_param(fd, ctx_id, &param);
+
+	if (nengines < 0)
+		return nengines;
+
+	if (!param.size || !nengines)
+		return -EINVAL;
+
+	e->class = engines.class_instance[engine].engine_class;
+	e->instance = engines.class_instance[engine].engine_instance;
+
+	return 0;
+}
+
+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 000000000000..806c260b1074
--- /dev/null
+++ b/lib/i915/gem_engine_topology.h
@@ -0,0 +1,78 @@
+/*
+ * 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, \
+					class_instance[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;
+	int error;
+	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_ctx_get_engine(int fd, uint32_t engine, uint32_t ctx_id,
+		       struct intel_execution_engine2 *e);
+
+#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 6654a659c062..03f19ca2dfb6 100644
--- a/lib/igt.h
+++ b/lib/igt.h
@@ -53,5 +53,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 475c0b3c3cc6..52b2f1ea95a5 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 89de06e6924a..93c01daa4222 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',
-- 
2.20.1

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

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

* [igt-dev] [PATCH v19 3/6] lib: igt_gt: add eb flags to class helper
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file Andi Shyti
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition Andi Shyti
@ 2019-04-08 16:15 ` Andi Shyti
  2019-04-08 16:24   ` Tvrtko Ursulin
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 4/6] lib: igt_gt: make gem_engine_can_store_dword() check engine class Andi Shyti
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:15 UTC (permalink / raw)
  To: IGT dev; +Cc: Andi Shyti

we have a "class/instance to eb flags" helper but not the
opposite, add it.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
---
 lib/igt_gt.c | 18 ++++++++++++++++++
 lib/igt_gt.h |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/lib/igt_gt.c b/lib/igt_gt.c
index 5999524326d0..8cd58f7afbfd 100644
--- a/lib/igt_gt.c
+++ b/lib/igt_gt.c
@@ -41,6 +41,7 @@
 #include "intel_reg.h"
 #include "intel_chipset.h"
 #include "igt_dummyload.h"
+#include "i915/gem_engine_topology.h"
 
 /**
  * SECTION:igt_gt
@@ -586,6 +587,23 @@ const struct intel_execution_engine2 intel_execution_engines2[] = {
 	{ }
 };
 
+int gem_eb_to_class(unsigned int flags)
+{
+	switch (flags & 0x3f) {
+		case I915_EXEC_DEFAULT:
+		case I915_EXEC_RENDER:
+			return I915_ENGINE_CLASS_RENDER;
+		case I915_EXEC_BLT:
+			return I915_ENGINE_CLASS_COPY;
+		case I915_EXEC_BSD:
+			return I915_ENGINE_CLASS_VIDEO;
+		case I915_EXEC_VEBOX:
+			return I915_ENGINE_CLASS_VIDEO_ENHANCE;
+		default:
+			igt_assert(0);
+	}
+}
+
 unsigned int
 gem_class_instance_to_eb_flags(int gem_fd,
 			       enum drm_i915_gem_engine_class class,
diff --git a/lib/igt_gt.h b/lib/igt_gt.h
index 52b2f1ea95a5..b13062ef7d33 100644
--- a/lib/igt_gt.h
+++ b/lib/igt_gt.h
@@ -99,6 +99,8 @@ extern const struct intel_execution_engine2 {
 	bool is_virtual;
 } intel_execution_engines2[];
 
+int gem_eb_to_class(unsigned int flags);
+
 unsigned int
 gem_class_instance_to_eb_flags(int gem_fd,
 			       enum drm_i915_gem_engine_class class,
-- 
2.20.1

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

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

* [igt-dev] [PATCH v19 4/6] lib: igt_gt: make gem_engine_can_store_dword() check engine class
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
                   ` (2 preceding siblings ...)
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 3/6] lib: igt_gt: add eb flags to class helper Andi Shyti
@ 2019-04-08 16:15 ` Andi Shyti
  2019-04-08 16:25   ` Tvrtko Ursulin
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine() Andi Shyti
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:15 UTC (permalink / raw)
  To: IGT dev; +Cc: Andi Shyti

Engines referred by class and instance are getting more populare,
gem_engine_can_store_dword() should handle the situation.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
---
 lib/igt_gt.c | 11 ++++++++---
 lib/igt_gt.h |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/lib/igt_gt.c b/lib/igt_gt.c
index 8cd58f7afbfd..5d0a8e8060a7 100644
--- a/lib/igt_gt.c
+++ b/lib/igt_gt.c
@@ -557,7 +557,7 @@ const struct intel_execution_engine intel_execution_engines[] = {
 	{ NULL, 0, 0 }
 };
 
-bool gem_can_store_dword(int fd, unsigned int engine)
+bool gem_class_can_store_dword(int fd, int class)
 {
 	uint16_t devid = intel_get_drm_devid(fd);
 	const struct intel_device_info *info = intel_get_device_info(devid);
@@ -569,8 +569,8 @@ bool gem_can_store_dword(int fd, unsigned int engine)
 	if (gen == 3 && (info->is_grantsdale || info->is_alviso))
 		return false; /* only supports physical addresses */
 
-	if (gen == 6 && ((engine & 0x3f) == I915_EXEC_BSD))
-		return false; /* kills the machine! */
+	if (gen == 6 && class == I915_ENGINE_CLASS_VIDEO)
+		return false;
 
 	if (info->is_broadwater)
 		return false; /* Not sure yet... */
@@ -578,6 +578,11 @@ bool gem_can_store_dword(int fd, unsigned int engine)
 	return true;
 }
 
+bool gem_can_store_dword(int fd, unsigned int engine)
+{
+	return gem_class_can_store_dword(fd, gem_eb_to_class(engine));
+}
+
 const struct intel_execution_engine2 intel_execution_engines2[] = {
 	{ "rcs0", I915_ENGINE_CLASS_RENDER, 0 },
 	{ "bcs0", I915_ENGINE_CLASS_COPY, 0 },
diff --git a/lib/igt_gt.h b/lib/igt_gt.h
index b13062ef7d33..af4cc38a1ef7 100644
--- a/lib/igt_gt.h
+++ b/lib/igt_gt.h
@@ -90,6 +90,7 @@ bool gem_ring_is_physical_engine(int fd, unsigned int ring);
 bool gem_ring_has_physical_engine(int fd, unsigned int ring);
 
 bool gem_can_store_dword(int fd, unsigned int engine);
+bool gem_class_can_store_dword(int fd, int class);
 
 extern const struct intel_execution_engine2 {
 	const char *name;
-- 
2.20.1

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

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

* [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine()
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
                   ` (3 preceding siblings ...)
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 4/6] lib: igt_gt: make gem_engine_can_store_dword() check engine class Andi Shyti
@ 2019-04-08 16:15 ` Andi Shyti
  2019-04-08 16:28   ` Tvrtko Ursulin
                     ` (2 more replies)
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 6/6] test: perf_pmu: use the gem_engine_topology library Andi Shyti
                   ` (3 subsequent siblings)
  8 siblings, 3 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:15 UTC (permalink / raw)
  To: IGT dev; +Cc: Andi Shyti

With the new getparam/setparam api, engines are mapped to
context. Use for_each_context_engine() to loop through existing
engines.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
---
 lib/igt_dummyload.c | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 47f6b92b424b..1d922fb698e0 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -39,6 +39,7 @@
 #include "ioctl_wrappers.h"
 #include "sw_sync.h"
 #include "igt_vgem.h"
+#include "i915/gem_engine_topology.h"
 #include "i915/gem_mman.h"
 
 /**
@@ -86,7 +87,7 @@ emit_recursive_batch(igt_spin_t *spin,
 	struct drm_i915_gem_relocation_entry relocs[2], *r;
 	struct drm_i915_gem_execbuffer2 *execbuf;
 	struct drm_i915_gem_exec_object2 *obj;
-	unsigned int engines[16];
+	unsigned int flags[GEM_MAX_ENGINES];
 	unsigned int nengine;
 	int fence_fd = -1;
 	uint32_t *batch, *batch_start;
@@ -94,17 +95,30 @@ emit_recursive_batch(igt_spin_t *spin,
 
 	nengine = 0;
 	if (opts->engine == ALL_ENGINES) {
-		unsigned int engine;
+		struct intel_execution_engine2 *engine;
 
-		for_each_physical_engine(fd, engine) {
+		for_each_context_engine(fd, opts->ctx, engine) {
 			if (opts->flags & IGT_SPIN_POLL_RUN &&
-			    !gem_can_store_dword(fd, engine))
+			    !gem_class_can_store_dword(fd, engine->class))
 				continue;
 
-			engines[nengine++] = engine;
+			flags[nengine++] = engine->flags;
 		}
 	} else {
-		engines[nengine++] = opts->engine;
+		struct intel_execution_engine2 *e;
+		int class;
+
+		if (!gem_ctx_get_engine(fd, opts->engine, opts->ctx, e)) {
+			class = e->class;
+		} else {
+			gem_require_ring(fd, opts->engine);
+			class = gem_eb_to_class(opts->engine);
+		}
+
+		if (opts->flags & IGT_SPIN_POLL_RUN)
+			igt_require(gem_class_can_store_dword(fd, class));
+
+		flags[nengine++] = opts->engine;
 	}
 	igt_require(nengine);
 
@@ -234,7 +248,7 @@ emit_recursive_batch(igt_spin_t *spin,
 
 	for (i = 0; i < nengine; i++) {
 		execbuf->flags &= ~ENGINE_MASK;
-		execbuf->flags |= engines[i];
+		execbuf->flags |= flags[i];
 
 		gem_execbuf_wr(fd, execbuf);
 
@@ -308,12 +322,6 @@ igt_spin_batch_factory(int fd, const struct igt_spin_factory *opts)
 
 	igt_require_gem(fd);
 
-	if (opts->engine != ALL_ENGINES) {
-		gem_require_ring(fd, opts->engine);
-		if (opts->flags & IGT_SPIN_POLL_RUN)
-			igt_require(gem_can_store_dword(fd, opts->engine));
-	}
-
 	spin = spin_batch_create(fd, opts);
 
 	igt_assert(gem_bo_busy(fd, spin->handle));
-- 
2.20.1

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

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

* [igt-dev] [PATCH v19 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
                   ` (4 preceding siblings ...)
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine() Andi Shyti
@ 2019-04-08 16:15 ` Andi Shyti
  2019-04-08 16:35   ` Tvrtko Ursulin
  2019-04-08 17:35 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface Patchwork
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:15 UTC (permalink / raw)
  To: IGT dev; +Cc: Andi Shyti

Replace the legacy for_each_engine* defines with the ones
implemented in the gem_engine_topology library.

Use whenever possible gem_engine_can_store_dword() that checks
class instead of flags.

Now the __for_each_engine_class_instance and
for_each_engine_class_instance are unused, remove them.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
---
 lib/igt_gt.h     |   7 ---
 tests/perf_pmu.c | 143 +++++++++++++++++++++++++++++------------------
 2 files changed, 88 insertions(+), 62 deletions(-)

diff --git a/lib/igt_gt.h b/lib/igt_gt.h
index af4cc38a1ef7..c2ca07e03738 100644
--- a/lib/igt_gt.h
+++ b/lib/igt_gt.h
@@ -119,11 +119,4 @@ void gem_require_engine(int gem_fd,
 	igt_require(gem_has_engine(gem_fd, class, instance));
 }
 
-#define __for_each_engine_class_instance(e__) \
-	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++)
-
-#define for_each_engine_class_instance(fd__, e__) \
-	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++) \
-		for_if (gem_has_engine((fd__), (e__)->class, (e__)->instance))
-
 #endif /* IGT_GT_H */
diff --git a/tests/perf_pmu.c b/tests/perf_pmu.c
index 4f552bc2ae28..a889b552236d 100644
--- a/tests/perf_pmu.c
+++ b/tests/perf_pmu.c
@@ -72,7 +72,7 @@ static int open_group(uint64_t config, int group)
 }
 
 static void
-init(int gem_fd, const struct intel_execution_engine2 *e, uint8_t sample)
+init(int gem_fd, struct intel_execution_engine2 *e, uint8_t sample)
 {
 	int fd, err = 0;
 	bool exists;
@@ -158,11 +158,6 @@ static unsigned int measured_usleep(unsigned int usec)
 	return igt_nsec_elapsed(&ts);
 }
 
-static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
-{
-	return gem_class_instance_to_eb_flags(gem_fd, e->class, e->instance);
-}
-
 #define TEST_BUSY (1)
 #define FLAG_SYNC (2)
 #define TEST_TRAILING_IDLE (4)
@@ -170,14 +165,15 @@ static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
 #define FLAG_LONG (16)
 #define FLAG_HANG (32)
 
-static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * __spin_poll(int fd, uint32_t ctx,
+				struct intel_execution_engine2 *e)
 {
 	struct igt_spin_factory opts = {
 		.ctx = ctx,
-		.engine = flags,
+		.engine = e->flags,
 	};
 
-	if (gem_can_store_dword(fd, flags))
+	if (gem_class_can_store_dword(fd, e->class))
 		opts.flags |= IGT_SPIN_POLL_RUN;
 
 	return __igt_spin_batch_factory(fd, &opts);
@@ -209,20 +205,34 @@ static unsigned long __spin_wait(int fd, igt_spin_t *spin)
 	return igt_nsec_elapsed(&start);
 }
 
-static igt_spin_t * __spin_sync(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * __spin_sync(int fd, uint32_t ctx,
+				struct intel_execution_engine2 *e)
 {
-	igt_spin_t *spin = __spin_poll(fd, ctx, flags);
+	igt_spin_t *spin = __spin_poll(fd, ctx, e);
 
 	__spin_wait(fd, spin);
 
 	return spin;
 }
 
-static igt_spin_t * spin_sync(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * spin_sync(int fd, uint32_t ctx,
+			      struct intel_execution_engine2 *e)
 {
 	igt_require_gem(fd);
 
-	return __spin_sync(fd, ctx, flags);
+	return __spin_sync(fd, ctx, e);
+}
+
+static igt_spin_t * spin_sync_flags(int fd, uint32_t ctx, unsigned int flags)
+{
+	struct intel_execution_engine2 e = { };
+
+	e.class = gem_eb_to_class(flags);
+	e.instance = (flags & (I915_EXEC_BSD_MASK | I915_EXEC_RING_MASK)) ==
+		     (I915_EXEC_BSD | I915_EXEC_BSD_RING2) ? 1 : 0;
+	e.flags = flags;
+
+	return spin_sync(fd, ctx, &e);
 }
 
 static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
@@ -257,7 +267,7 @@ static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
 }
 
 static void
-single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
+single(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
 {
 	unsigned long slept;
 	igt_spin_t *spin;
@@ -267,7 +277,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
 
 	if (flags & TEST_BUSY)
-		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+		spin = spin_sync(gem_fd, 0, e);
 	else
 		spin = NULL;
 
@@ -303,7 +313,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 }
 
 static void
-busy_start(int gem_fd, const struct intel_execution_engine2 *e)
+busy_start(int gem_fd, struct intel_execution_engine2 *e)
 {
 	unsigned long slept;
 	uint64_t val, ts[2];
@@ -316,7 +326,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
 	 */
 	sleep(2);
 
-	spin = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = __spin_sync(gem_fd, 0, e);
 
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
 
@@ -338,7 +348,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
  * will depend on the CI systems running it a lot to detect issues.
  */
 static void
-busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
+busy_double_start(int gem_fd, struct intel_execution_engine2 *e)
 {
 	unsigned long slept;
 	uint64_t val, val2, ts[2];
@@ -347,6 +357,7 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
 	int fd;
 
 	ctx = gem_context_create(gem_fd);
+	intel_init_engine_list(gem_fd, ctx);
 
 	/*
 	 * Defeat the busy stats delayed disable, we need to guarantee we are
@@ -359,11 +370,11 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
 	 * re-submission in execlists mode. Make sure busyness is correctly
 	 * reported with the engine busy, and after the engine went idle.
 	 */
-	spin[0] = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin[0] = __spin_sync(gem_fd, 0, e);
 	usleep(500e3);
 	spin[1] = __igt_spin_batch_new(gem_fd,
 				       .ctx = ctx,
-				       .engine = e2ring(gem_fd, e));
+				       .engine = e->flags);
 
 	/*
 	 * Open PMU as fast as possible after the second spin batch in attempt
@@ -421,10 +432,10 @@ static void log_busy(unsigned int num_engines, uint64_t *val)
 }
 
 static void
-busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
+busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
 	       const unsigned int num_engines, unsigned int flags)
 {
-	const struct intel_execution_engine2 *e_;
+	struct intel_execution_engine2 *e_;
 	uint64_t tval[2][num_engines];
 	unsigned int busy_idx = 0, i;
 	uint64_t val[num_engines];
@@ -434,8 +445,8 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 	i = 0;
 	fd[0] = -1;
-	for_each_engine_class_instance(gem_fd, e_) {
-		if (e == e_)
+	__for_each_physical_engine(gem_fd, e_) {
+		if (e->class == e_->class && e->instance == e_->instance)
 			busy_idx = i;
 
 		fd[i++] = open_group(I915_PMU_ENGINE_BUSY(e_->class,
@@ -445,7 +456,7 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 	igt_assert_eq(i, num_engines);
 
-	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = spin_sync(gem_fd, 0, e);
 	pmu_read_multi(fd[0], num_engines, tval[0]);
 	slept = measured_usleep(batch_duration_ns / 1000);
 	if (flags & TEST_TRAILING_IDLE)
@@ -472,23 +483,23 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 static void
 __submit_spin_batch(int gem_fd, igt_spin_t *spin,
-		    const struct intel_execution_engine2 *e,
+		    struct intel_execution_engine2 *e,
 		    int offset)
 {
 	struct drm_i915_gem_execbuffer2 eb = spin->execbuf;
 
 	eb.flags &= ~(0x3f | I915_EXEC_BSD_MASK);
-	eb.flags |= e2ring(gem_fd, e) | I915_EXEC_NO_RELOC;
+	eb.flags |= e->flags | I915_EXEC_NO_RELOC;
 	eb.batch_start_offset += offset;
 
 	gem_execbuf(gem_fd, &eb);
 }
 
 static void
-most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
+most_busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
 		    const unsigned int num_engines, unsigned int flags)
 {
-	const struct intel_execution_engine2 *e_;
+	struct intel_execution_engine2 *e_;
 	uint64_t tval[2][num_engines];
 	uint64_t val[num_engines];
 	int fd[num_engines];
@@ -497,13 +508,13 @@ most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 	unsigned int idle_idx, i;
 
 	i = 0;
-	for_each_engine_class_instance(gem_fd, e_) {
-		if (e == e_)
+	__for_each_physical_engine(gem_fd, e_) {
+		if (e->class == e_->class && e->instance == e_->instance)
 			idle_idx = i;
 		else if (spin)
 			__submit_spin_batch(gem_fd, spin, e_, 64);
 		else
-			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e_));
+			spin = __spin_poll(gem_fd, 0, e_);
 
 		val[i++] = I915_PMU_ENGINE_BUSY(e_->class, e_->instance);
 	}
@@ -545,7 +556,7 @@ static void
 all_busy_check_all(int gem_fd, const unsigned int num_engines,
 		   unsigned int flags)
 {
-	const struct intel_execution_engine2 *e;
+	struct intel_execution_engine2 *e;
 	uint64_t tval[2][num_engines];
 	uint64_t val[num_engines];
 	int fd[num_engines];
@@ -554,11 +565,11 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
 	unsigned int i;
 
 	i = 0;
-	for_each_engine_class_instance(gem_fd, e) {
+	__for_each_physical_engine(gem_fd, e) {
 		if (spin)
 			__submit_spin_batch(gem_fd, spin, e, 64);
 		else
-			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e));
+			spin = __spin_poll(gem_fd, 0, e);
 
 		val[i++] = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	}
@@ -592,7 +603,7 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
 }
 
 static void
-no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
+no_sema(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
 {
 	igt_spin_t *spin;
 	uint64_t val[2][2];
@@ -602,7 +613,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 	open_group(I915_PMU_ENGINE_WAIT(e->class, e->instance), fd);
 
 	if (flags & TEST_BUSY)
-		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+		spin = spin_sync(gem_fd, 0, e);
 	else
 		spin = NULL;
 
@@ -631,7 +642,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 #define   MI_SEMAPHORE_SAD_GTE_SDD	(1<<12)
 
 static void
-sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
+sema_wait(int gem_fd, struct intel_execution_engine2 *e,
 	  unsigned int flags)
 {
 	struct drm_i915_gem_relocation_entry reloc[2] = {};
@@ -689,7 +700,7 @@ sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
 
 	eb.buffer_count = 2;
 	eb.buffers_ptr = to_user_pointer(obj);
-	eb.flags = e2ring(gem_fd, e);
+	eb.flags = e->flags;
 
 	/**
 	 * Start the semaphore wait PMU and after some known time let the above
@@ -792,7 +803,7 @@ static int wait_vblank(int fd, union drm_wait_vblank *vbl)
 }
 
 static void
-event_wait(int gem_fd, const struct intel_execution_engine2 *e)
+event_wait(int gem_fd, struct intel_execution_engine2 *e)
 {
 	struct drm_i915_gem_exec_object2 obj = { };
 	struct drm_i915_gem_execbuffer2 eb = { };
@@ -845,7 +856,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
 
 	eb.buffer_count = 1;
 	eb.buffers_ptr = to_user_pointer(&obj);
-	eb.flags = e2ring(gem_fd, e) | I915_EXEC_SECURE;
+	eb.flags = e->flags | I915_EXEC_SECURE;
 
 	for_each_pipe_with_valid_output(&data.display, p, output) {
 		struct igt_helper_process waiter = { };
@@ -917,7 +928,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
 }
 
 static void
-multi_client(int gem_fd, const struct intel_execution_engine2 *e)
+multi_client(int gem_fd, struct intel_execution_engine2 *e)
 {
 	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	unsigned long slept[2];
@@ -936,7 +947,7 @@ multi_client(int gem_fd, const struct intel_execution_engine2 *e)
 	 */
 	fd[1] = open_pmu(config);
 
-	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = spin_sync(gem_fd, 0, e);
 
 	val[0] = val[1] = __pmu_read_single(fd[0], &ts[0]);
 	slept[1] = measured_usleep(batch_duration_ns / 1000);
@@ -1039,6 +1050,7 @@ static void cpu_hotplug(int gem_fd)
 	igt_spin_t *spin[2];
 	uint64_t ts[2];
 	uint64_t val;
+	uint32_t ctx;
 	int link[2];
 	int fd, ret;
 	int cur = 0;
@@ -1046,14 +1058,18 @@ static void cpu_hotplug(int gem_fd)
 
 	igt_require(cpu0_hotplug_support());
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(I915_ENGINE_CLASS_RENDER, 0));
 
 	/*
 	 * Create two spinners so test can ensure shorter gaps in engine
 	 * busyness as it is terminating one and re-starting the other.
 	 */
-	spin[0] = igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
-	spin[1] = __igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
+	spin[0] = igt_spin_batch_new(gem_fd,
+				     .engine = I915_EXEC_RENDER, .ctx = ctx);
+	spin[1] = __igt_spin_batch_new(gem_fd,
+				       .engine = I915_EXEC_RENDER, .ctx = ctx);
 
 	val = __pmu_read_single(fd, &ts[0]);
 
@@ -1137,6 +1153,7 @@ static void cpu_hotplug(int gem_fd)
 
 		igt_spin_batch_free(gem_fd, spin[cur]);
 		spin[cur] = __igt_spin_batch_new(gem_fd,
+						 .ctx = ctx,
 						 .engine = I915_EXEC_RENDER);
 		cur ^= 1;
 	}
@@ -1150,6 +1167,7 @@ static void cpu_hotplug(int gem_fd)
 	igt_waitchildren();
 	close(fd);
 	close(link[0]);
+	gem_context_destroy(gem_fd, ctx);
 
 	/* Skip if child signals a problem with offlining a CPU. */
 	igt_skip_on(buf == 's');
@@ -1165,17 +1183,21 @@ test_interrupts(int gem_fd)
 	igt_spin_t *spin[target];
 	struct pollfd pfd;
 	uint64_t idle, busy;
+	uint32_t ctx;
 	int fence_fd;
 	int fd;
 
 	gem_quiescent_gpu(gem_fd);
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_INTERRUPTS);
 
 	/* Queue spinning batches. */
 	for (int i = 0; i < target; i++) {
 		spin[i] = __igt_spin_batch_new(gem_fd,
 					       .engine = I915_EXEC_RENDER,
+					       .ctx = ctx,
 					       .flags = IGT_SPIN_FENCE_OUT);
 		if (i == 0) {
 			fence_fd = spin[i]->out_fence;
@@ -1217,6 +1239,7 @@ test_interrupts(int gem_fd)
 	/* Check at least as many interrupts has been generated. */
 	busy = pmu_read_single(fd) - idle;
 	close(fd);
+	gem_context_destroy(gem_fd, ctx);
 
 	igt_assert_lte(target, busy);
 }
@@ -1229,15 +1252,19 @@ test_interrupts_sync(int gem_fd)
 	igt_spin_t *spin[target];
 	struct pollfd pfd;
 	uint64_t idle, busy;
+	uint32_t ctx;
 	int fd;
 
 	gem_quiescent_gpu(gem_fd);
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_INTERRUPTS);
 
 	/* Queue spinning batches. */
 	for (int i = 0; i < target; i++)
 		spin[i] = __igt_spin_batch_new(gem_fd,
+					       .ctx = ctx,
 					       .flags = IGT_SPIN_FENCE_OUT);
 
 	/* Wait for idle state. */
@@ -1262,6 +1289,7 @@ test_interrupts_sync(int gem_fd)
 	/* Check at least as many interrupts has been generated. */
 	busy = pmu_read_single(fd) - idle;
 	close(fd);
+	gem_context_destroy(gem_fd, ctx);
 
 	igt_assert_lte(target, busy);
 }
@@ -1274,6 +1302,9 @@ test_frequency(int gem_fd)
 	double min[2], max[2];
 	igt_spin_t *spin;
 	int fd, sysfs;
+	uint32_t ctx;
+
+	ctx = gem_context_create(gem_fd);
 
 	sysfs = igt_sysfs_open(gem_fd);
 	igt_require(sysfs >= 0);
@@ -1301,7 +1332,7 @@ test_frequency(int gem_fd)
 	igt_require(igt_sysfs_get_u32(sysfs, "gt_boost_freq_mhz") == min_freq);
 
 	gem_quiescent_gpu(gem_fd); /* Idle to be sure the change takes effect */
-	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
+	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
 
 	slept = pmu_read_multi(fd, 2, start);
 	measured_usleep(batch_duration_ns / 1000);
@@ -1327,7 +1358,7 @@ test_frequency(int gem_fd)
 	igt_require(igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz") == max_freq);
 
 	gem_quiescent_gpu(gem_fd);
-	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
+	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
 
 	slept = pmu_read_multi(fd, 2, start);
 	measured_usleep(batch_duration_ns / 1000);
@@ -1348,6 +1379,8 @@ test_frequency(int gem_fd)
 			 min_freq, igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz"));
 	close(fd);
 
+	gem_context_destroy(gem_fd, ctx);
+
 	igt_info("Min frequency: requested %.1f, actual %.1f\n",
 		 min[0], min[1]);
 	igt_info("Max frequency: requested %.1f, actual %.1f\n",
@@ -1448,7 +1481,7 @@ test_rc6(int gem_fd, unsigned int flags)
 }
 
 static void
-test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
+test_enable_race(int gem_fd, struct intel_execution_engine2 *e)
 {
 	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	struct igt_helper_process engine_load = { };
@@ -1465,7 +1498,7 @@ test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
 
 	eb.buffer_count = 1;
 	eb.buffers_ptr = to_user_pointer(&obj);
-	eb.flags = e2ring(gem_fd, e);
+	eb.flags = e->flags;
 
 	/*
 	 * This test is probabilistic so run in a few times to increase the
@@ -1520,7 +1553,7 @@ static void __rearm_spin_batch(igt_spin_t *spin)
 	__assert_within(x, ref, tolerance, tolerance)
 
 static void
-accuracy(int gem_fd, const struct intel_execution_engine2 *e,
+accuracy(int gem_fd, struct intel_execution_engine2 *e,
 	 unsigned long target_busy_pct,
 	 unsigned long target_iters)
 {
@@ -1570,7 +1603,7 @@ accuracy(int gem_fd, const struct intel_execution_engine2 *e,
 		igt_spin_t *spin;
 
 		/* Allocate our spin batch and idle it. */
-		spin = igt_spin_batch_new(gem_fd, .engine = e2ring(gem_fd, e));
+		spin = igt_spin_batch_new(gem_fd, .engine = e->flags);
 		igt_spin_batch_end(spin);
 		gem_sync(gem_fd, spin->handle);
 
@@ -1674,7 +1707,7 @@ igt_main
 				I915_PMU_LAST - __I915_PMU_OTHER(0) + 1;
 	unsigned int num_engines = 0;
 	int fd = -1;
-	const struct intel_execution_engine2 *e;
+	struct intel_execution_engine2 *e;
 	unsigned int i;
 
 	igt_fixture {
@@ -1683,7 +1716,7 @@ igt_main
 		igt_require_gem(fd);
 		igt_require(i915_type_id() > 0);
 
-		for_each_engine_class_instance(fd, e)
+		__for_each_physical_engine(fd, e)
 			num_engines++;
 	}
 
@@ -1693,7 +1726,7 @@ igt_main
 	igt_subtest("invalid-init")
 		invalid_init();
 
-	__for_each_engine_class_instance(e) {
+	__for_each_physical_engine(fd, e) {
 		const unsigned int pct[] = { 2, 50, 98 };
 
 		/**
@@ -1897,7 +1930,7 @@ igt_main
 			gem_quiescent_gpu(fd);
 		}
 
-		__for_each_engine_class_instance(e) {
+		__for_each_physical_engine(render_fd, e) {
 			igt_subtest_group {
 				igt_fixture {
 					gem_require_engine(render_fd,
-- 
2.20.1

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

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

* Re: [igt-dev] [PATCH v19 3/6] lib: igt_gt: add eb flags to class helper
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 3/6] lib: igt_gt: add eb flags to class helper Andi Shyti
@ 2019-04-08 16:24   ` Tvrtko Ursulin
  0 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-08 16:24 UTC (permalink / raw)
  To: Andi Shyti, IGT dev; +Cc: Andi Shyti


On 08/04/2019 17:15, Andi Shyti wrote:
> we have a "class/instance to eb flags" helper but not the
> opposite, add it.
> 
> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> ---
>   lib/igt_gt.c | 18 ++++++++++++++++++
>   lib/igt_gt.h |  2 ++
>   2 files changed, 20 insertions(+)
> 
> diff --git a/lib/igt_gt.c b/lib/igt_gt.c
> index 5999524326d0..8cd58f7afbfd 100644
> --- a/lib/igt_gt.c
> +++ b/lib/igt_gt.c
> @@ -41,6 +41,7 @@
>   #include "intel_reg.h"
>   #include "intel_chipset.h"
>   #include "igt_dummyload.h"
> +#include "i915/gem_engine_topology.h"
>   
>   /**
>    * SECTION:igt_gt
> @@ -586,6 +587,23 @@ const struct intel_execution_engine2 intel_execution_engines2[] = {
>   	{ }
>   };
>   
> +int gem_eb_to_class(unsigned int flags)
> +{
> +	switch (flags & 0x3f) {
> +		case I915_EXEC_DEFAULT:
> +		case I915_EXEC_RENDER:
> +			return I915_ENGINE_CLASS_RENDER;
> +		case I915_EXEC_BLT:
> +			return I915_ENGINE_CLASS_COPY;
> +		case I915_EXEC_BSD:
> +			return I915_ENGINE_CLASS_VIDEO;
> +		case I915_EXEC_VEBOX:
> +			return I915_ENGINE_CLASS_VIDEO_ENHANCE;
> +		default:
> +			igt_assert(0);
> +	}
> +}
> +
>   unsigned int
>   gem_class_instance_to_eb_flags(int gem_fd,
>   			       enum drm_i915_gem_engine_class class,
> diff --git a/lib/igt_gt.h b/lib/igt_gt.h
> index 52b2f1ea95a5..b13062ef7d33 100644
> --- a/lib/igt_gt.h
> +++ b/lib/igt_gt.h
> @@ -99,6 +99,8 @@ extern const struct intel_execution_engine2 {
>   	bool is_virtual;
>   } intel_execution_engines2[];
>   
> +int gem_eb_to_class(unsigned int flags);
> +
>   unsigned int
>   gem_class_instance_to_eb_flags(int gem_fd,
>   			       enum drm_i915_gem_engine_class class,
> 

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

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

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

* Re: [igt-dev] [PATCH v19 4/6] lib: igt_gt: make gem_engine_can_store_dword() check engine class
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 4/6] lib: igt_gt: make gem_engine_can_store_dword() check engine class Andi Shyti
@ 2019-04-08 16:25   ` Tvrtko Ursulin
  0 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-08 16:25 UTC (permalink / raw)
  To: Andi Shyti, IGT dev; +Cc: Andi Shyti


On 08/04/2019 17:15, Andi Shyti wrote:
> Engines referred by class and instance are getting more populare,
> gem_engine_can_store_dword() should handle the situation.
> 
> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> ---
>   lib/igt_gt.c | 11 ++++++++---
>   lib/igt_gt.h |  1 +
>   2 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/igt_gt.c b/lib/igt_gt.c
> index 8cd58f7afbfd..5d0a8e8060a7 100644
> --- a/lib/igt_gt.c
> +++ b/lib/igt_gt.c
> @@ -557,7 +557,7 @@ const struct intel_execution_engine intel_execution_engines[] = {
>   	{ NULL, 0, 0 }
>   };
>   
> -bool gem_can_store_dword(int fd, unsigned int engine)
> +bool gem_class_can_store_dword(int fd, int class)
>   {
>   	uint16_t devid = intel_get_drm_devid(fd);
>   	const struct intel_device_info *info = intel_get_device_info(devid);
> @@ -569,8 +569,8 @@ bool gem_can_store_dword(int fd, unsigned int engine)
>   	if (gen == 3 && (info->is_grantsdale || info->is_alviso))
>   		return false; /* only supports physical addresses */
>   
> -	if (gen == 6 && ((engine & 0x3f) == I915_EXEC_BSD))
> -		return false; /* kills the machine! */
> +	if (gen == 6 && class == I915_ENGINE_CLASS_VIDEO)
> +		return false;
>   
>   	if (info->is_broadwater)
>   		return false; /* Not sure yet... */
> @@ -578,6 +578,11 @@ bool gem_can_store_dword(int fd, unsigned int engine)
>   	return true;
>   }
>   
> +bool gem_can_store_dword(int fd, unsigned int engine)
> +{
> +	return gem_class_can_store_dword(fd, gem_eb_to_class(engine));
> +}
> +
>   const struct intel_execution_engine2 intel_execution_engines2[] = {
>   	{ "rcs0", I915_ENGINE_CLASS_RENDER, 0 },
>   	{ "bcs0", I915_ENGINE_CLASS_COPY, 0 },
> diff --git a/lib/igt_gt.h b/lib/igt_gt.h
> index b13062ef7d33..af4cc38a1ef7 100644
> --- a/lib/igt_gt.h
> +++ b/lib/igt_gt.h
> @@ -90,6 +90,7 @@ bool gem_ring_is_physical_engine(int fd, unsigned int ring);
>   bool gem_ring_has_physical_engine(int fd, unsigned int ring);
>   
>   bool gem_can_store_dword(int fd, unsigned int engine);
> +bool gem_class_can_store_dword(int fd, int class);
>   
>   extern const struct intel_execution_engine2 {
>   	const char *name;
> 

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

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

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

* Re: [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine()
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine() Andi Shyti
@ 2019-04-08 16:28   ` Tvrtko Ursulin
  2019-04-08 16:45     ` Andi Shyti
  2019-04-11 12:26     ` [igt-dev] " Tvrtko Ursulin
  2019-04-11 12:28     ` [igt-dev] " Tvrtko Ursulin
  2 siblings, 1 reply; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-08 16:28 UTC (permalink / raw)
  To: Andi Shyti, IGT dev; +Cc: Andi Shyti


On 08/04/2019 17:15, Andi Shyti wrote:
> With the new getparam/setparam api, engines are mapped to
> context. Use for_each_context_engine() to loop through existing
> engines.
> 
> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> ---
>   lib/igt_dummyload.c | 34 +++++++++++++++++++++-------------
>   1 file changed, 21 insertions(+), 13 deletions(-)
> 
> diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
> index 47f6b92b424b..1d922fb698e0 100644
> --- a/lib/igt_dummyload.c
> +++ b/lib/igt_dummyload.c
> @@ -39,6 +39,7 @@
>   #include "ioctl_wrappers.h"
>   #include "sw_sync.h"
>   #include "igt_vgem.h"
> +#include "i915/gem_engine_topology.h"
>   #include "i915/gem_mman.h"
>   
>   /**
> @@ -86,7 +87,7 @@ emit_recursive_batch(igt_spin_t *spin,
>   	struct drm_i915_gem_relocation_entry relocs[2], *r;
>   	struct drm_i915_gem_execbuffer2 *execbuf;
>   	struct drm_i915_gem_exec_object2 *obj;
> -	unsigned int engines[16];
> +	unsigned int flags[GEM_MAX_ENGINES];
>   	unsigned int nengine;
>   	int fence_fd = -1;
>   	uint32_t *batch, *batch_start;
> @@ -94,17 +95,30 @@ emit_recursive_batch(igt_spin_t *spin,
>   
>   	nengine = 0;
>   	if (opts->engine == ALL_ENGINES) {
> -		unsigned int engine;
> +		struct intel_execution_engine2 *engine;
>   
> -		for_each_physical_engine(fd, engine) {
> +		for_each_context_engine(fd, opts->ctx, engine) {
>   			if (opts->flags & IGT_SPIN_POLL_RUN &&
> -			    !gem_can_store_dword(fd, engine))
> +			    !gem_class_can_store_dword(fd, engine->class))
>   				continue;
>   
> -			engines[nengine++] = engine;
> +			flags[nengine++] = engine->flags;
>   		}
>   	} else {
> -		engines[nengine++] = opts->engine;
> +		struct intel_execution_engine2 *e;
> +		int class;
> +
> +		if (!gem_ctx_get_engine(fd, opts->engine, opts->ctx, e)) {
> +			class = e->class;
> +		} else {
> +			gem_require_ring(fd, opts->engine);
> +			class = gem_eb_to_class(opts->engine);
> +		}
> +
> +		if (opts->flags & IGT_SPIN_POLL_RUN)
> +			igt_require(gem_class_can_store_dword(fd, class));
> +
> +		flags[nengine++] = opts->engine;
>   	}

Patch looks good but I'm afraid I made an oversight earlier in review 
when I asked you to move this else block in this function. I forgot that 
the differentiation between igt_spin_batch_new and __igt_spin_batch_new 
was that the latter should not do any execbuf calls apart from the 
spinner itself. Since gem_require_ring does one it could be a problem.

Would you mind moving just this else block back into the main constructor?

With that you can have:

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko

>   	igt_require(nengine);
>   
> @@ -234,7 +248,7 @@ emit_recursive_batch(igt_spin_t *spin,
>   
>   	for (i = 0; i < nengine; i++) {
>   		execbuf->flags &= ~ENGINE_MASK;
> -		execbuf->flags |= engines[i];
> +		execbuf->flags |= flags[i];
>   
>   		gem_execbuf_wr(fd, execbuf);
>   
> @@ -308,12 +322,6 @@ igt_spin_batch_factory(int fd, const struct igt_spin_factory *opts)
>   
>   	igt_require_gem(fd);
>   
> -	if (opts->engine != ALL_ENGINES) {
> -		gem_require_ring(fd, opts->engine);
> -		if (opts->flags & IGT_SPIN_POLL_RUN)
> -			igt_require(gem_can_store_dword(fd, opts->engine));
> -	}
> -
>   	spin = spin_batch_create(fd, opts);
>   
>   	igt_assert(gem_bo_busy(fd, spin->handle));
> 
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

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

* Re: [igt-dev] [PATCH v19 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 6/6] test: perf_pmu: use the gem_engine_topology library Andi Shyti
@ 2019-04-08 16:35   ` Tvrtko Ursulin
  2019-04-08 16:56     ` Andi Shyti
  0 siblings, 1 reply; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-08 16:35 UTC (permalink / raw)
  To: Andi Shyti, IGT dev; +Cc: Andi Shyti


On 08/04/2019 17:15, Andi Shyti wrote:
> Replace the legacy for_each_engine* defines with the ones
> implemented in the gem_engine_topology library.
> 
> Use whenever possible gem_engine_can_store_dword() that checks
> class instead of flags.
> 
> Now the __for_each_engine_class_instance and
> for_each_engine_class_instance are unused, remove them.

In the future please start adding per patch changelogs and in the cover 
letter just list the main changes.

> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> ---
>   lib/igt_gt.h     |   7 ---
>   tests/perf_pmu.c | 143 +++++++++++++++++++++++++++++------------------
>   2 files changed, 88 insertions(+), 62 deletions(-)
> 
> diff --git a/lib/igt_gt.h b/lib/igt_gt.h
> index af4cc38a1ef7..c2ca07e03738 100644
> --- a/lib/igt_gt.h
> +++ b/lib/igt_gt.h
> @@ -119,11 +119,4 @@ void gem_require_engine(int gem_fd,
>   	igt_require(gem_has_engine(gem_fd, class, instance));
>   }
>   
> -#define __for_each_engine_class_instance(e__) \
> -	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++)
> -
> -#define for_each_engine_class_instance(fd__, e__) \
> -	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++) \
> -		for_if (gem_has_engine((fd__), (e__)->class, (e__)->instance))
> -
>   #endif /* IGT_GT_H */
> diff --git a/tests/perf_pmu.c b/tests/perf_pmu.c
> index 4f552bc2ae28..a889b552236d 100644
> --- a/tests/perf_pmu.c
> +++ b/tests/perf_pmu.c
> @@ -72,7 +72,7 @@ static int open_group(uint64_t config, int group)
>   }
>   
>   static void
> -init(int gem_fd, const struct intel_execution_engine2 *e, uint8_t sample)
> +init(int gem_fd, struct intel_execution_engine2 *e, uint8_t sample)

Why is const a problem here? The function only reads from the object?

>   {
>   	int fd, err = 0;
>   	bool exists;
> @@ -158,11 +158,6 @@ static unsigned int measured_usleep(unsigned int usec)
>   	return igt_nsec_elapsed(&ts);
>   }
>   
> -static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
> -{
> -	return gem_class_instance_to_eb_flags(gem_fd, e->class, e->instance);
> -}
> -
>   #define TEST_BUSY (1)
>   #define FLAG_SYNC (2)
>   #define TEST_TRAILING_IDLE (4)
> @@ -170,14 +165,15 @@ static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
>   #define FLAG_LONG (16)
>   #define FLAG_HANG (32)
>   
> -static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags)
> +static igt_spin_t * __spin_poll(int fd, uint32_t ctx,
> +				struct intel_execution_engine2 *e)
>   {
>   	struct igt_spin_factory opts = {
>   		.ctx = ctx,
> -		.engine = flags,
> +		.engine = e->flags,
>   	};
>   
> -	if (gem_can_store_dword(fd, flags))
> +	if (gem_class_can_store_dword(fd, e->class))
>   		opts.flags |= IGT_SPIN_POLL_RUN;
>   
>   	return __igt_spin_batch_factory(fd, &opts);
> @@ -209,20 +205,34 @@ static unsigned long __spin_wait(int fd, igt_spin_t *spin)
>   	return igt_nsec_elapsed(&start);
>   }
>   
> -static igt_spin_t * __spin_sync(int fd, uint32_t ctx, unsigned long flags)
> +static igt_spin_t * __spin_sync(int fd, uint32_t ctx,
> +				struct intel_execution_engine2 *e)
>   {
> -	igt_spin_t *spin = __spin_poll(fd, ctx, flags);
> +	igt_spin_t *spin = __spin_poll(fd, ctx, e);
>   
>   	__spin_wait(fd, spin);
>   
>   	return spin;
>   }
>   
> -static igt_spin_t * spin_sync(int fd, uint32_t ctx, unsigned long flags)
> +static igt_spin_t * spin_sync(int fd, uint32_t ctx,
> +			      struct intel_execution_engine2 *e)
>   {
>   	igt_require_gem(fd);
>   
> -	return __spin_sync(fd, ctx, flags);
> +	return __spin_sync(fd, ctx, e);
> +}
> +
> +static igt_spin_t * spin_sync_flags(int fd, uint32_t ctx, unsigned int flags)
> +{
> +	struct intel_execution_engine2 e = { };
> +
> +	e.class = gem_eb_to_class(flags);
> +	e.instance = (flags & (I915_EXEC_BSD_MASK | I915_EXEC_RING_MASK)) ==
> +		     (I915_EXEC_BSD | I915_EXEC_BSD_RING2) ? 1 : 0;
> +	e.flags = flags;
> +
> +	return spin_sync(fd, ctx, &e);
>   }
>   
>   static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
> @@ -257,7 +267,7 @@ static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
>   }
>   
>   static void
> -single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
> +single(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
>   {
>   	unsigned long slept;
>   	igt_spin_t *spin;
> @@ -267,7 +277,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
>   	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
>   
>   	if (flags & TEST_BUSY)
> -		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
> +		spin = spin_sync(gem_fd, 0, e);
>   	else
>   		spin = NULL;
>   
> @@ -303,7 +313,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
>   }
>   
>   static void
> -busy_start(int gem_fd, const struct intel_execution_engine2 *e)
> +busy_start(int gem_fd, struct intel_execution_engine2 *e)
>   {
>   	unsigned long slept;
>   	uint64_t val, ts[2];
> @@ -316,7 +326,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
>   	 */
>   	sleep(2);
>   
> -	spin = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
> +	spin = __spin_sync(gem_fd, 0, e);
>   
>   	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
>   
> @@ -338,7 +348,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
>    * will depend on the CI systems running it a lot to detect issues.
>    */
>   static void
> -busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
> +busy_double_start(int gem_fd, struct intel_execution_engine2 *e)
>   {
>   	unsigned long slept;
>   	uint64_t val, val2, ts[2];
> @@ -347,6 +357,7 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
>   	int fd;
>   
>   	ctx = gem_context_create(gem_fd);
> +	intel_init_engine_list(gem_fd, ctx);

You didn't find this a bit ugly? I was thinking that we should maybe 
have a helper to configure the context which doesn't return the engine 
data struct. Doesn't matter I guess.

>   
>   	/*
>   	 * Defeat the busy stats delayed disable, we need to guarantee we are
> @@ -359,11 +370,11 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
>   	 * re-submission in execlists mode. Make sure busyness is correctly
>   	 * reported with the engine busy, and after the engine went idle.
>   	 */
> -	spin[0] = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
> +	spin[0] = __spin_sync(gem_fd, 0, e);
>   	usleep(500e3);
>   	spin[1] = __igt_spin_batch_new(gem_fd,
>   				       .ctx = ctx,
> -				       .engine = e2ring(gem_fd, e));
> +				       .engine = e->flags);
>   
>   	/*
>   	 * Open PMU as fast as possible after the second spin batch in attempt
> @@ -421,10 +432,10 @@ static void log_busy(unsigned int num_engines, uint64_t *val)
>   }
>   
>   static void
> -busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
> +busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
>   	       const unsigned int num_engines, unsigned int flags)
>   {
> -	const struct intel_execution_engine2 *e_;
> +	struct intel_execution_engine2 *e_;
>   	uint64_t tval[2][num_engines];
>   	unsigned int busy_idx = 0, i;
>   	uint64_t val[num_engines];
> @@ -434,8 +445,8 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
>   
>   	i = 0;
>   	fd[0] = -1;
> -	for_each_engine_class_instance(gem_fd, e_) {
> -		if (e == e_)
> +	__for_each_physical_engine(gem_fd, e_) {
> +		if (e->class == e_->class && e->instance == e_->instance)
>   			busy_idx = i;
>   
>   		fd[i++] = open_group(I915_PMU_ENGINE_BUSY(e_->class,
> @@ -445,7 +456,7 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
>   
>   	igt_assert_eq(i, num_engines);
>   
> -	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
> +	spin = spin_sync(gem_fd, 0, e);
>   	pmu_read_multi(fd[0], num_engines, tval[0]);
>   	slept = measured_usleep(batch_duration_ns / 1000);
>   	if (flags & TEST_TRAILING_IDLE)
> @@ -472,23 +483,23 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
>   
>   static void
>   __submit_spin_batch(int gem_fd, igt_spin_t *spin,
> -		    const struct intel_execution_engine2 *e,
> +		    struct intel_execution_engine2 *e,
>   		    int offset)
>   {
>   	struct drm_i915_gem_execbuffer2 eb = spin->execbuf;
>   
>   	eb.flags &= ~(0x3f | I915_EXEC_BSD_MASK);
> -	eb.flags |= e2ring(gem_fd, e) | I915_EXEC_NO_RELOC;
> +	eb.flags |= e->flags | I915_EXEC_NO_RELOC;
>   	eb.batch_start_offset += offset;
>   
>   	gem_execbuf(gem_fd, &eb);
>   }
>   
>   static void
> -most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
> +most_busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
>   		    const unsigned int num_engines, unsigned int flags)
>   {
> -	const struct intel_execution_engine2 *e_;
> +	struct intel_execution_engine2 *e_;
>   	uint64_t tval[2][num_engines];
>   	uint64_t val[num_engines];
>   	int fd[num_engines];
> @@ -497,13 +508,13 @@ most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
>   	unsigned int idle_idx, i;
>   
>   	i = 0;
> -	for_each_engine_class_instance(gem_fd, e_) {
> -		if (e == e_)
> +	__for_each_physical_engine(gem_fd, e_) {
> +		if (e->class == e_->class && e->instance == e_->instance)
>   			idle_idx = i;
>   		else if (spin)
>   			__submit_spin_batch(gem_fd, spin, e_, 64);
>   		else
> -			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e_));
> +			spin = __spin_poll(gem_fd, 0, e_);
>   
>   		val[i++] = I915_PMU_ENGINE_BUSY(e_->class, e_->instance);
>   	}
> @@ -545,7 +556,7 @@ static void
>   all_busy_check_all(int gem_fd, const unsigned int num_engines,
>   		   unsigned int flags)
>   {
> -	const struct intel_execution_engine2 *e;
> +	struct intel_execution_engine2 *e;
>   	uint64_t tval[2][num_engines];
>   	uint64_t val[num_engines];
>   	int fd[num_engines];
> @@ -554,11 +565,11 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
>   	unsigned int i;
>   
>   	i = 0;
> -	for_each_engine_class_instance(gem_fd, e) {
> +	__for_each_physical_engine(gem_fd, e) {
>   		if (spin)
>   			__submit_spin_batch(gem_fd, spin, e, 64);
>   		else
> -			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e));
> +			spin = __spin_poll(gem_fd, 0, e);
>   
>   		val[i++] = I915_PMU_ENGINE_BUSY(e->class, e->instance);
>   	}
> @@ -592,7 +603,7 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
>   }
>   
>   static void
> -no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
> +no_sema(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
>   {
>   	igt_spin_t *spin;
>   	uint64_t val[2][2];
> @@ -602,7 +613,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
>   	open_group(I915_PMU_ENGINE_WAIT(e->class, e->instance), fd);
>   
>   	if (flags & TEST_BUSY)
> -		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
> +		spin = spin_sync(gem_fd, 0, e);
>   	else
>   		spin = NULL;
>   
> @@ -631,7 +642,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
>   #define   MI_SEMAPHORE_SAD_GTE_SDD	(1<<12)
>   
>   static void
> -sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
> +sema_wait(int gem_fd, struct intel_execution_engine2 *e,
>   	  unsigned int flags)
>   {
>   	struct drm_i915_gem_relocation_entry reloc[2] = {};
> @@ -689,7 +700,7 @@ sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
>   
>   	eb.buffer_count = 2;
>   	eb.buffers_ptr = to_user_pointer(obj);
> -	eb.flags = e2ring(gem_fd, e);
> +	eb.flags = e->flags;
>   
>   	/**
>   	 * Start the semaphore wait PMU and after some known time let the above
> @@ -792,7 +803,7 @@ static int wait_vblank(int fd, union drm_wait_vblank *vbl)
>   }
>   
>   static void
> -event_wait(int gem_fd, const struct intel_execution_engine2 *e)
> +event_wait(int gem_fd, struct intel_execution_engine2 *e)
>   {
>   	struct drm_i915_gem_exec_object2 obj = { };
>   	struct drm_i915_gem_execbuffer2 eb = { };
> @@ -845,7 +856,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
>   
>   	eb.buffer_count = 1;
>   	eb.buffers_ptr = to_user_pointer(&obj);
> -	eb.flags = e2ring(gem_fd, e) | I915_EXEC_SECURE;
> +	eb.flags = e->flags | I915_EXEC_SECURE;
>   
>   	for_each_pipe_with_valid_output(&data.display, p, output) {
>   		struct igt_helper_process waiter = { };
> @@ -917,7 +928,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
>   }
>   
>   static void
> -multi_client(int gem_fd, const struct intel_execution_engine2 *e)
> +multi_client(int gem_fd, struct intel_execution_engine2 *e)
>   {
>   	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
>   	unsigned long slept[2];
> @@ -936,7 +947,7 @@ multi_client(int gem_fd, const struct intel_execution_engine2 *e)
>   	 */
>   	fd[1] = open_pmu(config);
>   
> -	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
> +	spin = spin_sync(gem_fd, 0, e);
>   
>   	val[0] = val[1] = __pmu_read_single(fd[0], &ts[0]);
>   	slept[1] = measured_usleep(batch_duration_ns / 1000);
> @@ -1039,6 +1050,7 @@ static void cpu_hotplug(int gem_fd)
>   	igt_spin_t *spin[2];
>   	uint64_t ts[2];
>   	uint64_t val;
> +	uint32_t ctx;
>   	int link[2];
>   	int fd, ret;
>   	int cur = 0;
> @@ -1046,14 +1058,18 @@ static void cpu_hotplug(int gem_fd)
>   
>   	igt_require(cpu0_hotplug_support());
>   
> +	ctx = gem_context_create(gem_fd);
> +
>   	fd = open_pmu(I915_PMU_ENGINE_BUSY(I915_ENGINE_CLASS_RENDER, 0));
>   
>   	/*
>   	 * Create two spinners so test can ensure shorter gaps in engine
>   	 * busyness as it is terminating one and re-starting the other.
>   	 */
> -	spin[0] = igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
> -	spin[1] = __igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
> +	spin[0] = igt_spin_batch_new(gem_fd,
> +				     .engine = I915_EXEC_RENDER, .ctx = ctx);
> +	spin[1] = __igt_spin_batch_new(gem_fd,
> +				       .engine = I915_EXEC_RENDER, .ctx = ctx);
>   
>   	val = __pmu_read_single(fd, &ts[0]);
>   
> @@ -1137,6 +1153,7 @@ static void cpu_hotplug(int gem_fd)
>   
>   		igt_spin_batch_free(gem_fd, spin[cur]);
>   		spin[cur] = __igt_spin_batch_new(gem_fd,
> +						 .ctx = ctx,
>   						 .engine = I915_EXEC_RENDER);
>   		cur ^= 1;
>   	}
> @@ -1150,6 +1167,7 @@ static void cpu_hotplug(int gem_fd)
>   	igt_waitchildren();
>   	close(fd);
>   	close(link[0]);
> +	gem_context_destroy(gem_fd, ctx);
>   
>   	/* Skip if child signals a problem with offlining a CPU. */
>   	igt_skip_on(buf == 's');
> @@ -1165,17 +1183,21 @@ test_interrupts(int gem_fd)
>   	igt_spin_t *spin[target];
>   	struct pollfd pfd;
>   	uint64_t idle, busy;
> +	uint32_t ctx;
>   	int fence_fd;
>   	int fd;
>   
>   	gem_quiescent_gpu(gem_fd);
>   
> +	ctx = gem_context_create(gem_fd);
> +
>   	fd = open_pmu(I915_PMU_INTERRUPTS);
>   
>   	/* Queue spinning batches. */
>   	for (int i = 0; i < target; i++) {
>   		spin[i] = __igt_spin_batch_new(gem_fd,
>   					       .engine = I915_EXEC_RENDER,
> +					       .ctx = ctx,
>   					       .flags = IGT_SPIN_FENCE_OUT);
>   		if (i == 0) {
>   			fence_fd = spin[i]->out_fence;
> @@ -1217,6 +1239,7 @@ test_interrupts(int gem_fd)
>   	/* Check at least as many interrupts has been generated. */
>   	busy = pmu_read_single(fd) - idle;
>   	close(fd);
> +	gem_context_destroy(gem_fd, ctx);
>   
>   	igt_assert_lte(target, busy);
>   }
> @@ -1229,15 +1252,19 @@ test_interrupts_sync(int gem_fd)
>   	igt_spin_t *spin[target];
>   	struct pollfd pfd;
>   	uint64_t idle, busy;
> +	uint32_t ctx;
>   	int fd;
>   
>   	gem_quiescent_gpu(gem_fd);
>   
> +	ctx = gem_context_create(gem_fd);
> +
>   	fd = open_pmu(I915_PMU_INTERRUPTS);
>   
>   	/* Queue spinning batches. */
>   	for (int i = 0; i < target; i++)
>   		spin[i] = __igt_spin_batch_new(gem_fd,
> +					       .ctx = ctx,
>   					       .flags = IGT_SPIN_FENCE_OUT);
>   
>   	/* Wait for idle state. */
> @@ -1262,6 +1289,7 @@ test_interrupts_sync(int gem_fd)
>   	/* Check at least as many interrupts has been generated. */
>   	busy = pmu_read_single(fd) - idle;
>   	close(fd);
> +	gem_context_destroy(gem_fd, ctx);
>   
>   	igt_assert_lte(target, busy);
>   }
> @@ -1274,6 +1302,9 @@ test_frequency(int gem_fd)
>   	double min[2], max[2];
>   	igt_spin_t *spin;
>   	int fd, sysfs;
> +	uint32_t ctx;
> +
> +	ctx = gem_context_create(gem_fd);
>   
>   	sysfs = igt_sysfs_open(gem_fd);
>   	igt_require(sysfs >= 0);
> @@ -1301,7 +1332,7 @@ test_frequency(int gem_fd)
>   	igt_require(igt_sysfs_get_u32(sysfs, "gt_boost_freq_mhz") == min_freq);
>   
>   	gem_quiescent_gpu(gem_fd); /* Idle to be sure the change takes effect */
> -	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
> +	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
>   
>   	slept = pmu_read_multi(fd, 2, start);
>   	measured_usleep(batch_duration_ns / 1000);
> @@ -1327,7 +1358,7 @@ test_frequency(int gem_fd)
>   	igt_require(igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz") == max_freq);
>   
>   	gem_quiescent_gpu(gem_fd);
> -	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
> +	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
>   
>   	slept = pmu_read_multi(fd, 2, start);
>   	measured_usleep(batch_duration_ns / 1000);
> @@ -1348,6 +1379,8 @@ test_frequency(int gem_fd)
>   			 min_freq, igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz"));
>   	close(fd);
>   
> +	gem_context_destroy(gem_fd, ctx);
> +
>   	igt_info("Min frequency: requested %.1f, actual %.1f\n",
>   		 min[0], min[1]);
>   	igt_info("Max frequency: requested %.1f, actual %.1f\n",
> @@ -1448,7 +1481,7 @@ test_rc6(int gem_fd, unsigned int flags)
>   }
>   
>   static void
> -test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
> +test_enable_race(int gem_fd, struct intel_execution_engine2 *e)
>   {
>   	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
>   	struct igt_helper_process engine_load = { };
> @@ -1465,7 +1498,7 @@ test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
>   
>   	eb.buffer_count = 1;
>   	eb.buffers_ptr = to_user_pointer(&obj);
> -	eb.flags = e2ring(gem_fd, e);
> +	eb.flags = e->flags;
>   
>   	/*
>   	 * This test is probabilistic so run in a few times to increase the
> @@ -1520,7 +1553,7 @@ static void __rearm_spin_batch(igt_spin_t *spin)
>   	__assert_within(x, ref, tolerance, tolerance)
>   
>   static void
> -accuracy(int gem_fd, const struct intel_execution_engine2 *e,
> +accuracy(int gem_fd, struct intel_execution_engine2 *e,
>   	 unsigned long target_busy_pct,
>   	 unsigned long target_iters)
>   {
> @@ -1570,7 +1603,7 @@ accuracy(int gem_fd, const struct intel_execution_engine2 *e,
>   		igt_spin_t *spin;
>   
>   		/* Allocate our spin batch and idle it. */
> -		spin = igt_spin_batch_new(gem_fd, .engine = e2ring(gem_fd, e));
> +		spin = igt_spin_batch_new(gem_fd, .engine = e->flags);
>   		igt_spin_batch_end(spin);
>   		gem_sync(gem_fd, spin->handle);
>   
> @@ -1674,7 +1707,7 @@ igt_main
>   				I915_PMU_LAST - __I915_PMU_OTHER(0) + 1;
>   	unsigned int num_engines = 0;
>   	int fd = -1;
> -	const struct intel_execution_engine2 *e;
> +	struct intel_execution_engine2 *e;
>   	unsigned int i;
>   
>   	igt_fixture {
> @@ -1683,7 +1716,7 @@ igt_main
>   		igt_require_gem(fd);
>   		igt_require(i915_type_id() > 0);
>   
> -		for_each_engine_class_instance(fd, e)
> +		__for_each_physical_engine(fd, e)
>   			num_engines++;
>   	}
>   
> @@ -1693,7 +1726,7 @@ igt_main
>   	igt_subtest("invalid-init")
>   		invalid_init();
>   
> -	__for_each_engine_class_instance(e) {
> +	__for_each_physical_engine(fd, e) {
>   		const unsigned int pct[] = { 2, 50, 98 };
>   
>   		/**
> @@ -1897,7 +1930,7 @@ igt_main
>   			gem_quiescent_gpu(fd);
>   		}
>   
> -		__for_each_engine_class_instance(e) {
> +		__for_each_physical_engine(render_fd, e) {
>   			igt_subtest_group {
>   				igt_fixture {
>   					gem_require_engine(render_fd,
> 
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

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

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

* Re: [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file Andi Shyti
@ 2019-04-08 16:37   ` Tvrtko Ursulin
  2019-04-08 16:47     ` Andi Shyti
  0 siblings, 1 reply; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-08 16:37 UTC (permalink / raw)
  To: Andi Shyti, IGT dev; +Cc: Andi Shyti


On 08/04/2019 17:15, Andi Shyti wrote:
> This header file is imported in order to include the two new
> ioctls DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM,
> DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM and DRM_IOCTL_I915_QUERY.
> 
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> ---
>   include/drm-uapi/i915_drm.h | 361 ++++++++++++++++++++++++++++++------
>   1 file changed, 304 insertions(+), 57 deletions(-)
> 
> diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
> index 4ae1c6ff6ae6..2bbad08eb9d2 100644
> --- a/include/drm-uapi/i915_drm.h
> +++ b/include/drm-uapi/i915_drm.h
> @@ -62,6 +62,26 @@ extern "C" {
>   #define I915_ERROR_UEVENT		"ERROR"
>   #define I915_RESET_UEVENT		"RESET"
>   
> +/*
> + * i915_user_extension: Base class for defining a chain of extensions
> + *
> + * Many interfaces need to grow over time. In most cases we can simply
> + * extend the struct and have userspace pass in more data. Another option,
> + * as demonstrated by Vulkan's approach to providing extensions for forward
> + * and backward compatibility, is to use a list of optional structs to
> + * provide those extra details.
> + *
> + * The key advantage to using an extension chain is that it allows us to
> + * redefine the interface more easily than an ever growing struct of
> + * increasing complexity, and for large parts of that interface to be
> + * entirely optional. The downside is more pointer chasing; chasing across
> + * the boundary with pointers encapsulated inside u64.
> + */
> +struct i915_user_extension {
> +	__u64 next_extension;
> +	__u64 name;
> +};

Just a note to not merge this version since my branch has accidentally 
diverged from latest drm-tip in this respect.

Regards,

Tvrtko

> +
>   /*
>    * MOCS indexes used for GPU surfaces, defining the cacheability of the
>    * surface data and the coherency for this data wrt. CPU vs. GPU accesses.
> @@ -104,6 +124,9 @@ enum drm_i915_gem_engine_class {
>   	I915_ENGINE_CLASS_INVALID	= -1
>   };
>   
> +#define I915_ENGINE_CLASS_INVALID_NONE -1
> +#define I915_ENGINE_CLASS_INVALID_VIRTUAL 0
> +
>   /**
>    * DOC: perf_events exposed by i915 through /sys/bus/event_sources/drivers/i915
>    *
> @@ -321,6 +344,8 @@ typedef struct _drm_i915_sarea {
>   #define DRM_I915_PERF_ADD_CONFIG	0x37
>   #define DRM_I915_PERF_REMOVE_CONFIG	0x38
>   #define DRM_I915_QUERY			0x39
> +#define DRM_I915_GEM_VM_CREATE		0x3a
> +#define DRM_I915_GEM_VM_DESTROY		0x3b
>   /* Must be kept compact -- no holes */
>   
>   #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
> @@ -370,6 +395,7 @@ typedef struct _drm_i915_sarea {
>   #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
>   #define DRM_IOCTL_I915_GEM_WAIT		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
>   #define DRM_IOCTL_I915_GEM_CONTEXT_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
> +#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext)
>   #define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
>   #define DRM_IOCTL_I915_REG_READ			DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
>   #define DRM_IOCTL_I915_GET_RESET_STATS		DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
> @@ -380,6 +406,8 @@ typedef struct _drm_i915_sarea {
>   #define DRM_IOCTL_I915_PERF_ADD_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
>   #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
>   #define DRM_IOCTL_I915_QUERY			DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query)
> +#define DRM_IOCTL_I915_GEM_VM_CREATE	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control)
> +#define DRM_IOCTL_I915_GEM_VM_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control)
>   
>   /* Allow drivers to submit batchbuffers directly to hardware, relying
>    * on the security mechanisms provided by hardware.
> @@ -563,6 +591,12 @@ typedef struct drm_i915_irq_wait {
>    */
>   #define I915_PARAM_MMAP_GTT_COHERENT	52
>   
> +/*
> + * Query whether DRM_I915_GEM_EXECBUFFER2 supports coordination of parallel
> + * execution through use of explicit fence support.
> + * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
> + */
> +#define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
>   /* Must be kept compact -- no holes and well documented */
>   
>   typedef struct drm_i915_getparam {
> @@ -1085,7 +1119,16 @@ struct drm_i915_gem_execbuffer2 {
>    */
>   #define I915_EXEC_FENCE_ARRAY   (1<<19)
>   
> -#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
> +/*
> + * Setting I915_EXEC_FENCE_SUBMIT implies that lower_32_bits(rsvd2) represent
> + * a sync_file fd to wait upon (in a nonblocking manner) prior to executing
> + * the batch.
> + *
> + * Returns -EINVAL if the sync_file fd cannot be found.
> + */
> +#define I915_EXEC_FENCE_SUBMIT		(1 << 20)
> +
> +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
>   
>   #define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
>   #define i915_execbuffer2_set_context_id(eb2, context) \
> @@ -1421,65 +1464,18 @@ struct drm_i915_gem_wait {
>   };
>   
>   struct drm_i915_gem_context_create {
> -	/*  output: id of new context*/
> -	__u32 ctx_id;
> -	__u32 pad;
> -};
> -
> -struct drm_i915_gem_context_destroy {
> -	__u32 ctx_id;
> -	__u32 pad;
> -};
> -
> -struct drm_i915_reg_read {
> -	/*
> -	 * Register offset.
> -	 * For 64bit wide registers where the upper 32bits don't immediately
> -	 * follow the lower 32bits, the offset of the lower 32bits must
> -	 * be specified
> -	 */
> -	__u64 offset;
> -#define I915_REG_READ_8B_WA (1ul << 0)
> -
> -	__u64 val; /* Return value */
> -};
> -/* Known registers:
> - *
> - * Render engine timestamp - 0x2358 + 64bit - gen7+
> - * - Note this register returns an invalid value if using the default
> - *   single instruction 8byte read, in order to workaround that pass
> - *   flag I915_REG_READ_8B_WA in offset field.
> - *
> - */
> -
> -struct drm_i915_reset_stats {
> -	__u32 ctx_id;
> -	__u32 flags;
> -
> -	/* All resets since boot/module reload, for all contexts */
> -	__u32 reset_count;
> -
> -	/* Number of batches lost when active in GPU, for this context */
> -	__u32 batch_active;
> -
> -	/* Number of batches lost pending for execution, for this context */
> -	__u32 batch_pending;
> -
> +	__u32 ctx_id; /* output: id of new context*/
>   	__u32 pad;
>   };
>   
> -struct drm_i915_gem_userptr {
> -	__u64 user_ptr;
> -	__u64 user_size;
> +struct drm_i915_gem_context_create_ext {
> +	__u32 ctx_id; /* output: id of new context*/
>   	__u32 flags;
> -#define I915_USERPTR_READ_ONLY 0x1
> -#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
> -	/**
> -	 * Returned handle for the object.
> -	 *
> -	 * Object handles are nonzero.
> -	 */
> -	__u32 handle;
> +#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS	(1u << 0)
> +#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE	(1u << 1)
> +#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \
> +	(-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1))
> +	__u64 extensions;
>   };
>   
>   struct drm_i915_gem_context_param {
> @@ -1520,7 +1516,43 @@ struct drm_i915_gem_context_param {
>    * On creation, all new contexts are marked as recoverable.
>    */
>   #define I915_CONTEXT_PARAM_RECOVERABLE	0x8
> +
> +	/*
> +	 * The id of the associated virtual memory address space (ppGTT) of
> +	 * this context. Can be retrieved and passed to another context
> +	 * (on the same fd) for both to use the same ppGTT and so share
> +	 * address layouts, and avoid reloading the page tables on context
> +	 * switches between themselves.
> +	 *
> +	 * See DRM_I915_GEM_VM_CREATE and DRM_I915_GEM_VM_DESTROY.
> +	 */
> +#define I915_CONTEXT_PARAM_VM		0x9
> +
> +/*
> + * I915_CONTEXT_PARAM_ENGINES:
> + *
> + * Bind this context to operate on this subset of available engines. Henceforth,
> + * the I915_EXEC_RING selector for DRM_IOCTL_I915_GEM_EXECBUFFER2 operates as
> + * an index into this array of engines; I915_EXEC_DEFAULT selecting engine[0]
> + * and upwards. Slots 0...N are filled in using the specified (class, instance).
> + * Use
> + *	engine_class: I915_ENGINE_CLASS_INVALID,
> + *	engine_instance: I915_ENGINE_CLASS_INVALID_NONE
> + * to specify a gap in the array that can be filled in later, e.g. by a
> + * virtual engine used for load balancing.
> + *
> + * Setting the number of engines bound to the context to 0, by passing a zero
> + * sized argument, will revert back to default settings.
> + *
> + * See struct i915_context_param_engines.
> + *
> + * Extensions:
> + *   i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE)
> + *   i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
> + */
> +#define I915_CONTEXT_PARAM_ENGINES	0xa
>   /* Must be kept compact -- no holes and well documented */
> +
>   	__u64 value;
>   };
>   
> @@ -1553,9 +1585,10 @@ struct drm_i915_gem_context_param_sseu {
>   	__u16 engine_instance;
>   
>   	/*
> -	 * Unused for now. Must be cleared to zero.
> +	 * Unknown flags must be cleared to zero.
>   	 */
>   	__u32 flags;
> +#define I915_CONTEXT_SSEU_FLAG_ENGINE_INDEX (1u << 0)
>   
>   	/*
>   	 * Mask of slices to enable for the context. Valid values are a subset
> @@ -1583,6 +1616,175 @@ struct drm_i915_gem_context_param_sseu {
>   	__u32 rsvd;
>   };
>   
> +/*
> + * i915_context_engines_load_balance:
> + *
> + * Enable load balancing across this set of engines.
> + *
> + * Into the I915_EXEC_DEFAULT slot [0], a virtual engine is created that when
> + * used will proxy the execbuffer request onto one of the set of engines
> + * in such a way as to distribute the load evenly across the set.
> + *
> + * The set of engines must be compatible (e.g. the same HW class) as they
> + * will share the same logical GPU context and ring.
> + *
> + * To intermix rendering with the virtual engine and direct rendering onto
> + * the backing engines (bypassing the load balancing proxy), the context must
> + * be defined to use a single timeline for all engines.
> + */
> +struct i915_context_engines_load_balance {
> +	struct i915_user_extension base;
> +
> +	__u16 engine_index;
> +	__u16 mbz16; /* reserved for future use; must be zero */
> +	__u32 flags; /* all undefined flags must be zero */
> +
> +	__u64 engines_mask; /* selection mask of engines[] */
> +
> +	__u64 mbz64[4]; /* reserved for future use; must be zero */
> +};
> +
> +/*
> + * i915_context_engines_bond:
> + *
> + */
> +struct i915_context_engines_bond {
> +	struct i915_user_extension base;
> +
> +	__u16 engine_index;
> +	__u16 mbz;
> +
> +	__u16 master_class;
> +	__u16 master_instance;
> +
> +	__u64 sibling_mask;
> +	__u64 flags; /* all undefined flags must be zero */
> +};
> +
> +struct i915_context_param_engines {
> +	__u64 extensions; /* linked chain of extension blocks, 0 terminates */
> +#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0
> +#define I915_CONTEXT_ENGINES_EXT_BOND 1
> +
> +	struct {
> +		__u16 engine_class; /* see enum drm_i915_gem_engine_class */
> +		__u16 engine_instance;
> +	} class_instance[0];
> +} __attribute__((packed));
> +
> +#define I915_DEFINE_CONTEXT_PARAM_ENGINES(name__, N__) struct { \
> +	__u64 extensions; \
> +	struct { \
> +		__u16 engine_class; \
> +		__u16 engine_instance; \
> +	} class_instance[N__]; \
> +} __attribute__((packed)) name__
> +
> +struct drm_i915_gem_context_create_ext_setparam {
> +#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
> +	struct i915_user_extension base;
> +	struct drm_i915_gem_context_param setparam;
> +};
> +
> +struct drm_i915_gem_context_create_ext_clone {
> +#define I915_CONTEXT_CREATE_EXT_CLONE 1
> +	struct i915_user_extension base;
> +	__u32 clone_id;
> +	__u32 flags;
> +#define I915_CONTEXT_CLONE_FLAGS	(1u << 0)
> +#define I915_CONTEXT_CLONE_SCHED	(1u << 1)
> +#define I915_CONTEXT_CLONE_SSEU		(1u << 2)
> +#define I915_CONTEXT_CLONE_TIMELINE	(1u << 3)
> +#define I915_CONTEXT_CLONE_VM		(1u << 4)
> +#define I915_CONTEXT_CLONE_ENGINES	(1u << 5)
> +#define I915_CONTEXT_CLONE_UNKNOWN -(I915_CONTEXT_CLONE_ENGINES << 1)
> +	__u64 rsvd;
> +};
> +
> +struct drm_i915_gem_context_destroy {
> +	__u32 ctx_id;
> +	__u32 pad;
> +};
> +
> +/*
> + * DRM_I915_GEM_VM_CREATE -
> + *
> + * Create a new virtual memory address space (ppGTT) for use within a context
> + * on the same file. Extensions can be provided to configure exactly how the
> + * address space is setup upon creation.
> + *
> + * The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is
> + * returned in the outparam @id.
> + *
> + * No flags are defined, with all bits reserved and must be zero.
> + *
> + * An extension chain maybe provided, starting with @extensions, and terminated
> + * by the @next_extension being 0. Currently, no extensions are defined.
> + *
> + * DRM_I915_GEM_VM_DESTROY -
> + *
> + * Destroys a previously created VM id, specified in @id.
> + *
> + * No extensions or flags are allowed currently, and so must be zero.
> + */
> +struct drm_i915_gem_vm_control {
> +	__u64 extensions;
> +	__u32 flags;
> +	__u32 id;
> +};
> +
> +struct drm_i915_reg_read {
> +	/*
> +	 * Register offset.
> +	 * For 64bit wide registers where the upper 32bits don't immediately
> +	 * follow the lower 32bits, the offset of the lower 32bits must
> +	 * be specified
> +	 */
> +	__u64 offset;
> +#define I915_REG_READ_8B_WA (1ul << 0)
> +
> +	__u64 val; /* Return value */
> +};
> +
> +/* Known registers:
> + *
> + * Render engine timestamp - 0x2358 + 64bit - gen7+
> + * - Note this register returns an invalid value if using the default
> + *   single instruction 8byte read, in order to workaround that pass
> + *   flag I915_REG_READ_8B_WA in offset field.
> + *
> + */
> +
> +struct drm_i915_reset_stats {
> +	__u32 ctx_id;
> +	__u32 flags;
> +
> +	/* All resets since boot/module reload, for all contexts */
> +	__u32 reset_count;
> +
> +	/* Number of batches lost when active in GPU, for this context */
> +	__u32 batch_active;
> +
> +	/* Number of batches lost pending for execution, for this context */
> +	__u32 batch_pending;
> +
> +	__u32 pad;
> +};
> +
> +struct drm_i915_gem_userptr {
> +	__u64 user_ptr;
> +	__u64 user_size;
> +	__u32 flags;
> +#define I915_USERPTR_READ_ONLY 0x1
> +#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
> +	/**
> +	 * Returned handle for the object.
> +	 *
> +	 * Object handles are nonzero.
> +	 */
> +	__u32 handle;
> +};
> +
>   enum drm_i915_oa_format {
>   	I915_OA_FORMAT_A13 = 1,	    /* HSW only */
>   	I915_OA_FORMAT_A29,	    /* HSW only */
> @@ -1744,6 +1946,7 @@ struct drm_i915_perf_oa_config {
>   struct drm_i915_query_item {
>   	__u64 query_id;
>   #define DRM_I915_QUERY_TOPOLOGY_INFO    1
> +#define DRM_I915_QUERY_ENGINE_INFO	2
>   /* Must be kept compact -- no holes and well documented */
>   
>   	/*
> @@ -1842,6 +2045,50 @@ struct drm_i915_query_topology_info {
>   	__u8 data[];
>   };
>   
> +/**
> + * struct drm_i915_engine_info
> + *
> + * Describes one engine and it's capabilities as known to the driver.
> + */
> +struct drm_i915_engine_info {
> +	/** Engine class as in enum drm_i915_gem_engine_class. */
> +	__u16 engine_class;
> +
> +	/** Engine instance number. */
> +	__u16 engine_instance;
> +
> +	/** Reserved field. */
> +	__u32 rsvd0;
> +
> +	/** Engine flags. */
> +	__u64 flags;
> +
> +	/** Capabilities of this engine. */
> +	__u64 capabilities;
> +#define I915_VIDEO_CLASS_CAPABILITY_HEVC		(1 << 0)
> +#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC	(1 << 1)
> +
> +	/** Reserved fields. */
> +	__u64 rsvd1[4];
> +};
> +
> +/**
> + * struct drm_i915_query_engine_info
> + *
> + * Engine info query enumerates all engines known to the driver by filling in
> + * an array of struct drm_i915_engine_info structures.
> + */
> +struct drm_i915_query_engine_info {
> +	/** Number of struct drm_i915_engine_info structs following. */
> +	__u32 num_engines;
> +
> +	/** MBZ */
> +	__u32 rsvd[3];
> +
> +	/** Marker for drm_i915_engine_info structures. */
> +	struct drm_i915_engine_info engines[];
> +};
> +
>   #if defined(__cplusplus)
>   }
>   #endif
> 
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

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

* Re: [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine()
  2019-04-08 16:28   ` Tvrtko Ursulin
@ 2019-04-08 16:45     ` Andi Shyti
  0 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:45 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: IGT dev, Andi Shyti

Hi Tvrtko,

> > -		engines[nengine++] = opts->engine;
> > +		struct intel_execution_engine2 *e;
> > +		int class;
> > +
> > +		if (!gem_ctx_get_engine(fd, opts->engine, opts->ctx, e)) {
> > +			class = e->class;
> > +		} else {
> > +			gem_require_ring(fd, opts->engine);
> > +			class = gem_eb_to_class(opts->engine);
> > +		}
> > +
> > +		if (opts->flags & IGT_SPIN_POLL_RUN)
> > +			igt_require(gem_class_can_store_dword(fd, class));
> > +
> > +		flags[nengine++] = opts->engine;
> >   	}
> 
> Patch looks good but I'm afraid I made an oversight earlier in review when I
> asked you to move this else block in this function. I forgot that the
> differentiation between igt_spin_batch_new and __igt_spin_batch_new was that
> the latter should not do any execbuf calls apart from the spinner itself.
> Since gem_require_ring does one it could be a problem.
> 
> Would you mind moving just this else block back into the main constructor?

No problem, I'll move it back.

> With that you can have:
> 
> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

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

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

* Re: [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file
  2019-04-08 16:37   ` Tvrtko Ursulin
@ 2019-04-08 16:47     ` Andi Shyti
  2019-04-08 16:56       ` Tvrtko Ursulin
  0 siblings, 1 reply; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:47 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: IGT dev, Andi Shyti

Hi Tvrtko,

> > This header file is imported in order to include the two new
> > ioctls DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM,
> > DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM and DRM_IOCTL_I915_QUERY.
> > 
> > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > ---
> >   include/drm-uapi/i915_drm.h | 361 ++++++++++++++++++++++++++++++------
> >   1 file changed, 304 insertions(+), 57 deletions(-)
> > 
> > diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
> > index 4ae1c6ff6ae6..2bbad08eb9d2 100644
> > --- a/include/drm-uapi/i915_drm.h
> > +++ b/include/drm-uapi/i915_drm.h
> > @@ -62,6 +62,26 @@ extern "C" {
> >   #define I915_ERROR_UEVENT		"ERROR"
> >   #define I915_RESET_UEVENT		"RESET"
> > +/*
> > + * i915_user_extension: Base class for defining a chain of extensions
> > + *
> > + * Many interfaces need to grow over time. In most cases we can simply
> > + * extend the struct and have userspace pass in more data. Another option,
> > + * as demonstrated by Vulkan's approach to providing extensions for forward
> > + * and backward compatibility, is to use a list of optional structs to
> > + * provide those extra details.
> > + *
> > + * The key advantage to using an extension chain is that it allows us to
> > + * redefine the interface more easily than an ever growing struct of
> > + * increasing complexity, and for large parts of that interface to be
> > + * entirely optional. The downside is more pointer chasing; chasing across
> > + * the boundary with pointers encapsulated inside u64.
> > + */
> > +struct i915_user_extension {
> > +	__u64 next_extension;
> > +	__u64 name;
> > +};
> 
> Just a note to not merge this version since my branch has accidentally
> diverged from latest drm-tip in this respect.

yes, it slipped off my mind. Do you have any plans to rebase your
branch? I would send the patches today.

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

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

* Re: [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition Andi Shyti
@ 2019-04-08 16:54   ` Tvrtko Ursulin
  2019-04-08 18:21     ` Andi Shyti
  2019-04-11 16:03   ` Tvrtko Ursulin
  1 sibling, 1 reply; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-08 16:54 UTC (permalink / raw)
  To: Andi Shyti, IGT dev; +Cc: Andi Shyti


On 08/04/2019 17:15, Andi Shyti wrote:
> The gem_engine_topology library is a set of functions that
> interface with the query and getparam/setparam ioctls.
> 
> The library's access point is the 'intel_init_engine_list()'
> function that, everytime is called, generates the list of active
> engines and returns them in a 'struct intel_engine_data'. The
> structure contains only the engines that are actively present in
> the GPU.
> 
> The function can work in both the cases that the query and
> getparam ioctls are implemented or not by the running kernel. In
> case they are implemented, a query is made to the driver to fetch
> the list of active engines. In case they are not implemented, the
> list is taken from the 'intel_execution_engines2' array and
> stored only after checking their presence.
> 
> The gem_engine_topology library provides some iteration helpers:
> 
>   - intel_get_current_engine(): provides the current engine in the
>     iteration.
> 
>   - intel_get_current_physical_engine(): provides the current
>     physical engine, if the current engine is a virtual engine,
>     it moves forward until it finds a physical engine.
> 
>   - intel_next_engine() it just increments the counter so that it
>     points to the next engine.
> 
> Extend the 'for_each_engine_class_instance' so that it can loop
> using the new 'intel_init_engine_list()' and rename it to
> 'for_each_context_engine'.
> 
> Move '__for_each_engine_class_instance' to gem_engine_topology.h
> and rename it to '__for_each_static_engine'.
> 
> Update accordingly tests/perf_pmu.c to use correctly the new
> for_each loops.
> 
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> ---
>   lib/Makefile.sources           |   2 +
>   lib/i915/gem_engine_topology.c | 281 +++++++++++++++++++++++++++++++++
>   lib/i915/gem_engine_topology.h |  78 +++++++++
>   lib/igt.h                      |   1 +
>   lib/igt_gt.h                   |   2 +
>   lib/meson.build                |   1 +
>   6 files changed, 365 insertions(+)
>   create mode 100644 lib/i915/gem_engine_topology.c
>   create mode 100644 lib/i915/gem_engine_topology.h
> 
> diff --git a/lib/Makefile.sources b/lib/Makefile.sources
> index e00347f945c5..41331c2f2b80 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 000000000000..06f538372a4d
> --- /dev/null
> +++ b/lib/i915/gem_engine_topology.c
> @@ -0,0 +1,281 @@
> +/*
> + * 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"
> +
> +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->class_instance[0]) *p =
> +	     &engines->class_instance[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), class_instance[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_class,
> +			    query_engine->engines[i].engine_instance, i);
> +
> +	ed->nengines = query_engine->num_engines;
> +}
> +
> +struct intel_execution_engine2
> +*intel_get_current_engine(struct intel_engine_data *ed)
> +{

Our coding style is

type *
func_name(..)

(Take care of all instances in source and header.)

> +	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->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, uint32_t ctx,
> +				  struct drm_i915_gem_context_param *p)
> +{
> +	int nengines;
> +	int ret;
> +
> +	if (igt_only_list_subtests())
> +		return -EPERM;

Puzzling choice of errno, not that it matters, but I am tempted to 
suggest -ENODEV.

> +
> +	ret = __gem_context_get_param(fd, p);
> +	if (ret)
> +		return ret;
> +
> +	nengines = p->size > sizeof(struct i915_context_param_engines) ?
> +		   (p->size - sizeof(struct i915_context_param_engines)) /
> +		   (2 * sizeof(__u16)) :
> +		   0;
> +
> +	igt_assert_f(nengines <= GEM_MAX_ENGINES, "unsupported engine count\n");
> +
> +	return nengines;
> +}
> +
> +struct intel_engine_data intel_init_engine_list(int fd, uint32_t ctx_id)
> +{
> +	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, GEM_MAX_ENGINES);
> +	struct intel_engine_data engine_data = { };
> +	struct drm_i915_gem_context_param param = {
> +		.param = I915_CONTEXT_PARAM_ENGINES,
> +		.ctx_id = ctx_id,
> +		.size = SIZEOF_CTX_PARAM,
> +		.value = to_user_pointer(&engines),
> +	};
> +	int nengines = gem_topology_get_param(fd, ctx_id, &param);
> +	int i;
> +
> +	if (nengines < 0) {
> +		/* 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);

Would it make sense to "poison" flags with like -1 (when listing 
subtests) so any mistakes would never have a chance to work?

> +
> +				if (!gem_has_ring(fd, __e2->flags))
> +					continue;
> +			}
> +
> +			__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) {
> +		/* else if context doesn't have mapped engines */
> +		query_engine_list(fd, &engine_data);
> +		ctx_map_engines(fd, &engine_data, &param);
> +

Extra blank line.

> +	} else {
> +		/* context has a list of mapped engines */
> +
> +		for (i = 0; i < nengines; i++)
> +			init_engine(&engine_data.engines[i],
> +				    engines.class_instance[i].engine_class,
> +				    engines.class_instance[i].engine_instance,
> +				    i);
> +
> +		engine_data.nengines = i;
> +	}
> +
> +	return engine_data;
> +}
> +
> +int gem_ctx_get_engine(int fd, uint32_t engine, uint32_t ctx_id,
> +		       struct intel_execution_engine2 *e)
> +{
> +	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, GEM_MAX_ENGINES);
> +	struct drm_i915_gem_context_param param = {
> +		.param = I915_CONTEXT_PARAM_ENGINES,
> +		.ctx_id = ctx_id,
> +		.size = SIZEOF_CTX_PARAM,
> +		.value = to_user_pointer(&engines),
> +	};
> +	int nengines = gem_topology_get_param(fd, ctx_id, &param);
> +
> +	if (nengines < 0)
> +		return nengines;
> +
> +	if (!param.size || !nengines)
> +		return -EINVAL;
> +
> +	e->class = engines.class_instance[engine].engine_class;
> +	e->instance = engines.class_instance[engine].engine_instance;
> +
> +	return 0;
> +}
> +
> +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 000000000000..806c260b1074
> --- /dev/null
> +++ b/lib/i915/gem_engine_topology.h
> @@ -0,0 +1,78 @@
> +/*
> + * 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, \
> +					class_instance[GEM_MAX_ENGINES])
> +#define SIZEOF_QUERY		offsetof(struct drm_i915_query_engine_info, \
> +					engines[GEM_MAX_ENGINES])

Do you need these two in the header file?

> +
> +#define GEM_MAX_ENGINES		I915_EXEC_RING_MASK + 1
> +
> +struct intel_engine_data {
> +	uint32_t nengines;
> +	uint32_t n;
> +	int error;

Unused?

> +	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_ctx_get_engine(int fd, uint32_t engine, uint32_t ctx_id,
> +		       struct intel_execution_engine2 *e);
> +
> +#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 6654a659c062..03f19ca2dfb6 100644
> --- a/lib/igt.h
> +++ b/lib/igt.h
> @@ -53,5 +53,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 475c0b3c3cc6..52b2f1ea95a5 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 89de06e6924a..93c01daa4222 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',
> 

Coding style and question against the header file are the only real ones 
left. Otherwise looks good.

Regards,

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

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

* Re: [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file
  2019-04-08 16:47     ` Andi Shyti
@ 2019-04-08 16:56       ` Tvrtko Ursulin
  2019-04-08 18:33         ` Antonio Argenziano
  0 siblings, 1 reply; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-08 16:56 UTC (permalink / raw)
  To: Andi Shyti; +Cc: IGT dev, Andi Shyti


On 08/04/2019 17:47, Andi Shyti wrote:
> Hi Tvrtko,
> 
>>> This header file is imported in order to include the two new
>>> ioctls DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM,
>>> DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM and DRM_IOCTL_I915_QUERY.
>>>
>>> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
>>> ---
>>>    include/drm-uapi/i915_drm.h | 361 ++++++++++++++++++++++++++++++------
>>>    1 file changed, 304 insertions(+), 57 deletions(-)
>>>
>>> diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
>>> index 4ae1c6ff6ae6..2bbad08eb9d2 100644
>>> --- a/include/drm-uapi/i915_drm.h
>>> +++ b/include/drm-uapi/i915_drm.h
>>> @@ -62,6 +62,26 @@ extern "C" {
>>>    #define I915_ERROR_UEVENT		"ERROR"
>>>    #define I915_RESET_UEVENT		"RESET"
>>> +/*
>>> + * i915_user_extension: Base class for defining a chain of extensions
>>> + *
>>> + * Many interfaces need to grow over time. In most cases we can simply
>>> + * extend the struct and have userspace pass in more data. Another option,
>>> + * as demonstrated by Vulkan's approach to providing extensions for forward
>>> + * and backward compatibility, is to use a list of optional structs to
>>> + * provide those extra details.
>>> + *
>>> + * The key advantage to using an extension chain is that it allows us to
>>> + * redefine the interface more easily than an ever growing struct of
>>> + * increasing complexity, and for large parts of that interface to be
>>> + * entirely optional. The downside is more pointer chasing; chasing across
>>> + * the boundary with pointers encapsulated inside u64.
>>> + */
>>> +struct i915_user_extension {
>>> +	__u64 next_extension;
>>> +	__u64 name;
>>> +};
>>
>> Just a note to not merge this version since my branch has accidentally
>> diverged from latest drm-tip in this respect.
> 
> yes, it slipped off my mind. Do you have any plans to rebase your
> branch? I would send the patches today.

I do have plans but I won't make it today. Will let you know.

Regards,

Tvrtko

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

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

* Re: [igt-dev] [PATCH v19 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-08 16:35   ` Tvrtko Ursulin
@ 2019-04-08 16:56     ` Andi Shyti
  0 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 16:56 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: IGT dev, Andi Shyti

Hi Tvrtko,

> > Replace the legacy for_each_engine* defines with the ones
> > implemented in the gem_engine_topology library.
> > 
> > Use whenever possible gem_engine_can_store_dword() that checks
> > class instead of flags.
> > 
> > Now the __for_each_engine_class_instance and
> > for_each_engine_class_instance are unused, remove them.
> 
> In the future please start adding per patch changelogs and in the cover
> letter just list the main changes.

I personally never liked versioning in the commit log because
it's a reference external to the current commit history.

But if this is the igt culture, I'll comply. Next time I will add
the versioning in the commit log.

> > -init(int gem_fd, const struct intel_execution_engine2 *e, uint8_t sample)
> > +init(int gem_fd, struct intel_execution_engine2 *e, uint8_t sample)
> 
> Why is const a problem here? The function only reads from the object?

It's not a problem, but I think it's not necessary. init() is not
called anymore with a 'const' variable type.

> >   	unsigned long slept;
> >   	uint64_t val, val2, ts[2];
> > @@ -347,6 +357,7 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
> >   	int fd;
> >   	ctx = gem_context_create(gem_fd);
> > +	intel_init_engine_list(gem_fd, ctx);
> 
> You didn't find this a bit ugly? I was thinking that we should maybe have a
> helper to configure the context which doesn't return the engine data struct.
> Doesn't matter I guess.

well yes, it's not very nice :)

"do it once, do it right!" I'll add a helper that just binds the
engines to the given context (without creating all the stuff we
have in init_engine_list()).

> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Thanks a lot!
Andi
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

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

* [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
                   ` (5 preceding siblings ...)
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 6/6] test: perf_pmu: use the gem_engine_topology library Andi Shyti
@ 2019-04-08 17:35 ` Patchwork
  2019-04-11 14:54 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev3) Patchwork
  2019-04-11 18:11 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev4) Patchwork
  8 siblings, 0 replies; 43+ messages in thread
From: Patchwork @ 2019-04-08 17:35 UTC (permalink / raw)
  To: Andi Shyti; +Cc: igt-dev

== Series Details ==

Series: new engine discovery interface
URL   : https://patchwork.freedesktop.org/series/59185/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_5889 -> IGTPW_2817
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_2817 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_2817, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/59185/revisions/1/mbox/

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@gem_wait@basic-busy-all:
    - fi-blb-e6850:       PASS -> FAIL +1
    - fi-bwr-2160:        PASS -> FAIL +1
    - fi-pnv-d510:        PASS -> FAIL +1

  * igt@gem_wait@basic-wait-all:
    - fi-gdg-551:         PASS -> FAIL +1

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

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

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_suspend@basic-s3:
    - fi-icl-y:           PASS -> FAIL [fdo#103375]

  * igt@i915_selftest@live_contexts:
    - fi-bdw-gvtdvm:      PASS -> DMESG-FAIL [fdo#110235 ]

  * igt@kms_cursor_legacy@basic-flip-before-cursor-varying-size:
    - fi-glk-dsi:         PASS -> INCOMPLETE [fdo#103359] / [k.org#198133]

  * igt@kms_frontbuffer_tracking@basic:
    - fi-icl-u3:          PASS -> FAIL [fdo#103167]

  
#### Possible fixes ####

  * igt@i915_selftest@live_execlists:
    - fi-apl-guc:         INCOMPLETE [fdo#103927] / [fdo#109720] -> PASS

  * igt@kms_pipe_crc_basic@nonblocking-crc-pipe-b-frame-sequence:
    - fi-byt-clapper:     FAIL [fdo#103191] / [fdo#107362] -> PASS +1

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

  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
  [fdo#103359]: https://bugs.freedesktop.org/show_bug.cgi?id=103359
  [fdo#103375]: https://bugs.freedesktop.org/show_bug.cgi?id=103375
  [fdo#103927]: https://bugs.freedesktop.org/show_bug.cgi?id=103927
  [fdo#107362]: https://bugs.freedesktop.org/show_bug.cgi?id=107362
  [fdo#109720]: https://bugs.freedesktop.org/show_bug.cgi?id=109720
  [fdo#110235 ]: https://bugs.freedesktop.org/show_bug.cgi?id=110235 
  [fdo#110246]: https://bugs.freedesktop.org/show_bug.cgi?id=110246
  [k.org#198133]: https://bugzilla.kernel.org/show_bug.cgi?id=198133


Participating hosts (49 -> 41)
------------------------------

  Additional (1): fi-icl-u2 
  Missing    (9): fi-kbl-7567u fi-ilk-m540 fi-bdw-5557u fi-byt-squawks fi-bsw-cyan fi-ctg-p8600 fi-ivb-3770 fi-bdw-samus fi-skl-6600u 


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

    * IGT: IGT_4932 -> IGTPW_2817

  CI_DRM_5889: 7cb7ad99a4f507f6025706637baae5fd16e491eb @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2817: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2817/
  IGT_4932: 08cf63a8fac11e3594b57580331fb319241a0d69 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

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

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

* Re: [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition
  2019-04-08 16:54   ` Tvrtko Ursulin
@ 2019-04-08 18:21     ` Andi Shyti
  0 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-08 18:21 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: IGT dev, Andi Shyti

Hi Tvrtko,

I forgot to answer to this one,

> > +struct intel_execution_engine2
> > +*intel_get_current_engine(struct intel_engine_data *ed)
> > +{
> 
> Our coding style is
> 
> type *
> func_name(..)

Yes.

> (Take care of all instances in source and header.)

You know I might forget :)

> > +	if (igt_only_list_subtests())
> > +		return -EPERM;
> 
> Puzzling choice of errno, not that it matters, but I am tempted to suggest
> -ENODEV.

I will can change it to ENODEV. It looked more appropriate
because if we fall into this case it doesn't mean that there is
no device, but that any ioctl to the device is "forbidden".

But, OK, I don't really mind.

> > +			if (!igt_only_list_subtests()) {
> > +				__e2->flags = gem_class_instance_to_eb_flags(fd,
> > +						e2->class, e2->instance);
> 
> Would it make sense to "poison" flags with like -1 (when listing subtests)
> so any mistakes would never have a chance to work?

yes, makes sense.

> > +/*
> > + * 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, \
> > +					class_instance[GEM_MAX_ENGINES])
> > +#define SIZEOF_QUERY		offsetof(struct drm_i915_query_engine_info, \
> > +					engines[GEM_MAX_ENGINES])
> 
> Do you need these two in the header file?

You defined the same in your "fixup" patch, so that I thought to
define i once and here.

> > +#define GEM_MAX_ENGINES		I915_EXEC_RING_MASK + 1
> > +
> > +struct intel_engine_data {
> > +	uint32_t nengines;
> > +	uint32_t n;
> > +	int error;
> 
> Unused?

It's a leftover from one of the previous reworks, it was added to
check in the for_each whether I was receiving more engines than
the limit.

I'll remove it.

> Coding style and question against the header file are the only real ones
> left. Otherwise looks good.
> 
> Regards,

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

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

* Re: [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file
  2019-04-08 16:56       ` Tvrtko Ursulin
@ 2019-04-08 18:33         ` Antonio Argenziano
  2019-04-09  7:33           ` Tvrtko Ursulin
  0 siblings, 1 reply; 43+ messages in thread
From: Antonio Argenziano @ 2019-04-08 18:33 UTC (permalink / raw)
  To: Tvrtko Ursulin, Andi Shyti; +Cc: IGT dev, Andi Shyti



On 08/04/19 09:56, Tvrtko Ursulin wrote:
> 
> On 08/04/2019 17:47, Andi Shyti wrote:
>> Hi Tvrtko,
>>
>>>> This header file is imported in order to include the two new
>>>> ioctls DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM,
>>>> DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM and DRM_IOCTL_I915_QUERY.
>>>>
>>>> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
>>>> ---
>>>>    include/drm-uapi/i915_drm.h | 361 
>>>> ++++++++++++++++++++++++++++++------
>>>>    1 file changed, 304 insertions(+), 57 deletions(-)
>>>>
>>>> diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
>>>> index 4ae1c6ff6ae6..2bbad08eb9d2 100644
>>>> --- a/include/drm-uapi/i915_drm.h
>>>> +++ b/include/drm-uapi/i915_drm.h
>>>> @@ -62,6 +62,26 @@ extern "C" {
>>>>    #define I915_ERROR_UEVENT        "ERROR"
>>>>    #define I915_RESET_UEVENT        "RESET"
>>>> +/*
>>>> + * i915_user_extension: Base class for defining a chain of extensions
>>>> + *
>>>> + * Many interfaces need to grow over time. In most cases we can simply
>>>> + * extend the struct and have userspace pass in more data. Another 
>>>> option,
>>>> + * as demonstrated by Vulkan's approach to providing extensions for 
>>>> forward
>>>> + * and backward compatibility, is to use a list of optional structs to
>>>> + * provide those extra details.
>>>> + *
>>>> + * The key advantage to using an extension chain is that it allows 
>>>> us to
>>>> + * redefine the interface more easily than an ever growing struct of
>>>> + * increasing complexity, and for large parts of that interface to be
>>>> + * entirely optional. The downside is more pointer chasing; chasing 
>>>> across
>>>> + * the boundary with pointers encapsulated inside u64.
>>>> + */
>>>> +struct i915_user_extension {
>>>> +    __u64 next_extension;
>>>> +    __u64 name;
>>>> +};
>>>
>>> Just a note to not merge this version since my branch has accidentally
>>> diverged from latest drm-tip in this respect.
>>
>> yes, it slipped off my mind. Do you have any plans to rebase your
>> branch? I would send the patches today.
> 
> I do have plans but I won't make it today. Will let you know.

Are we saying to merge the header file from a private branch? if that is 
the case, can we have 'LOCAL_' definitions of the IOCTLs you are trying 
to import. It might get messy in case the private and public version 
diverge again. If that is not the case, ignore me ;).

Antonio

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

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

* Re: [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file
  2019-04-08 18:33         ` Antonio Argenziano
@ 2019-04-09  7:33           ` Tvrtko Ursulin
  0 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-09  7:33 UTC (permalink / raw)
  To: Antonio Argenziano, Andi Shyti; +Cc: IGT dev, Andi Shyti


On 08/04/2019 19:33, Antonio Argenziano wrote:
> On 08/04/19 09:56, Tvrtko Ursulin wrote:
>>
>> On 08/04/2019 17:47, Andi Shyti wrote:
>>> Hi Tvrtko,
>>>
>>>>> This header file is imported in order to include the two new
>>>>> ioctls DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM,
>>>>> DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM and DRM_IOCTL_I915_QUERY.
>>>>>
>>>>> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
>>>>> ---
>>>>>    include/drm-uapi/i915_drm.h | 361 
>>>>> ++++++++++++++++++++++++++++++------
>>>>>    1 file changed, 304 insertions(+), 57 deletions(-)
>>>>>
>>>>> diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h
>>>>> index 4ae1c6ff6ae6..2bbad08eb9d2 100644
>>>>> --- a/include/drm-uapi/i915_drm.h
>>>>> +++ b/include/drm-uapi/i915_drm.h
>>>>> @@ -62,6 +62,26 @@ extern "C" {
>>>>>    #define I915_ERROR_UEVENT        "ERROR"
>>>>>    #define I915_RESET_UEVENT        "RESET"
>>>>> +/*
>>>>> + * i915_user_extension: Base class for defining a chain of extensions
>>>>> + *
>>>>> + * Many interfaces need to grow over time. In most cases we can 
>>>>> simply
>>>>> + * extend the struct and have userspace pass in more data. Another 
>>>>> option,
>>>>> + * as demonstrated by Vulkan's approach to providing extensions 
>>>>> for forward
>>>>> + * and backward compatibility, is to use a list of optional 
>>>>> structs to
>>>>> + * provide those extra details.
>>>>> + *
>>>>> + * The key advantage to using an extension chain is that it allows 
>>>>> us to
>>>>> + * redefine the interface more easily than an ever growing struct of
>>>>> + * increasing complexity, and for large parts of that interface to be
>>>>> + * entirely optional. The downside is more pointer chasing; 
>>>>> chasing across
>>>>> + * the boundary with pointers encapsulated inside u64.
>>>>> + */
>>>>> +struct i915_user_extension {
>>>>> +    __u64 next_extension;
>>>>> +    __u64 name;
>>>>> +};
>>>>
>>>> Just a note to not merge this version since my branch has accidentally
>>>> diverged from latest drm-tip in this respect.
>>>
>>> yes, it slipped off my mind. Do you have any plans to rebase your
>>> branch? I would send the patches today.
>>
>> I do have plans but I won't make it today. Will let you know.
> 
> Are we saying to merge the header file from a private branch? if that is 

Certainly not! :) Just making the delta, between the tree Andi uses to 
develop this and what will one day become upstream, smaller.

> the case, can we have 'LOCAL_' definitions of the IOCTLs you are trying 
> to import. It might get messy in case the private and public version 
> diverge again. If that is not the case, ignore me ;).

LOCAL_ approach would be annoying in this case since we have many tests 
and tools piled up for media scalability and uAPI still keeps getting 
tweaks.

Regards,

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

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

* [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine() Andi Shyti
@ 2019-04-11 12:26     ` Tvrtko Ursulin
  2019-04-11 12:26     ` [igt-dev] " Tvrtko Ursulin
  2019-04-11 12:28     ` [igt-dev] " Tvrtko Ursulin
  2 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 12:26 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx

From: Andi Shyti <andi.shyti@intel.com>

Replace the legacy for_each_engine* defines with the ones
implemented in the gem_engine_topology library.

Use whenever possible gem_engine_can_store_dword() that checks
class instead of flags.

Now the __for_each_engine_class_instance and
for_each_engine_class_instance are unused, remove them.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 lib/igt_gt.h     |   7 ---
 tests/perf_pmu.c | 143 +++++++++++++++++++++++++++++------------------
 2 files changed, 88 insertions(+), 62 deletions(-)

diff --git a/lib/igt_gt.h b/lib/igt_gt.h
index af4cc38a1ef7..c2ca07e03738 100644
--- a/lib/igt_gt.h
+++ b/lib/igt_gt.h
@@ -119,11 +119,4 @@ void gem_require_engine(int gem_fd,
 	igt_require(gem_has_engine(gem_fd, class, instance));
 }
 
-#define __for_each_engine_class_instance(e__) \
-	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++)
-
-#define for_each_engine_class_instance(fd__, e__) \
-	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++) \
-		for_if (gem_has_engine((fd__), (e__)->class, (e__)->instance))
-
 #endif /* IGT_GT_H */
diff --git a/tests/perf_pmu.c b/tests/perf_pmu.c
index 4f552bc2ae28..a889b552236d 100644
--- a/tests/perf_pmu.c
+++ b/tests/perf_pmu.c
@@ -72,7 +72,7 @@ static int open_group(uint64_t config, int group)
 }
 
 static void
-init(int gem_fd, const struct intel_execution_engine2 *e, uint8_t sample)
+init(int gem_fd, struct intel_execution_engine2 *e, uint8_t sample)
 {
 	int fd, err = 0;
 	bool exists;
@@ -158,11 +158,6 @@ static unsigned int measured_usleep(unsigned int usec)
 	return igt_nsec_elapsed(&ts);
 }
 
-static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
-{
-	return gem_class_instance_to_eb_flags(gem_fd, e->class, e->instance);
-}
-
 #define TEST_BUSY (1)
 #define FLAG_SYNC (2)
 #define TEST_TRAILING_IDLE (4)
@@ -170,14 +165,15 @@ static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
 #define FLAG_LONG (16)
 #define FLAG_HANG (32)
 
-static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * __spin_poll(int fd, uint32_t ctx,
+				struct intel_execution_engine2 *e)
 {
 	struct igt_spin_factory opts = {
 		.ctx = ctx,
-		.engine = flags,
+		.engine = e->flags,
 	};
 
-	if (gem_can_store_dword(fd, flags))
+	if (gem_class_can_store_dword(fd, e->class))
 		opts.flags |= IGT_SPIN_POLL_RUN;
 
 	return __igt_spin_batch_factory(fd, &opts);
@@ -209,20 +205,34 @@ static unsigned long __spin_wait(int fd, igt_spin_t *spin)
 	return igt_nsec_elapsed(&start);
 }
 
-static igt_spin_t * __spin_sync(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * __spin_sync(int fd, uint32_t ctx,
+				struct intel_execution_engine2 *e)
 {
-	igt_spin_t *spin = __spin_poll(fd, ctx, flags);
+	igt_spin_t *spin = __spin_poll(fd, ctx, e);
 
 	__spin_wait(fd, spin);
 
 	return spin;
 }
 
-static igt_spin_t * spin_sync(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * spin_sync(int fd, uint32_t ctx,
+			      struct intel_execution_engine2 *e)
 {
 	igt_require_gem(fd);
 
-	return __spin_sync(fd, ctx, flags);
+	return __spin_sync(fd, ctx, e);
+}
+
+static igt_spin_t * spin_sync_flags(int fd, uint32_t ctx, unsigned int flags)
+{
+	struct intel_execution_engine2 e = { };
+
+	e.class = gem_eb_to_class(flags);
+	e.instance = (flags & (I915_EXEC_BSD_MASK | I915_EXEC_RING_MASK)) ==
+		     (I915_EXEC_BSD | I915_EXEC_BSD_RING2) ? 1 : 0;
+	e.flags = flags;
+
+	return spin_sync(fd, ctx, &e);
 }
 
 static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
@@ -257,7 +267,7 @@ static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
 }
 
 static void
-single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
+single(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
 {
 	unsigned long slept;
 	igt_spin_t *spin;
@@ -267,7 +277,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
 
 	if (flags & TEST_BUSY)
-		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+		spin = spin_sync(gem_fd, 0, e);
 	else
 		spin = NULL;
 
@@ -303,7 +313,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 }
 
 static void
-busy_start(int gem_fd, const struct intel_execution_engine2 *e)
+busy_start(int gem_fd, struct intel_execution_engine2 *e)
 {
 	unsigned long slept;
 	uint64_t val, ts[2];
@@ -316,7 +326,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
 	 */
 	sleep(2);
 
-	spin = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = __spin_sync(gem_fd, 0, e);
 
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
 
@@ -338,7 +348,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
  * will depend on the CI systems running it a lot to detect issues.
  */
 static void
-busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
+busy_double_start(int gem_fd, struct intel_execution_engine2 *e)
 {
 	unsigned long slept;
 	uint64_t val, val2, ts[2];
@@ -347,6 +357,7 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
 	int fd;
 
 	ctx = gem_context_create(gem_fd);
+	intel_init_engine_list(gem_fd, ctx);
 
 	/*
 	 * Defeat the busy stats delayed disable, we need to guarantee we are
@@ -359,11 +370,11 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
 	 * re-submission in execlists mode. Make sure busyness is correctly
 	 * reported with the engine busy, and after the engine went idle.
 	 */
-	spin[0] = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin[0] = __spin_sync(gem_fd, 0, e);
 	usleep(500e3);
 	spin[1] = __igt_spin_batch_new(gem_fd,
 				       .ctx = ctx,
-				       .engine = e2ring(gem_fd, e));
+				       .engine = e->flags);
 
 	/*
 	 * Open PMU as fast as possible after the second spin batch in attempt
@@ -421,10 +432,10 @@ static void log_busy(unsigned int num_engines, uint64_t *val)
 }
 
 static void
-busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
+busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
 	       const unsigned int num_engines, unsigned int flags)
 {
-	const struct intel_execution_engine2 *e_;
+	struct intel_execution_engine2 *e_;
 	uint64_t tval[2][num_engines];
 	unsigned int busy_idx = 0, i;
 	uint64_t val[num_engines];
@@ -434,8 +445,8 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 	i = 0;
 	fd[0] = -1;
-	for_each_engine_class_instance(gem_fd, e_) {
-		if (e == e_)
+	__for_each_physical_engine(gem_fd, e_) {
+		if (e->class == e_->class && e->instance == e_->instance)
 			busy_idx = i;
 
 		fd[i++] = open_group(I915_PMU_ENGINE_BUSY(e_->class,
@@ -445,7 +456,7 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 	igt_assert_eq(i, num_engines);
 
-	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = spin_sync(gem_fd, 0, e);
 	pmu_read_multi(fd[0], num_engines, tval[0]);
 	slept = measured_usleep(batch_duration_ns / 1000);
 	if (flags & TEST_TRAILING_IDLE)
@@ -472,23 +483,23 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 static void
 __submit_spin_batch(int gem_fd, igt_spin_t *spin,
-		    const struct intel_execution_engine2 *e,
+		    struct intel_execution_engine2 *e,
 		    int offset)
 {
 	struct drm_i915_gem_execbuffer2 eb = spin->execbuf;
 
 	eb.flags &= ~(0x3f | I915_EXEC_BSD_MASK);
-	eb.flags |= e2ring(gem_fd, e) | I915_EXEC_NO_RELOC;
+	eb.flags |= e->flags | I915_EXEC_NO_RELOC;
 	eb.batch_start_offset += offset;
 
 	gem_execbuf(gem_fd, &eb);
 }
 
 static void
-most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
+most_busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
 		    const unsigned int num_engines, unsigned int flags)
 {
-	const struct intel_execution_engine2 *e_;
+	struct intel_execution_engine2 *e_;
 	uint64_t tval[2][num_engines];
 	uint64_t val[num_engines];
 	int fd[num_engines];
@@ -497,13 +508,13 @@ most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 	unsigned int idle_idx, i;
 
 	i = 0;
-	for_each_engine_class_instance(gem_fd, e_) {
-		if (e == e_)
+	__for_each_physical_engine(gem_fd, e_) {
+		if (e->class == e_->class && e->instance == e_->instance)
 			idle_idx = i;
 		else if (spin)
 			__submit_spin_batch(gem_fd, spin, e_, 64);
 		else
-			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e_));
+			spin = __spin_poll(gem_fd, 0, e_);
 
 		val[i++] = I915_PMU_ENGINE_BUSY(e_->class, e_->instance);
 	}
@@ -545,7 +556,7 @@ static void
 all_busy_check_all(int gem_fd, const unsigned int num_engines,
 		   unsigned int flags)
 {
-	const struct intel_execution_engine2 *e;
+	struct intel_execution_engine2 *e;
 	uint64_t tval[2][num_engines];
 	uint64_t val[num_engines];
 	int fd[num_engines];
@@ -554,11 +565,11 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
 	unsigned int i;
 
 	i = 0;
-	for_each_engine_class_instance(gem_fd, e) {
+	__for_each_physical_engine(gem_fd, e) {
 		if (spin)
 			__submit_spin_batch(gem_fd, spin, e, 64);
 		else
-			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e));
+			spin = __spin_poll(gem_fd, 0, e);
 
 		val[i++] = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	}
@@ -592,7 +603,7 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
 }
 
 static void
-no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
+no_sema(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
 {
 	igt_spin_t *spin;
 	uint64_t val[2][2];
@@ -602,7 +613,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 	open_group(I915_PMU_ENGINE_WAIT(e->class, e->instance), fd);
 
 	if (flags & TEST_BUSY)
-		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+		spin = spin_sync(gem_fd, 0, e);
 	else
 		spin = NULL;
 
@@ -631,7 +642,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 #define   MI_SEMAPHORE_SAD_GTE_SDD	(1<<12)
 
 static void
-sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
+sema_wait(int gem_fd, struct intel_execution_engine2 *e,
 	  unsigned int flags)
 {
 	struct drm_i915_gem_relocation_entry reloc[2] = {};
@@ -689,7 +700,7 @@ sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
 
 	eb.buffer_count = 2;
 	eb.buffers_ptr = to_user_pointer(obj);
-	eb.flags = e2ring(gem_fd, e);
+	eb.flags = e->flags;
 
 	/**
 	 * Start the semaphore wait PMU and after some known time let the above
@@ -792,7 +803,7 @@ static int wait_vblank(int fd, union drm_wait_vblank *vbl)
 }
 
 static void
-event_wait(int gem_fd, const struct intel_execution_engine2 *e)
+event_wait(int gem_fd, struct intel_execution_engine2 *e)
 {
 	struct drm_i915_gem_exec_object2 obj = { };
 	struct drm_i915_gem_execbuffer2 eb = { };
@@ -845,7 +856,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
 
 	eb.buffer_count = 1;
 	eb.buffers_ptr = to_user_pointer(&obj);
-	eb.flags = e2ring(gem_fd, e) | I915_EXEC_SECURE;
+	eb.flags = e->flags | I915_EXEC_SECURE;
 
 	for_each_pipe_with_valid_output(&data.display, p, output) {
 		struct igt_helper_process waiter = { };
@@ -917,7 +928,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
 }
 
 static void
-multi_client(int gem_fd, const struct intel_execution_engine2 *e)
+multi_client(int gem_fd, struct intel_execution_engine2 *e)
 {
 	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	unsigned long slept[2];
@@ -936,7 +947,7 @@ multi_client(int gem_fd, const struct intel_execution_engine2 *e)
 	 */
 	fd[1] = open_pmu(config);
 
-	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = spin_sync(gem_fd, 0, e);
 
 	val[0] = val[1] = __pmu_read_single(fd[0], &ts[0]);
 	slept[1] = measured_usleep(batch_duration_ns / 1000);
@@ -1039,6 +1050,7 @@ static void cpu_hotplug(int gem_fd)
 	igt_spin_t *spin[2];
 	uint64_t ts[2];
 	uint64_t val;
+	uint32_t ctx;
 	int link[2];
 	int fd, ret;
 	int cur = 0;
@@ -1046,14 +1058,18 @@ static void cpu_hotplug(int gem_fd)
 
 	igt_require(cpu0_hotplug_support());
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(I915_ENGINE_CLASS_RENDER, 0));
 
 	/*
 	 * Create two spinners so test can ensure shorter gaps in engine
 	 * busyness as it is terminating one and re-starting the other.
 	 */
-	spin[0] = igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
-	spin[1] = __igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
+	spin[0] = igt_spin_batch_new(gem_fd,
+				     .engine = I915_EXEC_RENDER, .ctx = ctx);
+	spin[1] = __igt_spin_batch_new(gem_fd,
+				       .engine = I915_EXEC_RENDER, .ctx = ctx);
 
 	val = __pmu_read_single(fd, &ts[0]);
 
@@ -1137,6 +1153,7 @@ static void cpu_hotplug(int gem_fd)
 
 		igt_spin_batch_free(gem_fd, spin[cur]);
 		spin[cur] = __igt_spin_batch_new(gem_fd,
+						 .ctx = ctx,
 						 .engine = I915_EXEC_RENDER);
 		cur ^= 1;
 	}
@@ -1150,6 +1167,7 @@ static void cpu_hotplug(int gem_fd)
 	igt_waitchildren();
 	close(fd);
 	close(link[0]);
+	gem_context_destroy(gem_fd, ctx);
 
 	/* Skip if child signals a problem with offlining a CPU. */
 	igt_skip_on(buf == 's');
@@ -1165,17 +1183,21 @@ test_interrupts(int gem_fd)
 	igt_spin_t *spin[target];
 	struct pollfd pfd;
 	uint64_t idle, busy;
+	uint32_t ctx;
 	int fence_fd;
 	int fd;
 
 	gem_quiescent_gpu(gem_fd);
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_INTERRUPTS);
 
 	/* Queue spinning batches. */
 	for (int i = 0; i < target; i++) {
 		spin[i] = __igt_spin_batch_new(gem_fd,
 					       .engine = I915_EXEC_RENDER,
+					       .ctx = ctx,
 					       .flags = IGT_SPIN_FENCE_OUT);
 		if (i == 0) {
 			fence_fd = spin[i]->out_fence;
@@ -1217,6 +1239,7 @@ test_interrupts(int gem_fd)
 	/* Check at least as many interrupts has been generated. */
 	busy = pmu_read_single(fd) - idle;
 	close(fd);
+	gem_context_destroy(gem_fd, ctx);
 
 	igt_assert_lte(target, busy);
 }
@@ -1229,15 +1252,19 @@ test_interrupts_sync(int gem_fd)
 	igt_spin_t *spin[target];
 	struct pollfd pfd;
 	uint64_t idle, busy;
+	uint32_t ctx;
 	int fd;
 
 	gem_quiescent_gpu(gem_fd);
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_INTERRUPTS);
 
 	/* Queue spinning batches. */
 	for (int i = 0; i < target; i++)
 		spin[i] = __igt_spin_batch_new(gem_fd,
+					       .ctx = ctx,
 					       .flags = IGT_SPIN_FENCE_OUT);
 
 	/* Wait for idle state. */
@@ -1262,6 +1289,7 @@ test_interrupts_sync(int gem_fd)
 	/* Check at least as many interrupts has been generated. */
 	busy = pmu_read_single(fd) - idle;
 	close(fd);
+	gem_context_destroy(gem_fd, ctx);
 
 	igt_assert_lte(target, busy);
 }
@@ -1274,6 +1302,9 @@ test_frequency(int gem_fd)
 	double min[2], max[2];
 	igt_spin_t *spin;
 	int fd, sysfs;
+	uint32_t ctx;
+
+	ctx = gem_context_create(gem_fd);
 
 	sysfs = igt_sysfs_open(gem_fd);
 	igt_require(sysfs >= 0);
@@ -1301,7 +1332,7 @@ test_frequency(int gem_fd)
 	igt_require(igt_sysfs_get_u32(sysfs, "gt_boost_freq_mhz") == min_freq);
 
 	gem_quiescent_gpu(gem_fd); /* Idle to be sure the change takes effect */
-	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
+	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
 
 	slept = pmu_read_multi(fd, 2, start);
 	measured_usleep(batch_duration_ns / 1000);
@@ -1327,7 +1358,7 @@ test_frequency(int gem_fd)
 	igt_require(igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz") == max_freq);
 
 	gem_quiescent_gpu(gem_fd);
-	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
+	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
 
 	slept = pmu_read_multi(fd, 2, start);
 	measured_usleep(batch_duration_ns / 1000);
@@ -1348,6 +1379,8 @@ test_frequency(int gem_fd)
 			 min_freq, igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz"));
 	close(fd);
 
+	gem_context_destroy(gem_fd, ctx);
+
 	igt_info("Min frequency: requested %.1f, actual %.1f\n",
 		 min[0], min[1]);
 	igt_info("Max frequency: requested %.1f, actual %.1f\n",
@@ -1448,7 +1481,7 @@ test_rc6(int gem_fd, unsigned int flags)
 }
 
 static void
-test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
+test_enable_race(int gem_fd, struct intel_execution_engine2 *e)
 {
 	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	struct igt_helper_process engine_load = { };
@@ -1465,7 +1498,7 @@ test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
 
 	eb.buffer_count = 1;
 	eb.buffers_ptr = to_user_pointer(&obj);
-	eb.flags = e2ring(gem_fd, e);
+	eb.flags = e->flags;
 
 	/*
 	 * This test is probabilistic so run in a few times to increase the
@@ -1520,7 +1553,7 @@ static void __rearm_spin_batch(igt_spin_t *spin)
 	__assert_within(x, ref, tolerance, tolerance)
 
 static void
-accuracy(int gem_fd, const struct intel_execution_engine2 *e,
+accuracy(int gem_fd, struct intel_execution_engine2 *e,
 	 unsigned long target_busy_pct,
 	 unsigned long target_iters)
 {
@@ -1570,7 +1603,7 @@ accuracy(int gem_fd, const struct intel_execution_engine2 *e,
 		igt_spin_t *spin;
 
 		/* Allocate our spin batch and idle it. */
-		spin = igt_spin_batch_new(gem_fd, .engine = e2ring(gem_fd, e));
+		spin = igt_spin_batch_new(gem_fd, .engine = e->flags);
 		igt_spin_batch_end(spin);
 		gem_sync(gem_fd, spin->handle);
 
@@ -1674,7 +1707,7 @@ igt_main
 				I915_PMU_LAST - __I915_PMU_OTHER(0) + 1;
 	unsigned int num_engines = 0;
 	int fd = -1;
-	const struct intel_execution_engine2 *e;
+	struct intel_execution_engine2 *e;
 	unsigned int i;
 
 	igt_fixture {
@@ -1683,7 +1716,7 @@ igt_main
 		igt_require_gem(fd);
 		igt_require(i915_type_id() > 0);
 
-		for_each_engine_class_instance(fd, e)
+		__for_each_physical_engine(fd, e)
 			num_engines++;
 	}
 
@@ -1693,7 +1726,7 @@ igt_main
 	igt_subtest("invalid-init")
 		invalid_init();
 
-	__for_each_engine_class_instance(e) {
+	__for_each_physical_engine(fd, e) {
 		const unsigned int pct[] = { 2, 50, 98 };
 
 		/**
@@ -1897,7 +1930,7 @@ igt_main
 			gem_quiescent_gpu(fd);
 		}
 
-		__for_each_engine_class_instance(e) {
+		__for_each_physical_engine(render_fd, e) {
 			igt_subtest_group {
 				igt_fixture {
 					gem_require_engine(render_fd,
-- 
2.19.1

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

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

* [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 12:26     ` Tvrtko Ursulin
  0 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 12:26 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx

From: Andi Shyti <andi.shyti@intel.com>

Replace the legacy for_each_engine* defines with the ones
implemented in the gem_engine_topology library.

Use whenever possible gem_engine_can_store_dword() that checks
class instead of flags.

Now the __for_each_engine_class_instance and
for_each_engine_class_instance are unused, remove them.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 lib/igt_gt.h     |   7 ---
 tests/perf_pmu.c | 143 +++++++++++++++++++++++++++++------------------
 2 files changed, 88 insertions(+), 62 deletions(-)

diff --git a/lib/igt_gt.h b/lib/igt_gt.h
index af4cc38a1ef7..c2ca07e03738 100644
--- a/lib/igt_gt.h
+++ b/lib/igt_gt.h
@@ -119,11 +119,4 @@ void gem_require_engine(int gem_fd,
 	igt_require(gem_has_engine(gem_fd, class, instance));
 }
 
-#define __for_each_engine_class_instance(e__) \
-	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++)
-
-#define for_each_engine_class_instance(fd__, e__) \
-	for ((e__) = intel_execution_engines2; (e__)->name; (e__)++) \
-		for_if (gem_has_engine((fd__), (e__)->class, (e__)->instance))
-
 #endif /* IGT_GT_H */
diff --git a/tests/perf_pmu.c b/tests/perf_pmu.c
index 4f552bc2ae28..a889b552236d 100644
--- a/tests/perf_pmu.c
+++ b/tests/perf_pmu.c
@@ -72,7 +72,7 @@ static int open_group(uint64_t config, int group)
 }
 
 static void
-init(int gem_fd, const struct intel_execution_engine2 *e, uint8_t sample)
+init(int gem_fd, struct intel_execution_engine2 *e, uint8_t sample)
 {
 	int fd, err = 0;
 	bool exists;
@@ -158,11 +158,6 @@ static unsigned int measured_usleep(unsigned int usec)
 	return igt_nsec_elapsed(&ts);
 }
 
-static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
-{
-	return gem_class_instance_to_eb_flags(gem_fd, e->class, e->instance);
-}
-
 #define TEST_BUSY (1)
 #define FLAG_SYNC (2)
 #define TEST_TRAILING_IDLE (4)
@@ -170,14 +165,15 @@ static unsigned int e2ring(int gem_fd, const struct intel_execution_engine2 *e)
 #define FLAG_LONG (16)
 #define FLAG_HANG (32)
 
-static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * __spin_poll(int fd, uint32_t ctx,
+				struct intel_execution_engine2 *e)
 {
 	struct igt_spin_factory opts = {
 		.ctx = ctx,
-		.engine = flags,
+		.engine = e->flags,
 	};
 
-	if (gem_can_store_dword(fd, flags))
+	if (gem_class_can_store_dword(fd, e->class))
 		opts.flags |= IGT_SPIN_POLL_RUN;
 
 	return __igt_spin_batch_factory(fd, &opts);
@@ -209,20 +205,34 @@ static unsigned long __spin_wait(int fd, igt_spin_t *spin)
 	return igt_nsec_elapsed(&start);
 }
 
-static igt_spin_t * __spin_sync(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * __spin_sync(int fd, uint32_t ctx,
+				struct intel_execution_engine2 *e)
 {
-	igt_spin_t *spin = __spin_poll(fd, ctx, flags);
+	igt_spin_t *spin = __spin_poll(fd, ctx, e);
 
 	__spin_wait(fd, spin);
 
 	return spin;
 }
 
-static igt_spin_t * spin_sync(int fd, uint32_t ctx, unsigned long flags)
+static igt_spin_t * spin_sync(int fd, uint32_t ctx,
+			      struct intel_execution_engine2 *e)
 {
 	igt_require_gem(fd);
 
-	return __spin_sync(fd, ctx, flags);
+	return __spin_sync(fd, ctx, e);
+}
+
+static igt_spin_t * spin_sync_flags(int fd, uint32_t ctx, unsigned int flags)
+{
+	struct intel_execution_engine2 e = { };
+
+	e.class = gem_eb_to_class(flags);
+	e.instance = (flags & (I915_EXEC_BSD_MASK | I915_EXEC_RING_MASK)) ==
+		     (I915_EXEC_BSD | I915_EXEC_BSD_RING2) ? 1 : 0;
+	e.flags = flags;
+
+	return spin_sync(fd, ctx, &e);
 }
 
 static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
@@ -257,7 +267,7 @@ static void end_spin(int fd, igt_spin_t *spin, unsigned int flags)
 }
 
 static void
-single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
+single(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
 {
 	unsigned long slept;
 	igt_spin_t *spin;
@@ -267,7 +277,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
 
 	if (flags & TEST_BUSY)
-		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+		spin = spin_sync(gem_fd, 0, e);
 	else
 		spin = NULL;
 
@@ -303,7 +313,7 @@ single(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 }
 
 static void
-busy_start(int gem_fd, const struct intel_execution_engine2 *e)
+busy_start(int gem_fd, struct intel_execution_engine2 *e)
 {
 	unsigned long slept;
 	uint64_t val, ts[2];
@@ -316,7 +326,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
 	 */
 	sleep(2);
 
-	spin = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = __spin_sync(gem_fd, 0, e);
 
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(e->class, e->instance));
 
@@ -338,7 +348,7 @@ busy_start(int gem_fd, const struct intel_execution_engine2 *e)
  * will depend on the CI systems running it a lot to detect issues.
  */
 static void
-busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
+busy_double_start(int gem_fd, struct intel_execution_engine2 *e)
 {
 	unsigned long slept;
 	uint64_t val, val2, ts[2];
@@ -347,6 +357,7 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
 	int fd;
 
 	ctx = gem_context_create(gem_fd);
+	intel_init_engine_list(gem_fd, ctx);
 
 	/*
 	 * Defeat the busy stats delayed disable, we need to guarantee we are
@@ -359,11 +370,11 @@ busy_double_start(int gem_fd, const struct intel_execution_engine2 *e)
 	 * re-submission in execlists mode. Make sure busyness is correctly
 	 * reported with the engine busy, and after the engine went idle.
 	 */
-	spin[0] = __spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin[0] = __spin_sync(gem_fd, 0, e);
 	usleep(500e3);
 	spin[1] = __igt_spin_batch_new(gem_fd,
 				       .ctx = ctx,
-				       .engine = e2ring(gem_fd, e));
+				       .engine = e->flags);
 
 	/*
 	 * Open PMU as fast as possible after the second spin batch in attempt
@@ -421,10 +432,10 @@ static void log_busy(unsigned int num_engines, uint64_t *val)
 }
 
 static void
-busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
+busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
 	       const unsigned int num_engines, unsigned int flags)
 {
-	const struct intel_execution_engine2 *e_;
+	struct intel_execution_engine2 *e_;
 	uint64_t tval[2][num_engines];
 	unsigned int busy_idx = 0, i;
 	uint64_t val[num_engines];
@@ -434,8 +445,8 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 	i = 0;
 	fd[0] = -1;
-	for_each_engine_class_instance(gem_fd, e_) {
-		if (e == e_)
+	__for_each_physical_engine(gem_fd, e_) {
+		if (e->class == e_->class && e->instance == e_->instance)
 			busy_idx = i;
 
 		fd[i++] = open_group(I915_PMU_ENGINE_BUSY(e_->class,
@@ -445,7 +456,7 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 	igt_assert_eq(i, num_engines);
 
-	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = spin_sync(gem_fd, 0, e);
 	pmu_read_multi(fd[0], num_engines, tval[0]);
 	slept = measured_usleep(batch_duration_ns / 1000);
 	if (flags & TEST_TRAILING_IDLE)
@@ -472,23 +483,23 @@ busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 
 static void
 __submit_spin_batch(int gem_fd, igt_spin_t *spin,
-		    const struct intel_execution_engine2 *e,
+		    struct intel_execution_engine2 *e,
 		    int offset)
 {
 	struct drm_i915_gem_execbuffer2 eb = spin->execbuf;
 
 	eb.flags &= ~(0x3f | I915_EXEC_BSD_MASK);
-	eb.flags |= e2ring(gem_fd, e) | I915_EXEC_NO_RELOC;
+	eb.flags |= e->flags | I915_EXEC_NO_RELOC;
 	eb.batch_start_offset += offset;
 
 	gem_execbuf(gem_fd, &eb);
 }
 
 static void
-most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
+most_busy_check_all(int gem_fd, struct intel_execution_engine2 *e,
 		    const unsigned int num_engines, unsigned int flags)
 {
-	const struct intel_execution_engine2 *e_;
+	struct intel_execution_engine2 *e_;
 	uint64_t tval[2][num_engines];
 	uint64_t val[num_engines];
 	int fd[num_engines];
@@ -497,13 +508,13 @@ most_busy_check_all(int gem_fd, const struct intel_execution_engine2 *e,
 	unsigned int idle_idx, i;
 
 	i = 0;
-	for_each_engine_class_instance(gem_fd, e_) {
-		if (e == e_)
+	__for_each_physical_engine(gem_fd, e_) {
+		if (e->class == e_->class && e->instance == e_->instance)
 			idle_idx = i;
 		else if (spin)
 			__submit_spin_batch(gem_fd, spin, e_, 64);
 		else
-			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e_));
+			spin = __spin_poll(gem_fd, 0, e_);
 
 		val[i++] = I915_PMU_ENGINE_BUSY(e_->class, e_->instance);
 	}
@@ -545,7 +556,7 @@ static void
 all_busy_check_all(int gem_fd, const unsigned int num_engines,
 		   unsigned int flags)
 {
-	const struct intel_execution_engine2 *e;
+	struct intel_execution_engine2 *e;
 	uint64_t tval[2][num_engines];
 	uint64_t val[num_engines];
 	int fd[num_engines];
@@ -554,11 +565,11 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
 	unsigned int i;
 
 	i = 0;
-	for_each_engine_class_instance(gem_fd, e) {
+	__for_each_physical_engine(gem_fd, e) {
 		if (spin)
 			__submit_spin_batch(gem_fd, spin, e, 64);
 		else
-			spin = __spin_poll(gem_fd, 0, e2ring(gem_fd, e));
+			spin = __spin_poll(gem_fd, 0, e);
 
 		val[i++] = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	}
@@ -592,7 +603,7 @@ all_busy_check_all(int gem_fd, const unsigned int num_engines,
 }
 
 static void
-no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
+no_sema(int gem_fd, struct intel_execution_engine2 *e, unsigned int flags)
 {
 	igt_spin_t *spin;
 	uint64_t val[2][2];
@@ -602,7 +613,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 	open_group(I915_PMU_ENGINE_WAIT(e->class, e->instance), fd);
 
 	if (flags & TEST_BUSY)
-		spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+		spin = spin_sync(gem_fd, 0, e);
 	else
 		spin = NULL;
 
@@ -631,7 +642,7 @@ no_sema(int gem_fd, const struct intel_execution_engine2 *e, unsigned int flags)
 #define   MI_SEMAPHORE_SAD_GTE_SDD	(1<<12)
 
 static void
-sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
+sema_wait(int gem_fd, struct intel_execution_engine2 *e,
 	  unsigned int flags)
 {
 	struct drm_i915_gem_relocation_entry reloc[2] = {};
@@ -689,7 +700,7 @@ sema_wait(int gem_fd, const struct intel_execution_engine2 *e,
 
 	eb.buffer_count = 2;
 	eb.buffers_ptr = to_user_pointer(obj);
-	eb.flags = e2ring(gem_fd, e);
+	eb.flags = e->flags;
 
 	/**
 	 * Start the semaphore wait PMU and after some known time let the above
@@ -792,7 +803,7 @@ static int wait_vblank(int fd, union drm_wait_vblank *vbl)
 }
 
 static void
-event_wait(int gem_fd, const struct intel_execution_engine2 *e)
+event_wait(int gem_fd, struct intel_execution_engine2 *e)
 {
 	struct drm_i915_gem_exec_object2 obj = { };
 	struct drm_i915_gem_execbuffer2 eb = { };
@@ -845,7 +856,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
 
 	eb.buffer_count = 1;
 	eb.buffers_ptr = to_user_pointer(&obj);
-	eb.flags = e2ring(gem_fd, e) | I915_EXEC_SECURE;
+	eb.flags = e->flags | I915_EXEC_SECURE;
 
 	for_each_pipe_with_valid_output(&data.display, p, output) {
 		struct igt_helper_process waiter = { };
@@ -917,7 +928,7 @@ event_wait(int gem_fd, const struct intel_execution_engine2 *e)
 }
 
 static void
-multi_client(int gem_fd, const struct intel_execution_engine2 *e)
+multi_client(int gem_fd, struct intel_execution_engine2 *e)
 {
 	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	unsigned long slept[2];
@@ -936,7 +947,7 @@ multi_client(int gem_fd, const struct intel_execution_engine2 *e)
 	 */
 	fd[1] = open_pmu(config);
 
-	spin = spin_sync(gem_fd, 0, e2ring(gem_fd, e));
+	spin = spin_sync(gem_fd, 0, e);
 
 	val[0] = val[1] = __pmu_read_single(fd[0], &ts[0]);
 	slept[1] = measured_usleep(batch_duration_ns / 1000);
@@ -1039,6 +1050,7 @@ static void cpu_hotplug(int gem_fd)
 	igt_spin_t *spin[2];
 	uint64_t ts[2];
 	uint64_t val;
+	uint32_t ctx;
 	int link[2];
 	int fd, ret;
 	int cur = 0;
@@ -1046,14 +1058,18 @@ static void cpu_hotplug(int gem_fd)
 
 	igt_require(cpu0_hotplug_support());
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_ENGINE_BUSY(I915_ENGINE_CLASS_RENDER, 0));
 
 	/*
 	 * Create two spinners so test can ensure shorter gaps in engine
 	 * busyness as it is terminating one and re-starting the other.
 	 */
-	spin[0] = igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
-	spin[1] = __igt_spin_batch_new(gem_fd, .engine = I915_EXEC_RENDER);
+	spin[0] = igt_spin_batch_new(gem_fd,
+				     .engine = I915_EXEC_RENDER, .ctx = ctx);
+	spin[1] = __igt_spin_batch_new(gem_fd,
+				       .engine = I915_EXEC_RENDER, .ctx = ctx);
 
 	val = __pmu_read_single(fd, &ts[0]);
 
@@ -1137,6 +1153,7 @@ static void cpu_hotplug(int gem_fd)
 
 		igt_spin_batch_free(gem_fd, spin[cur]);
 		spin[cur] = __igt_spin_batch_new(gem_fd,
+						 .ctx = ctx,
 						 .engine = I915_EXEC_RENDER);
 		cur ^= 1;
 	}
@@ -1150,6 +1167,7 @@ static void cpu_hotplug(int gem_fd)
 	igt_waitchildren();
 	close(fd);
 	close(link[0]);
+	gem_context_destroy(gem_fd, ctx);
 
 	/* Skip if child signals a problem with offlining a CPU. */
 	igt_skip_on(buf == 's');
@@ -1165,17 +1183,21 @@ test_interrupts(int gem_fd)
 	igt_spin_t *spin[target];
 	struct pollfd pfd;
 	uint64_t idle, busy;
+	uint32_t ctx;
 	int fence_fd;
 	int fd;
 
 	gem_quiescent_gpu(gem_fd);
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_INTERRUPTS);
 
 	/* Queue spinning batches. */
 	for (int i = 0; i < target; i++) {
 		spin[i] = __igt_spin_batch_new(gem_fd,
 					       .engine = I915_EXEC_RENDER,
+					       .ctx = ctx,
 					       .flags = IGT_SPIN_FENCE_OUT);
 		if (i == 0) {
 			fence_fd = spin[i]->out_fence;
@@ -1217,6 +1239,7 @@ test_interrupts(int gem_fd)
 	/* Check at least as many interrupts has been generated. */
 	busy = pmu_read_single(fd) - idle;
 	close(fd);
+	gem_context_destroy(gem_fd, ctx);
 
 	igt_assert_lte(target, busy);
 }
@@ -1229,15 +1252,19 @@ test_interrupts_sync(int gem_fd)
 	igt_spin_t *spin[target];
 	struct pollfd pfd;
 	uint64_t idle, busy;
+	uint32_t ctx;
 	int fd;
 
 	gem_quiescent_gpu(gem_fd);
 
+	ctx = gem_context_create(gem_fd);
+
 	fd = open_pmu(I915_PMU_INTERRUPTS);
 
 	/* Queue spinning batches. */
 	for (int i = 0; i < target; i++)
 		spin[i] = __igt_spin_batch_new(gem_fd,
+					       .ctx = ctx,
 					       .flags = IGT_SPIN_FENCE_OUT);
 
 	/* Wait for idle state. */
@@ -1262,6 +1289,7 @@ test_interrupts_sync(int gem_fd)
 	/* Check at least as many interrupts has been generated. */
 	busy = pmu_read_single(fd) - idle;
 	close(fd);
+	gem_context_destroy(gem_fd, ctx);
 
 	igt_assert_lte(target, busy);
 }
@@ -1274,6 +1302,9 @@ test_frequency(int gem_fd)
 	double min[2], max[2];
 	igt_spin_t *spin;
 	int fd, sysfs;
+	uint32_t ctx;
+
+	ctx = gem_context_create(gem_fd);
 
 	sysfs = igt_sysfs_open(gem_fd);
 	igt_require(sysfs >= 0);
@@ -1301,7 +1332,7 @@ test_frequency(int gem_fd)
 	igt_require(igt_sysfs_get_u32(sysfs, "gt_boost_freq_mhz") == min_freq);
 
 	gem_quiescent_gpu(gem_fd); /* Idle to be sure the change takes effect */
-	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
+	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
 
 	slept = pmu_read_multi(fd, 2, start);
 	measured_usleep(batch_duration_ns / 1000);
@@ -1327,7 +1358,7 @@ test_frequency(int gem_fd)
 	igt_require(igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz") == max_freq);
 
 	gem_quiescent_gpu(gem_fd);
-	spin = spin_sync(gem_fd, 0, I915_EXEC_RENDER);
+	spin = spin_sync_flags(gem_fd, ctx, I915_EXEC_RENDER);
 
 	slept = pmu_read_multi(fd, 2, start);
 	measured_usleep(batch_duration_ns / 1000);
@@ -1348,6 +1379,8 @@ test_frequency(int gem_fd)
 			 min_freq, igt_sysfs_get_u32(sysfs, "gt_min_freq_mhz"));
 	close(fd);
 
+	gem_context_destroy(gem_fd, ctx);
+
 	igt_info("Min frequency: requested %.1f, actual %.1f\n",
 		 min[0], min[1]);
 	igt_info("Max frequency: requested %.1f, actual %.1f\n",
@@ -1448,7 +1481,7 @@ test_rc6(int gem_fd, unsigned int flags)
 }
 
 static void
-test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
+test_enable_race(int gem_fd, struct intel_execution_engine2 *e)
 {
 	uint64_t config = I915_PMU_ENGINE_BUSY(e->class, e->instance);
 	struct igt_helper_process engine_load = { };
@@ -1465,7 +1498,7 @@ test_enable_race(int gem_fd, const struct intel_execution_engine2 *e)
 
 	eb.buffer_count = 1;
 	eb.buffers_ptr = to_user_pointer(&obj);
-	eb.flags = e2ring(gem_fd, e);
+	eb.flags = e->flags;
 
 	/*
 	 * This test is probabilistic so run in a few times to increase the
@@ -1520,7 +1553,7 @@ static void __rearm_spin_batch(igt_spin_t *spin)
 	__assert_within(x, ref, tolerance, tolerance)
 
 static void
-accuracy(int gem_fd, const struct intel_execution_engine2 *e,
+accuracy(int gem_fd, struct intel_execution_engine2 *e,
 	 unsigned long target_busy_pct,
 	 unsigned long target_iters)
 {
@@ -1570,7 +1603,7 @@ accuracy(int gem_fd, const struct intel_execution_engine2 *e,
 		igt_spin_t *spin;
 
 		/* Allocate our spin batch and idle it. */
-		spin = igt_spin_batch_new(gem_fd, .engine = e2ring(gem_fd, e));
+		spin = igt_spin_batch_new(gem_fd, .engine = e->flags);
 		igt_spin_batch_end(spin);
 		gem_sync(gem_fd, spin->handle);
 
@@ -1674,7 +1707,7 @@ igt_main
 				I915_PMU_LAST - __I915_PMU_OTHER(0) + 1;
 	unsigned int num_engines = 0;
 	int fd = -1;
-	const struct intel_execution_engine2 *e;
+	struct intel_execution_engine2 *e;
 	unsigned int i;
 
 	igt_fixture {
@@ -1683,7 +1716,7 @@ igt_main
 		igt_require_gem(fd);
 		igt_require(i915_type_id() > 0);
 
-		for_each_engine_class_instance(fd, e)
+		__for_each_physical_engine(fd, e)
 			num_engines++;
 	}
 
@@ -1693,7 +1726,7 @@ igt_main
 	igt_subtest("invalid-init")
 		invalid_init();
 
-	__for_each_engine_class_instance(e) {
+	__for_each_physical_engine(fd, e) {
 		const unsigned int pct[] = { 2, 50, 98 };
 
 		/**
@@ -1897,7 +1930,7 @@ igt_main
 			gem_quiescent_gpu(fd);
 		}
 
-		__for_each_engine_class_instance(e) {
+		__for_each_physical_engine(render_fd, e) {
 			igt_subtest_group {
 				igt_fixture {
 					gem_require_engine(render_fd,
-- 
2.19.1

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

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

* [RFT i-g-t 5/6] lib: igt_dummyload: use for_each_context_engine()
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine() Andi Shyti
@ 2019-04-11 12:28     ` Tvrtko Ursulin
  2019-04-11 12:26     ` [igt-dev] " Tvrtko Ursulin
  2019-04-11 12:28     ` [igt-dev] " Tvrtko Ursulin
  2 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 12:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx

From: Andi Shyti <andi.shyti@intel.com>

With the new getparam/setparam api, engines are mapped to
context. Use for_each_context_engine() to loop through existing
engines.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
Just some debug to get more data from CI.
---
 lib/igt_dummyload.c | 38 +++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 47f6b92b424b..e7f3f480dc26 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -39,6 +39,7 @@
 #include "ioctl_wrappers.h"
 #include "sw_sync.h"
 #include "igt_vgem.h"
+#include "i915/gem_engine_topology.h"
 #include "i915/gem_mman.h"
 
 /**
@@ -86,7 +87,7 @@ emit_recursive_batch(igt_spin_t *spin,
 	struct drm_i915_gem_relocation_entry relocs[2], *r;
 	struct drm_i915_gem_execbuffer2 *execbuf;
 	struct drm_i915_gem_exec_object2 *obj;
-	unsigned int engines[16];
+	unsigned int flags[GEM_MAX_ENGINES];
 	unsigned int nengine;
 	int fence_fd = -1;
 	uint32_t *batch, *batch_start;
@@ -94,17 +95,33 @@ emit_recursive_batch(igt_spin_t *spin,
 
 	nengine = 0;
 	if (opts->engine == ALL_ENGINES) {
-		unsigned int engine;
+		struct intel_execution_engine2 *engine;
 
-		for_each_physical_engine(fd, engine) {
+		for_each_context_engine(fd, opts->ctx, engine) {
 			if (opts->flags & IGT_SPIN_POLL_RUN &&
-			    !gem_can_store_dword(fd, engine))
+			    !gem_class_can_store_dword(fd, engine->class))
 				continue;
 
-			engines[nengine++] = engine;
+			igt_debug("%u=%llx (%u:%u)\n",
+				  nengine,
+				  engine->flags, engine->class, engine->instance);
+			flags[nengine++] = engine->flags;
 		}
 	} else {
-		engines[nengine++] = opts->engine;
+		struct intel_execution_engine2 *e;
+		int class;
+
+		if (!gem_ctx_get_engine(fd, opts->engine, opts->ctx, e)) {
+			class = e->class;
+		} else {
+			gem_require_ring(fd, opts->engine);
+			class = gem_eb_to_class(opts->engine);
+		}
+
+		if (opts->flags & IGT_SPIN_POLL_RUN)
+			igt_require(gem_class_can_store_dword(fd, class));
+
+		flags[nengine++] = opts->engine;
 	}
 	igt_require(nengine);
 
@@ -234,8 +251,9 @@ emit_recursive_batch(igt_spin_t *spin,
 
 	for (i = 0; i < nengine; i++) {
 		execbuf->flags &= ~ENGINE_MASK;
-		execbuf->flags |= engines[i];
+		execbuf->flags |= flags[i];
 
+		igt_debug("eb %u = %llx\n", i, flags[i]);
 		gem_execbuf_wr(fd, execbuf);
 
 		if (opts->flags & IGT_SPIN_FENCE_OUT) {
@@ -308,12 +326,6 @@ igt_spin_batch_factory(int fd, const struct igt_spin_factory *opts)
 
 	igt_require_gem(fd);
 
-	if (opts->engine != ALL_ENGINES) {
-		gem_require_ring(fd, opts->engine);
-		if (opts->flags & IGT_SPIN_POLL_RUN)
-			igt_require(gem_can_store_dword(fd, opts->engine));
-	}
-
 	spin = spin_batch_create(fd, opts);
 
 	igt_assert(gem_bo_busy(fd, spin->handle));
-- 
2.19.1

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

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

* [igt-dev] [RFT i-g-t 5/6] lib: igt_dummyload: use for_each_context_engine()
@ 2019-04-11 12:28     ` Tvrtko Ursulin
  0 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 12:28 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx

From: Andi Shyti <andi.shyti@intel.com>

With the new getparam/setparam api, engines are mapped to
context. Use for_each_context_engine() to loop through existing
engines.

Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Andi Shyti <andi.shyti@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
Just some debug to get more data from CI.
---
 lib/igt_dummyload.c | 38 +++++++++++++++++++++++++-------------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 47f6b92b424b..e7f3f480dc26 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -39,6 +39,7 @@
 #include "ioctl_wrappers.h"
 #include "sw_sync.h"
 #include "igt_vgem.h"
+#include "i915/gem_engine_topology.h"
 #include "i915/gem_mman.h"
 
 /**
@@ -86,7 +87,7 @@ emit_recursive_batch(igt_spin_t *spin,
 	struct drm_i915_gem_relocation_entry relocs[2], *r;
 	struct drm_i915_gem_execbuffer2 *execbuf;
 	struct drm_i915_gem_exec_object2 *obj;
-	unsigned int engines[16];
+	unsigned int flags[GEM_MAX_ENGINES];
 	unsigned int nengine;
 	int fence_fd = -1;
 	uint32_t *batch, *batch_start;
@@ -94,17 +95,33 @@ emit_recursive_batch(igt_spin_t *spin,
 
 	nengine = 0;
 	if (opts->engine == ALL_ENGINES) {
-		unsigned int engine;
+		struct intel_execution_engine2 *engine;
 
-		for_each_physical_engine(fd, engine) {
+		for_each_context_engine(fd, opts->ctx, engine) {
 			if (opts->flags & IGT_SPIN_POLL_RUN &&
-			    !gem_can_store_dword(fd, engine))
+			    !gem_class_can_store_dword(fd, engine->class))
 				continue;
 
-			engines[nengine++] = engine;
+			igt_debug("%u=%llx (%u:%u)\n",
+				  nengine,
+				  engine->flags, engine->class, engine->instance);
+			flags[nengine++] = engine->flags;
 		}
 	} else {
-		engines[nengine++] = opts->engine;
+		struct intel_execution_engine2 *e;
+		int class;
+
+		if (!gem_ctx_get_engine(fd, opts->engine, opts->ctx, e)) {
+			class = e->class;
+		} else {
+			gem_require_ring(fd, opts->engine);
+			class = gem_eb_to_class(opts->engine);
+		}
+
+		if (opts->flags & IGT_SPIN_POLL_RUN)
+			igt_require(gem_class_can_store_dword(fd, class));
+
+		flags[nengine++] = opts->engine;
 	}
 	igt_require(nengine);
 
@@ -234,8 +251,9 @@ emit_recursive_batch(igt_spin_t *spin,
 
 	for (i = 0; i < nengine; i++) {
 		execbuf->flags &= ~ENGINE_MASK;
-		execbuf->flags |= engines[i];
+		execbuf->flags |= flags[i];
 
+		igt_debug("eb %u = %llx\n", i, flags[i]);
 		gem_execbuf_wr(fd, execbuf);
 
 		if (opts->flags & IGT_SPIN_FENCE_OUT) {
@@ -308,12 +326,6 @@ igt_spin_batch_factory(int fd, const struct igt_spin_factory *opts)
 
 	igt_require_gem(fd);
 
-	if (opts->engine != ALL_ENGINES) {
-		gem_require_ring(fd, opts->engine);
-		if (opts->flags & IGT_SPIN_POLL_RUN)
-			igt_require(gem_can_store_dword(fd, opts->engine));
-	}
-
 	spin = spin_batch_create(fd, opts);
 
 	igt_assert(gem_bo_busy(fd, spin->handle));
-- 
2.19.1

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

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-11 12:26     ` [igt-dev] " Tvrtko Ursulin
@ 2019-04-11 12:32       ` Chris Wilson
  -1 siblings, 0 replies; 43+ messages in thread
From: Chris Wilson @ 2019-04-11 12:32 UTC (permalink / raw)
  To: Tvrtko Ursulin, igt-dev; +Cc: Intel-gfx

Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> From: Andi Shyti <andi.shyti@intel.com>
> 
> Replace the legacy for_each_engine* defines with the ones
> implemented in the gem_engine_topology library.
> 
> Use whenever possible gem_engine_can_store_dword() that checks
> class instead of flags.
> 
> Now the __for_each_engine_class_instance and
> for_each_engine_class_instance are unused, remove them.
> 
> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

I see a lot of new gem_context_create(), but not gem_require_contexts().
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 12:32       ` Chris Wilson
  0 siblings, 0 replies; 43+ messages in thread
From: Chris Wilson @ 2019-04-11 12:32 UTC (permalink / raw)
  To: Tvrtko Ursulin, igt-dev; +Cc: Intel-gfx

Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> From: Andi Shyti <andi.shyti@intel.com>
> 
> Replace the legacy for_each_engine* defines with the ones
> implemented in the gem_engine_topology library.
> 
> Use whenever possible gem_engine_can_store_dword() that checks
> class instead of flags.
> 
> Now the __for_each_engine_class_instance and
> for_each_engine_class_instance are unused, remove them.
> 
> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

I see a lot of new gem_context_create(), but not gem_require_contexts().
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-11 12:32       ` [Intel-gfx] " Chris Wilson
@ 2019-04-11 12:53         ` Tvrtko Ursulin
  -1 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 12:53 UTC (permalink / raw)
  To: Chris Wilson, igt-dev; +Cc: Intel-gfx


On 11/04/2019 13:32, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
>> From: Andi Shyti <andi.shyti@intel.com>
>>
>> Replace the legacy for_each_engine* defines with the ones
>> implemented in the gem_engine_topology library.
>>
>> Use whenever possible gem_engine_can_store_dword() that checks
>> class instead of flags.
>>
>> Now the __for_each_engine_class_instance and
>> for_each_engine_class_instance are unused, remove them.
>>
>> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> I see a lot of new gem_context_create(), but not gem_require_contexts().

Problem is __for_each_physical_engine modifies the default context so 
tests under that iterator can't keep using I915_EXEC_RENDER.

It was perhaps a knee-jerk reaction to make them create their own 
context as a workaround.

Should we have a helper after all to get eb flags for given class:instance?

unsigned int
gem_get_ctx_eb_flags(uint32_t ctx, uint16_t class, uint16_t instance)
{
	if (ctx.has_map)
		return find_class_instance_in_map->flags;
	else
		return gem_class_instance_to_eb_flags(class, instance);
}

?

Regards,

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

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 12:53         ` Tvrtko Ursulin
  0 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 12:53 UTC (permalink / raw)
  To: Chris Wilson, igt-dev; +Cc: Intel-gfx, Andi Shyti


On 11/04/2019 13:32, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
>> From: Andi Shyti <andi.shyti@intel.com>
>>
>> Replace the legacy for_each_engine* defines with the ones
>> implemented in the gem_engine_topology library.
>>
>> Use whenever possible gem_engine_can_store_dword() that checks
>> class instead of flags.
>>
>> Now the __for_each_engine_class_instance and
>> for_each_engine_class_instance are unused, remove them.
>>
>> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> I see a lot of new gem_context_create(), but not gem_require_contexts().

Problem is __for_each_physical_engine modifies the default context so 
tests under that iterator can't keep using I915_EXEC_RENDER.

It was perhaps a knee-jerk reaction to make them create their own 
context as a workaround.

Should we have a helper after all to get eb flags for given class:instance?

unsigned int
gem_get_ctx_eb_flags(uint32_t ctx, uint16_t class, uint16_t instance)
{
	if (ctx.has_map)
		return find_class_instance_in_map->flags;
	else
		return gem_class_instance_to_eb_flags(class, instance);
}

?

Regards,

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

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-11 12:32       ` [Intel-gfx] " Chris Wilson
@ 2019-04-11 13:01         ` Andi Shyti
  -1 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-11 13:01 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev, Intel-gfx

On Thu, Apr 11, 2019 at 01:32:03PM +0100, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> > From: Andi Shyti <andi.shyti@intel.com>
> > 
> > Replace the legacy for_each_engine* defines with the ones
> > implemented in the gem_engine_topology library.
> > 
> > Use whenever possible gem_engine_can_store_dword() that checks
> > class instead of flags.
> > 
> > Now the __for_each_engine_class_instance and
> > for_each_engine_class_instance are unused, remove them.
> > 
> > Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> I see a lot of new gem_context_create(), but not gem_require_contexts().

gem_require_contexts() should go on top of engine_topology.
I will add it there.

Thanks,
Andi

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

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

* Re: [igt-dev] [Intel-gfx] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 13:01         ` Andi Shyti
  0 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-11 13:01 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev, Intel-gfx

On Thu, Apr 11, 2019 at 01:32:03PM +0100, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> > From: Andi Shyti <andi.shyti@intel.com>
> > 
> > Replace the legacy for_each_engine* defines with the ones
> > implemented in the gem_engine_topology library.
> > 
> > Use whenever possible gem_engine_can_store_dword() that checks
> > class instead of flags.
> > 
> > Now the __for_each_engine_class_instance and
> > for_each_engine_class_instance are unused, remove them.
> > 
> > Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> 
> I see a lot of new gem_context_create(), but not gem_require_contexts().

gem_require_contexts() should go on top of engine_topology.
I will add it there.

Thanks,
Andi

> -Chris
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-11 13:01         ` [igt-dev] [Intel-gfx] " Andi Shyti
@ 2019-04-11 13:40           ` Chris Wilson
  -1 siblings, 0 replies; 43+ messages in thread
From: Chris Wilson @ 2019-04-11 13:40 UTC (permalink / raw)
  To: Andi Shyti; +Cc: igt-dev, Intel-gfx

Quoting Andi Shyti (2019-04-11 14:01:01)
> On Thu, Apr 11, 2019 at 01:32:03PM +0100, Chris Wilson wrote:
> > Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> > > From: Andi Shyti <andi.shyti@intel.com>
> > > 
> > > Replace the legacy for_each_engine* defines with the ones
> > > implemented in the gem_engine_topology library.
> > > 
> > > Use whenever possible gem_engine_can_store_dword() that checks
> > > class instead of flags.
> > > 
> > > Now the __for_each_engine_class_instance and
> > > for_each_engine_class_instance are unused, remove them.
> > > 
> > > Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > > Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > 
> > I see a lot of new gem_context_create(), but not gem_require_contexts().
> 
> gem_require_contexts() should go on top of engine_topology.

engine_topology shouldn't require contexts per se, as we should be able
to quite happily modify the engine map for Pineview. To what purpose,
we do not ask!

Just be careful you don't legacy tests.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [igt-dev] [Intel-gfx] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 13:40           ` Chris Wilson
  0 siblings, 0 replies; 43+ messages in thread
From: Chris Wilson @ 2019-04-11 13:40 UTC (permalink / raw)
  To: Andi Shyti; +Cc: igt-dev, Intel-gfx

Quoting Andi Shyti (2019-04-11 14:01:01)
> On Thu, Apr 11, 2019 at 01:32:03PM +0100, Chris Wilson wrote:
> > Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> > > From: Andi Shyti <andi.shyti@intel.com>
> > > 
> > > Replace the legacy for_each_engine* defines with the ones
> > > implemented in the gem_engine_topology library.
> > > 
> > > Use whenever possible gem_engine_can_store_dword() that checks
> > > class instead of flags.
> > > 
> > > Now the __for_each_engine_class_instance and
> > > for_each_engine_class_instance are unused, remove them.
> > > 
> > > Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > > Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > 
> > I see a lot of new gem_context_create(), but not gem_require_contexts().
> 
> gem_require_contexts() should go on top of engine_topology.

engine_topology shouldn't require contexts per se, as we should be able
to quite happily modify the engine map for Pineview. To what purpose,
we do not ask!

Just be careful you don't legacy tests.
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-11 12:53         ` Tvrtko Ursulin
@ 2019-04-11 13:50           ` Chris Wilson
  -1 siblings, 0 replies; 43+ messages in thread
From: Chris Wilson @ 2019-04-11 13:50 UTC (permalink / raw)
  To: Tvrtko Ursulin, igt-dev; +Cc: Intel-gfx

Quoting Tvrtko Ursulin (2019-04-11 13:53:24)
> 
> On 11/04/2019 13:32, Chris Wilson wrote:
> > Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> >> From: Andi Shyti <andi.shyti@intel.com>
> >>
> >> Replace the legacy for_each_engine* defines with the ones
> >> implemented in the gem_engine_topology library.
> >>
> >> Use whenever possible gem_engine_can_store_dword() that checks
> >> class instead of flags.
> >>
> >> Now the __for_each_engine_class_instance and
> >> for_each_engine_class_instance are unused, remove them.
> >>
> >> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> >> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> >> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> >> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > 
> > I see a lot of new gem_context_create(), but not gem_require_contexts().
> 
> Problem is __for_each_physical_engine modifies the default context so 
> tests under that iterator can't keep using I915_EXEC_RENDER.
> 
> It was perhaps a knee-jerk reaction to make them create their own 
> context as a workaround.

From the looks of the tests affected, they all should support contexts. I
would be more concerned if the basic busyness checking tests grew a new
dependency.

Operating on the default context, should be fine though. May require an
operation to reset in case a previous subtest failed, which is a
downside.
 
> Should we have a helper after all to get eb flags for given class:instance?

I think resist/delay as much as possible. In 3 months time we can sweep
away any evidence of the old ways, and only the explicit legacy ABI
tests need concern themselves with BSD | BSD2 ;)
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 13:50           ` Chris Wilson
  0 siblings, 0 replies; 43+ messages in thread
From: Chris Wilson @ 2019-04-11 13:50 UTC (permalink / raw)
  To: Tvrtko Ursulin, igt-dev; +Cc: Intel-gfx, Andi Shyti

Quoting Tvrtko Ursulin (2019-04-11 13:53:24)
> 
> On 11/04/2019 13:32, Chris Wilson wrote:
> > Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> >> From: Andi Shyti <andi.shyti@intel.com>
> >>
> >> Replace the legacy for_each_engine* defines with the ones
> >> implemented in the gem_engine_topology library.
> >>
> >> Use whenever possible gem_engine_can_store_dword() that checks
> >> class instead of flags.
> >>
> >> Now the __for_each_engine_class_instance and
> >> for_each_engine_class_instance are unused, remove them.
> >>
> >> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> >> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> >> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> >> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > 
> > I see a lot of new gem_context_create(), but not gem_require_contexts().
> 
> Problem is __for_each_physical_engine modifies the default context so 
> tests under that iterator can't keep using I915_EXEC_RENDER.
> 
> It was perhaps a knee-jerk reaction to make them create their own 
> context as a workaround.

From the looks of the tests affected, they all should support contexts. I
would be more concerned if the basic busyness checking tests grew a new
dependency.

Operating on the default context, should be fine though. May require an
operation to reset in case a previous subtest failed, which is a
downside.
 
> Should we have a helper after all to get eb flags for given class:instance?

I think resist/delay as much as possible. In 3 months time we can sweep
away any evidence of the old ways, and only the explicit legacy ABI
tests need concern themselves with BSD | BSD2 ;)
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-11 13:50           ` Chris Wilson
@ 2019-04-11 14:37             ` Tvrtko Ursulin
  -1 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 14:37 UTC (permalink / raw)
  To: Chris Wilson, igt-dev; +Cc: Intel-gfx


On 11/04/2019 14:50, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-04-11 13:53:24)
>>
>> On 11/04/2019 13:32, Chris Wilson wrote:
>>> Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
>>>> From: Andi Shyti <andi.shyti@intel.com>
>>>>
>>>> Replace the legacy for_each_engine* defines with the ones
>>>> implemented in the gem_engine_topology library.
>>>>
>>>> Use whenever possible gem_engine_can_store_dword() that checks
>>>> class instead of flags.
>>>>
>>>> Now the __for_each_engine_class_instance and
>>>> for_each_engine_class_instance are unused, remove them.
>>>>
>>>> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>>> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
>>>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>>>> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>>
>>> I see a lot of new gem_context_create(), but not gem_require_contexts().
>>
>> Problem is __for_each_physical_engine modifies the default context so
>> tests under that iterator can't keep using I915_EXEC_RENDER.
>>
>> It was perhaps a knee-jerk reaction to make them create their own
>> context as a workaround.
> 
>  From the looks of the tests affected, they all should support contexts. I
> would be more concerned if the basic busyness checking tests grew a new
> dependency.

Basic busyness ones have not, but the ones I fixed up by making them 
create a context have. Which is fixable with below.

Failures are only with gem_wait/basic-*-all, so I suspect something's 
off in igt_dummyload.c. Will see what happens with the debugs added.

> Operating on the default context, should be fine though. May require an
> operation to reset in case a previous subtest failed, which is a
> downside.
>   
>> Should we have a helper after all to get eb flags for given class:instance?
> 
> I think resist/delay as much as possible. In 3 months time we can sweep
> away any evidence of the old ways, and only the explicit legacy ABI
> tests need concern themselves with BSD | BSD2 ;)

perf_pmu tests which I added context_create to open PMU for rcs:0 and 
submit batches to I915_EXEC_RENDER.

Well alternative to the helper could be to change them to submit to 
I915_EXEC_DEFAULT and rely on context map to always have rcs:0 at index 
0. Which could even be passable. If the promise is broken the tests will 
fail to let us know.

Okay with this alternative hack?

Regards,

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

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 14:37             ` Tvrtko Ursulin
  0 siblings, 0 replies; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 14:37 UTC (permalink / raw)
  To: Chris Wilson, igt-dev; +Cc: Intel-gfx, Andi Shyti


On 11/04/2019 14:50, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-04-11 13:53:24)
>>
>> On 11/04/2019 13:32, Chris Wilson wrote:
>>> Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
>>>> From: Andi Shyti <andi.shyti@intel.com>
>>>>
>>>> Replace the legacy for_each_engine* defines with the ones
>>>> implemented in the gem_engine_topology library.
>>>>
>>>> Use whenever possible gem_engine_can_store_dword() that checks
>>>> class instead of flags.
>>>>
>>>> Now the __for_each_engine_class_instance and
>>>> for_each_engine_class_instance are unused, remove them.
>>>>
>>>> Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>>> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
>>>> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
>>>> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>>
>>> I see a lot of new gem_context_create(), but not gem_require_contexts().
>>
>> Problem is __for_each_physical_engine modifies the default context so
>> tests under that iterator can't keep using I915_EXEC_RENDER.
>>
>> It was perhaps a knee-jerk reaction to make them create their own
>> context as a workaround.
> 
>  From the looks of the tests affected, they all should support contexts. I
> would be more concerned if the basic busyness checking tests grew a new
> dependency.

Basic busyness ones have not, but the ones I fixed up by making them 
create a context have. Which is fixable with below.

Failures are only with gem_wait/basic-*-all, so I suspect something's 
off in igt_dummyload.c. Will see what happens with the debugs added.

> Operating on the default context, should be fine though. May require an
> operation to reset in case a previous subtest failed, which is a
> downside.
>   
>> Should we have a helper after all to get eb flags for given class:instance?
> 
> I think resist/delay as much as possible. In 3 months time we can sweep
> away any evidence of the old ways, and only the explicit legacy ABI
> tests need concern themselves with BSD | BSD2 ;)

perf_pmu tests which I added context_create to open PMU for rcs:0 and 
submit batches to I915_EXEC_RENDER.

Well alternative to the helper could be to change them to submit to 
I915_EXEC_DEFAULT and rely on context map to always have rcs:0 at index 
0. Which could even be passable. If the promise is broken the tests will 
fail to let us know.

Okay with this alternative hack?

Regards,

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

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

* [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev3)
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
                   ` (6 preceding siblings ...)
  2019-04-08 17:35 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface Patchwork
@ 2019-04-11 14:54 ` Patchwork
  2019-04-11 18:11 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev4) Patchwork
  8 siblings, 0 replies; 43+ messages in thread
From: Patchwork @ 2019-04-11 14:54 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: igt-dev

== Series Details ==

Series: new engine discovery interface (rev3)
URL   : https://patchwork.freedesktop.org/series/59185/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_5909 -> IGTPW_2846
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_2846 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_2846, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/59185/revisions/3/mbox/

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@gem_wait@basic-busy-all:
    - fi-bwr-2160:        PASS -> FAIL +1
    - fi-pnv-d510:        PASS -> FAIL +1

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

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

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_suspend@basic-s3:
    - fi-blb-e6850:       PASS -> INCOMPLETE [fdo#107718]

  * igt@i915_selftest@live_evict:
    - fi-bsw-kefka:       PASS -> DMESG-WARN [fdo#107709]

  * igt@i915_selftest@live_execlists:
    - fi-apl-guc:         PASS -> INCOMPLETE [fdo#103927] / [fdo#109720]

  * igt@kms_cursor_legacy@basic-flip-before-cursor-varying-size:
    - fi-glk-dsi:         PASS -> INCOMPLETE [fdo#103359] / [k.org#198133]

  * igt@runner@aborted:
    - fi-bsw-kefka:       NOTRUN -> FAIL [fdo#107709]
    - fi-apl-guc:         NOTRUN -> FAIL [fdo#108622] / [fdo#109720]

  
#### Possible fixes ####

  * igt@i915_selftest@live_hangcheck:
    - fi-bxt-dsi:         INCOMPLETE [fdo#103927] -> PASS

  
  [fdo#103359]: https://bugs.freedesktop.org/show_bug.cgi?id=103359
  [fdo#103927]: https://bugs.freedesktop.org/show_bug.cgi?id=103927
  [fdo#107709]: https://bugs.freedesktop.org/show_bug.cgi?id=107709
  [fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
  [fdo#108622]: https://bugs.freedesktop.org/show_bug.cgi?id=108622
  [fdo#109720]: https://bugs.freedesktop.org/show_bug.cgi?id=109720
  [k.org#198133]: https://bugzilla.kernel.org/show_bug.cgi?id=198133


Participating hosts (49 -> 41)
------------------------------

  Missing    (8): fi-ilk-m540 fi-skl-6770hq fi-byt-squawks fi-bsw-cyan fi-gdg-551 fi-cfl-8109u fi-bdw-samus fi-skl-6700k2 


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

    * IGT: IGT_4943 -> IGTPW_2846

  CI_DRM_5909: af07fbb536d0728e381cc001cac5bc259c41fe02 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2846: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2846/
  IGT_4943: 5941f371b0fe25084d4b1c49882faa8d41d44c9f @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

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

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

* Re: [igt-dev] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
  2019-04-11 13:40           ` [igt-dev] [Intel-gfx] " Chris Wilson
@ 2019-04-11 14:55             ` Andi Shyti
  -1 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-11 14:55 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev, Intel-gfx

On Thu, Apr 11, 2019 at 02:40:45PM +0100, Chris Wilson wrote:
> Quoting Andi Shyti (2019-04-11 14:01:01)
> > On Thu, Apr 11, 2019 at 01:32:03PM +0100, Chris Wilson wrote:
> > > Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> > > > From: Andi Shyti <andi.shyti@intel.com>
> > > > 
> > > > Replace the legacy for_each_engine* defines with the ones
> > > > implemented in the gem_engine_topology library.
> > > > 
> > > > Use whenever possible gem_engine_can_store_dword() that checks
> > > > class instead of flags.
> > > > 
> > > > Now the __for_each_engine_class_instance and
> > > > for_each_engine_class_instance are unused, remove them.
> > > > 
> > > > Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > > > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > > > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > > > Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > > 
> > > I see a lot of new gem_context_create(), but not gem_require_contexts().
> > 
> > gem_require_contexts() should go on top of engine_topology.
> 
> engine_topology shouldn't require contexts per se, as we should be able
> to quite happily modify the engine map for Pineview. To what purpose,
> we do not ask!
> 
> Just be careful you don't legacy tests.

I created a helper to avoid initializing the whole "think".
Tvrtko, indeed at some point calls "init_engine_list".

The helper looks like this:

+int64_t gem_map_all_engines(int fd)
+{
+       DEFINE_CONTEXT_PARAM(engines, param, 0, GEM_MAX_ENGINES);
+       struct intel_engine_data engine_data = { };

/* here is where I would add gem_require_contexts() */

+       param.ctx_id = gem_context_create(fd);
+
+       if (gem_topology_get_param(fd, &param) > 0 && !param.size) {
+               query_engine_list(fd, &engine_data);
+               ctx_map_engines(fd, &engine_data, &param);
+       }
+
+       return param.ctx_id;
+}

and of course there is an unmap_engines that just deletes the
context.

Maybe such a helper is not required in the new world, but it can
be useful for legacy tests.

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

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

* Re: [igt-dev] [Intel-gfx] [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library
@ 2019-04-11 14:55             ` Andi Shyti
  0 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-11 14:55 UTC (permalink / raw)
  To: Chris Wilson; +Cc: igt-dev, Intel-gfx

On Thu, Apr 11, 2019 at 02:40:45PM +0100, Chris Wilson wrote:
> Quoting Andi Shyti (2019-04-11 14:01:01)
> > On Thu, Apr 11, 2019 at 01:32:03PM +0100, Chris Wilson wrote:
> > > Quoting Tvrtko Ursulin (2019-04-11 13:26:54)
> > > > From: Andi Shyti <andi.shyti@intel.com>
> > > > 
> > > > Replace the legacy for_each_engine* defines with the ones
> > > > implemented in the gem_engine_topology library.
> > > > 
> > > > Use whenever possible gem_engine_can_store_dword() that checks
> > > > class instead of flags.
> > > > 
> > > > Now the __for_each_engine_class_instance and
> > > > for_each_engine_class_instance are unused, remove them.
> > > > 
> > > > Suggested-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > > > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > > > Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> > > > Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> > > 
> > > I see a lot of new gem_context_create(), but not gem_require_contexts().
> > 
> > gem_require_contexts() should go on top of engine_topology.
> 
> engine_topology shouldn't require contexts per se, as we should be able
> to quite happily modify the engine map for Pineview. To what purpose,
> we do not ask!
> 
> Just be careful you don't legacy tests.

I created a helper to avoid initializing the whole "think".
Tvrtko, indeed at some point calls "init_engine_list".

The helper looks like this:

+int64_t gem_map_all_engines(int fd)
+{
+       DEFINE_CONTEXT_PARAM(engines, param, 0, GEM_MAX_ENGINES);
+       struct intel_engine_data engine_data = { };

/* here is where I would add gem_require_contexts() */

+       param.ctx_id = gem_context_create(fd);
+
+       if (gem_topology_get_param(fd, &param) > 0 && !param.size) {
+               query_engine_list(fd, &engine_data);
+               ctx_map_engines(fd, &engine_data, &param);
+       }
+
+       return param.ctx_id;
+}

and of course there is an unmap_engines that just deletes the
context.

Maybe such a helper is not required in the new world, but it can
be useful for legacy tests.

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

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

* Re: [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition
  2019-04-08 16:15 ` [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition Andi Shyti
  2019-04-08 16:54   ` Tvrtko Ursulin
@ 2019-04-11 16:03   ` Tvrtko Ursulin
  2019-04-11 23:23     ` Andi Shyti
  1 sibling, 1 reply; 43+ messages in thread
From: Tvrtko Ursulin @ 2019-04-11 16:03 UTC (permalink / raw)
  To: Andi Shyti, IGT dev; +Cc: Andi Shyti


On 08/04/2019 17:15, Andi Shyti wrote:
> The gem_engine_topology library is a set of functions that
> interface with the query and getparam/setparam ioctls.
> 
> The library's access point is the 'intel_init_engine_list()'
> function that, everytime is called, generates the list of active
> engines and returns them in a 'struct intel_engine_data'. The
> structure contains only the engines that are actively present in
> the GPU.
> 
> The function can work in both the cases that the query and
> getparam ioctls are implemented or not by the running kernel. In
> case they are implemented, a query is made to the driver to fetch
> the list of active engines. In case they are not implemented, the
> list is taken from the 'intel_execution_engines2' array and
> stored only after checking their presence.
> 
> The gem_engine_topology library provides some iteration helpers:
> 
>   - intel_get_current_engine(): provides the current engine in the
>     iteration.
> 
>   - intel_get_current_physical_engine(): provides the current
>     physical engine, if the current engine is a virtual engine,
>     it moves forward until it finds a physical engine.
> 
>   - intel_next_engine() it just increments the counter so that it
>     points to the next engine.
> 
> Extend the 'for_each_engine_class_instance' so that it can loop
> using the new 'intel_init_engine_list()' and rename it to
> 'for_each_context_engine'.
> 
> Move '__for_each_engine_class_instance' to gem_engine_topology.h
> and rename it to '__for_each_static_engine'.
> 
> Update accordingly tests/perf_pmu.c to use correctly the new
> for_each loops.
> 
> Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> ---
>   lib/Makefile.sources           |   2 +
>   lib/i915/gem_engine_topology.c | 281 +++++++++++++++++++++++++++++++++
>   lib/i915/gem_engine_topology.h |  78 +++++++++
>   lib/igt.h                      |   1 +
>   lib/igt_gt.h                   |   2 +
>   lib/meson.build                |   1 +
>   6 files changed, 365 insertions(+)
>   create mode 100644 lib/i915/gem_engine_topology.c
>   create mode 100644 lib/i915/gem_engine_topology.h
> 
> diff --git a/lib/Makefile.sources b/lib/Makefile.sources
> index e00347f945c5..41331c2f2b80 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 000000000000..06f538372a4d
> --- /dev/null
> +++ b/lib/i915/gem_engine_topology.c
> @@ -0,0 +1,281 @@
> +/*
> + * 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"
> +
> +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->class_instance[0]) *p =
> +	     &engines->class_instance[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), class_instance[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_class,
> +			    query_engine->engines[i].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++;

This is broken for one engine. It should read:

	if (++ed->n < ed->nengines)
		ed->current_engine = &ed->engines[ed->n];
	else
		ed->current_engine = NULL;

Otherwise ed->n is always zero and it never progresses.

*However*... there is a mystery to solve in why with the broken code if 
you run gem_wait --r basic-busy-all the loop still exits (on my system 
after 65 iterations).

On the other hand my system "perf_pmu --list" loops forever as expected.

I fear there is some stack corruption or something. But Valgrind does 
not catch anything.

You can comment out all but RCS in the static engine list and test. And 
OFC use drm-tip so legacy path runs.

Regards,

Tvrtko


> +		ed->current_engine = &ed->engines[ed->n];
> +	} else {
> +		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, uint32_t ctx,
> +				  struct drm_i915_gem_context_param *p)
> +{
> +	int nengines;
> +	int ret;
> +
> +	if (igt_only_list_subtests())
> +		return -EPERM;
> +
> +	ret = __gem_context_get_param(fd, p);
> +	if (ret)
> +		return ret;
> +
> +	nengines = p->size > sizeof(struct i915_context_param_engines) ?
> +		   (p->size - sizeof(struct i915_context_param_engines)) /
> +		   (2 * sizeof(__u16)) :
> +		   0;
> +
> +	igt_assert_f(nengines <= GEM_MAX_ENGINES, "unsupported engine count\n");
> +
> +	return nengines;
> +}
> +
> +struct intel_engine_data intel_init_engine_list(int fd, uint32_t ctx_id)
> +{
> +	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, GEM_MAX_ENGINES);
> +	struct intel_engine_data engine_data = { };
> +	struct drm_i915_gem_context_param param = {
> +		.param = I915_CONTEXT_PARAM_ENGINES,
> +		.ctx_id = ctx_id,
> +		.size = SIZEOF_CTX_PARAM,
> +		.value = to_user_pointer(&engines),
> +	};
> +	int nengines = gem_topology_get_param(fd, ctx_id, &param);
> +	int i;
> +
> +	if (nengines < 0) {
> +		/* 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;
> +			}
> +
> +			__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) {
> +		/* else if context doesn't have mapped engines */
> +		query_engine_list(fd, &engine_data);
> +		ctx_map_engines(fd, &engine_data, &param);
> +
> +	} else {
> +		/* context has a list of mapped engines */
> +
> +		for (i = 0; i < nengines; i++)
> +			init_engine(&engine_data.engines[i],
> +				    engines.class_instance[i].engine_class,
> +				    engines.class_instance[i].engine_instance,
> +				    i);
> +
> +		engine_data.nengines = i;
> +	}
> +
> +	return engine_data;
> +}
> +
> +int gem_ctx_get_engine(int fd, uint32_t engine, uint32_t ctx_id,
> +		       struct intel_execution_engine2 *e)
> +{
> +	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, GEM_MAX_ENGINES);
> +	struct drm_i915_gem_context_param param = {
> +		.param = I915_CONTEXT_PARAM_ENGINES,
> +		.ctx_id = ctx_id,
> +		.size = SIZEOF_CTX_PARAM,
> +		.value = to_user_pointer(&engines),
> +	};
> +	int nengines = gem_topology_get_param(fd, ctx_id, &param);
> +
> +	if (nengines < 0)
> +		return nengines;
> +
> +	if (!param.size || !nengines)
> +		return -EINVAL;
> +
> +	e->class = engines.class_instance[engine].engine_class;
> +	e->instance = engines.class_instance[engine].engine_instance;
> +
> +	return 0;
> +}
> +
> +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 000000000000..806c260b1074
> --- /dev/null
> +++ b/lib/i915/gem_engine_topology.h
> @@ -0,0 +1,78 @@
> +/*
> + * 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, \
> +					class_instance[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;
> +	int error;
> +	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_ctx_get_engine(int fd, uint32_t engine, uint32_t ctx_id,
> +		       struct intel_execution_engine2 *e);
> +
> +#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 6654a659c062..03f19ca2dfb6 100644
> --- a/lib/igt.h
> +++ b/lib/igt.h
> @@ -53,5 +53,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 475c0b3c3cc6..52b2f1ea95a5 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 89de06e6924a..93c01daa4222 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',
> 
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

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

* [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev4)
  2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
                   ` (7 preceding siblings ...)
  2019-04-11 14:54 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev3) Patchwork
@ 2019-04-11 18:11 ` Patchwork
  8 siblings, 0 replies; 43+ messages in thread
From: Patchwork @ 2019-04-11 18:11 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: igt-dev

== Series Details ==

Series: new engine discovery interface (rev4)
URL   : https://patchwork.freedesktop.org/series/59185/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_5912 -> IGTPW_2850
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with IGTPW_2850 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_2850, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/59185/revisions/4/mbox/

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

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

### IGT changes ###

#### Possible regressions ####

  * igt@gem_wait@basic-busy-all:
    - fi-bwr-2160:        PASS -> FAIL +1

  * igt@gem_wait@basic-wait-all:
    - fi-gdg-551:         PASS -> FAIL +1

  * igt@runner@aborted:
    - fi-icl-y:           NOTRUN -> FAIL

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

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

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_suspend@basic-s3:
    - fi-blb-e6850:       PASS -> INCOMPLETE [fdo#107718]

  * igt@kms_chamelium@hdmi-edid-read:
    - fi-hsw-peppy:       NOTRUN -> SKIP [fdo#109271] +46

  * igt@kms_force_connector_basic@force-edid:
    - fi-glk-dsi:         NOTRUN -> SKIP [fdo#109271] +26

  * igt@kms_frontbuffer_tracking@basic:
    - fi-hsw-peppy:       NOTRUN -> DMESG-FAIL [fdo#102614] / [fdo#107814]
    - fi-glk-dsi:         NOTRUN -> FAIL [fdo#103167]

  * igt@kms_pipe_crc_basic@read-crc-pipe-b:
    - fi-byt-clapper:     PASS -> FAIL [fdo#103191] +1

  
#### Possible fixes ####

  * igt@i915_selftest@live_hangcheck:
    - fi-skl-iommu:       INCOMPLETE [fdo#108602] / [fdo#108744] -> PASS

  * igt@kms_cursor_legacy@basic-flip-before-cursor-varying-size:
    - fi-glk-dsi:         INCOMPLETE [fdo#103359] / [k.org#198133] -> PASS

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

  [fdo#102614]: https://bugs.freedesktop.org/show_bug.cgi?id=102614
  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
  [fdo#103359]: https://bugs.freedesktop.org/show_bug.cgi?id=103359
  [fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
  [fdo#107814]: https://bugs.freedesktop.org/show_bug.cgi?id=107814
  [fdo#108569]: https://bugs.freedesktop.org/show_bug.cgi?id=108569
  [fdo#108602]: https://bugs.freedesktop.org/show_bug.cgi?id=108602
  [fdo#108744]: https://bugs.freedesktop.org/show_bug.cgi?id=108744
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [k.org#198133]: https://bugzilla.kernel.org/show_bug.cgi?id=198133


Participating hosts (50 -> 39)
------------------------------

  Additional (1): fi-hsw-peppy 
  Missing    (12): fi-kbl-soraka fi-ilk-m540 fi-hsw-4200u fi-byt-squawks fi-bsw-cyan fi-snb-2520m fi-kbl-guc fi-ctg-p8600 fi-icl-u3 fi-pnv-d510 fi-bdw-samus fi-kbl-r 


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

    * IGT: IGT_4943 -> IGTPW_2850

  CI_DRM_5912: d7c1889b2e971f44d10c69ec204991f3264d2412 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2850: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2850/
  IGT_4943: 5941f371b0fe25084d4b1c49882faa8d41d44c9f @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

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

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

* Re: [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition
  2019-04-11 16:03   ` Tvrtko Ursulin
@ 2019-04-11 23:23     ` Andi Shyti
  0 siblings, 0 replies; 43+ messages in thread
From: Andi Shyti @ 2019-04-11 23:23 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: IGT dev, Andi Shyti

On Thu, Apr 11, 2019 at 05:03:58PM +0100, Tvrtko Ursulin wrote:
> 
> On 08/04/2019 17:15, Andi Shyti wrote:
> > The gem_engine_topology library is a set of functions that
> > interface with the query and getparam/setparam ioctls.
> > 
> > The library's access point is the 'intel_init_engine_list()'
> > function that, everytime is called, generates the list of active
> > engines and returns them in a 'struct intel_engine_data'. The
> > structure contains only the engines that are actively present in
> > the GPU.
> > 
> > The function can work in both the cases that the query and
> > getparam ioctls are implemented or not by the running kernel. In
> > case they are implemented, a query is made to the driver to fetch
> > the list of active engines. In case they are not implemented, the
> > list is taken from the 'intel_execution_engines2' array and
> > stored only after checking their presence.
> > 
> > The gem_engine_topology library provides some iteration helpers:
> > 
> >   - intel_get_current_engine(): provides the current engine in the
> >     iteration.
> > 
> >   - intel_get_current_physical_engine(): provides the current
> >     physical engine, if the current engine is a virtual engine,
> >     it moves forward until it finds a physical engine.
> > 
> >   - intel_next_engine() it just increments the counter so that it
> >     points to the next engine.
> > 
> > Extend the 'for_each_engine_class_instance' so that it can loop
> > using the new 'intel_init_engine_list()' and rename it to
> > 'for_each_context_engine'.
> > 
> > Move '__for_each_engine_class_instance' to gem_engine_topology.h
> > and rename it to '__for_each_static_engine'.
> > 
> > Update accordingly tests/perf_pmu.c to use correctly the new
> > for_each loops.
> > 
> > Signed-off-by: Andi Shyti <andi.shyti@intel.com>
> > ---
> >   lib/Makefile.sources           |   2 +
> >   lib/i915/gem_engine_topology.c | 281 +++++++++++++++++++++++++++++++++
> >   lib/i915/gem_engine_topology.h |  78 +++++++++
> >   lib/igt.h                      |   1 +
> >   lib/igt_gt.h                   |   2 +
> >   lib/meson.build                |   1 +
> >   6 files changed, 365 insertions(+)
> >   create mode 100644 lib/i915/gem_engine_topology.c
> >   create mode 100644 lib/i915/gem_engine_topology.h
> > 
> > diff --git a/lib/Makefile.sources b/lib/Makefile.sources
> > index e00347f945c5..41331c2f2b80 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 000000000000..06f538372a4d
> > --- /dev/null
> > +++ b/lib/i915/gem_engine_topology.c
> > @@ -0,0 +1,281 @@
> > +/*
> > + * 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"
> > +
> > +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->class_instance[0]) *p =
> > +	     &engines->class_instance[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), class_instance[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_class,
> > +			    query_engine->engines[i].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++;
> 
> This is broken for one engine. It should read:

true! I considered as a case but then I forgot to fix it.

> 	if (++ed->n < ed->nengines)

an uncontrolled access to intel_next_engine would increase 'n'
incontrollably as well.

> 		ed->current_engine = &ed->engines[ed->n];
> 	else
> 		ed->current_engine = NULL;

I should assign here "ed->n = ed->nengines".

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

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

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

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-08 16:15 [igt-dev] [PATCH v19 0/6] new engine discovery interface Andi Shyti
2019-04-08 16:15 ` [igt-dev] [PATCH v19 1/6] include/drm-uapi: import i915_drm.h header file Andi Shyti
2019-04-08 16:37   ` Tvrtko Ursulin
2019-04-08 16:47     ` Andi Shyti
2019-04-08 16:56       ` Tvrtko Ursulin
2019-04-08 18:33         ` Antonio Argenziano
2019-04-09  7:33           ` Tvrtko Ursulin
2019-04-08 16:15 ` [igt-dev] [PATCH v19 2/6] lib/i915: add gem_engine_topology library and for_each loop definition Andi Shyti
2019-04-08 16:54   ` Tvrtko Ursulin
2019-04-08 18:21     ` Andi Shyti
2019-04-11 16:03   ` Tvrtko Ursulin
2019-04-11 23:23     ` Andi Shyti
2019-04-08 16:15 ` [igt-dev] [PATCH v19 3/6] lib: igt_gt: add eb flags to class helper Andi Shyti
2019-04-08 16:24   ` Tvrtko Ursulin
2019-04-08 16:15 ` [igt-dev] [PATCH v19 4/6] lib: igt_gt: make gem_engine_can_store_dword() check engine class Andi Shyti
2019-04-08 16:25   ` Tvrtko Ursulin
2019-04-08 16:15 ` [igt-dev] [PATCH v19 5/6] lib: igt_dummyload: use for_each_context_engine() Andi Shyti
2019-04-08 16:28   ` Tvrtko Ursulin
2019-04-08 16:45     ` Andi Shyti
2019-04-11 12:26   ` [RFT i-g-t 6/6] test: perf_pmu: use the gem_engine_topology library Tvrtko Ursulin
2019-04-11 12:26     ` [igt-dev] " Tvrtko Ursulin
2019-04-11 12:32     ` Chris Wilson
2019-04-11 12:32       ` [Intel-gfx] " Chris Wilson
2019-04-11 12:53       ` Tvrtko Ursulin
2019-04-11 12:53         ` Tvrtko Ursulin
2019-04-11 13:50         ` Chris Wilson
2019-04-11 13:50           ` Chris Wilson
2019-04-11 14:37           ` Tvrtko Ursulin
2019-04-11 14:37             ` Tvrtko Ursulin
2019-04-11 13:01       ` Andi Shyti
2019-04-11 13:01         ` [igt-dev] [Intel-gfx] " Andi Shyti
2019-04-11 13:40         ` [igt-dev] " Chris Wilson
2019-04-11 13:40           ` [igt-dev] [Intel-gfx] " Chris Wilson
2019-04-11 14:55           ` [igt-dev] " Andi Shyti
2019-04-11 14:55             ` [igt-dev] [Intel-gfx] " Andi Shyti
2019-04-11 12:28   ` [RFT i-g-t 5/6] lib: igt_dummyload: use for_each_context_engine() Tvrtko Ursulin
2019-04-11 12:28     ` [igt-dev] " Tvrtko Ursulin
2019-04-08 16:15 ` [igt-dev] [PATCH v19 6/6] test: perf_pmu: use the gem_engine_topology library Andi Shyti
2019-04-08 16:35   ` Tvrtko Ursulin
2019-04-08 16:56     ` Andi Shyti
2019-04-08 17:35 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface Patchwork
2019-04-11 14:54 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev3) Patchwork
2019-04-11 18:11 ` [igt-dev] ✗ Fi.CI.BAT: failure for new engine discovery interface (rev4) 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.