[igt-dev] [PATCH i-g-t v5 2/2] Add device selection for IGT

Zbigniew Kempczyński zbigniew.kempczynski at intel.com
Fri Aug 23 07:03:51 UTC 2019


New IGT command line argument --device, IGT_DEVICE enviroment
and .igtrc Common::Device were added to allow selecting device
using device selection API.

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>
Cc: Arkadiusz Hiler <arkadiusz.hiler at intel.com>
Cc: Daniel Vetter <daniel at ffwll.ch>
Cc: Petri Latvala <petri.latvala at intel.com>
---
 docs/chamelium.txt |   3 +
 lib/drmtest.c      | 188 ++++++++++++++++++++++++++++++++++++++++++++-
 lib/drmtest.h      |   9 +++
 lib/igt_core.c     |  34 ++++++++
 4 files changed, 232 insertions(+), 2 deletions(-)

diff --git a/docs/chamelium.txt b/docs/chamelium.txt
index 32c296f7..d3a379d3 100644
--- a/docs/chamelium.txt
+++ b/docs/chamelium.txt
@@ -84,6 +84,9 @@ example (only Chamelium.URL is mandatory):
     # The path to dump frames that fail comparison checks
     FrameDumpPath=/root/
 
+    # Device selection filter
+    Device=pci:vendor=8086,card=0;vgem:
+
     # The following section is used for configuring the Device Under Test.
     # It is not mandatory and allows overriding default values.
     [DUT]
diff --git a/lib/drmtest.c b/lib/drmtest.c
index c379a7b7..c01a88a9 100644
--- a/lib/drmtest.c
+++ b/lib/drmtest.c
@@ -55,6 +55,7 @@
 #include "igt_gt.h"
 #include "igt_kmod.h"
 #include "igt_sysfs.h"
+#include "igt_device_scan.h"
 #include "version.h"
 #include "config.h"
 #include "intel_reg.h"
@@ -289,25 +290,208 @@ static int __open_driver(const char *base, int offset, unsigned int chipset)
 	return __search_and_open(base, offset, chipset);
 }
 
+static int __open_driver_exact(const char *name, unsigned int chipset)
+{
+	static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+	int fd;
+
+	fd = open_device(name, chipset);
+	if (fd != -1)
+		return fd;
+
+	pthread_mutex_lock(&mutex);
+	for (const struct module *m = modules; m->module; m++) {
+		if (chipset & m->bit) {
+			if (m->modprobe)
+				m->modprobe(m->module);
+			else
+				modprobe(m->module);
+		}
+	}
+	pthread_mutex_unlock(&mutex);
+
+	return open_device(name, chipset);
+}
+
+/*
+ * For compatibility mode when multiple --device argument were passed
+ * this function tries to be smart enough to handle tests which opens
+ * more than single device. It iterates over filter list and
+ * compares requested chipset to card chipset (or any).
+ *
+ * Returns:
+ * True if card according to filters added and chipset was found,
+ * false othwerwise.
+ */
+static bool __find_card_with_chipset(int chipset, struct igt_device_card *card)
+{
+	int i, n = igt_device_filter_count();
+	const char *filter;
+	bool match;
+
+	for (i = 0; i < n; i++) {
+		filter = igt_device_filter_get(i);
+		match = igt_device_card_match(filter, card);
+		if (match && (card->chipset == chipset ||
+			      card->chipset == DRIVER_ANY)) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
 /**
  * __drm_open_driver:
  * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL
  *
- * Open the first DRM device we can find, searching up to 16 device nodes
+ * Function opens device in the following order:
+ * 1. when --device arguments are present device scanning will be executed,
+ * then filter argument is used to find matching one.
+ * 2. compatibility mode - open the first DRM device we can find,
+ * searching up to 16 device nodes.
  *
  * Returns:
  * An open DRM fd or -1 on error
  */
 int __drm_open_driver(int chipset)
 {
+	int n = igt_device_filter_count();
+
+	if (n) {
+		bool found;
+		struct igt_device_card card;
+
+		found = __find_card_with_chipset(chipset, &card);
+		if (!found || !strlen(card.card))
+			return -1;
+
+		return __open_driver_exact(card.card, chipset);
+	}
+
 	return __open_driver("/dev/dri/card", 0, chipset);
 }
 
-static int __drm_open_driver_render(int chipset)
+int __drm_open_driver_render(int chipset)
 {
+	int n = igt_device_filter_count();
+
+	if (n) {
+		bool found;
+		struct igt_device_card card;
+
+		found = __find_card_with_chipset(chipset, &card);
+		if (!found || !strlen(card.render))
+			return -1;
+
+		return __open_driver_exact(card.render, chipset);
+	}
+
 	return __open_driver("/dev/dri/renderD", 128, chipset);
 }
 
+static int __drm_open_with_nth_filter(int num, int chipset, bool open_render)
+{
+	struct igt_device_card card;
+	const char *filter, *devname;
+	bool match;
+	int n = igt_device_filter_count();
+
+	if (!n || num < 0 || num >= n) {
+		igt_warn("No device filter num == %d passed\n", num);
+		return -1;
+	}
+
+	filter = igt_device_filter_get(num);
+	match = igt_device_card_match(filter, &card);
+	if (!match) {
+		igt_warn("No device match filter: %s\n", filter);
+		return -1;
+	}
+
+	if (!strlen(card.card) && !strlen(card.render))
+		return -1;
+
+	devname = open_render ? card.render : card.card;
+	if (!strlen(devname)) {
+		igt_warn("No %s node matching filter: %s\n",
+			 open_render ? "render" : "card", filter);
+		return -1;
+	}
+	return __open_driver_exact(devname, chipset);
+}
+
+/**
+ * drm_open_card_with_nth_filter:
+ * @num: number of --device argument
+ * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL
+ *
+ * Open /dev/dri/cardX device using multi-device selection API.
+ * When test require to open more than one device selection uses filter
+ * passed as --device argument. Arguments @num indicate filter number
+ * and @chipset expected device card chipset.
+ *
+ * An open DRM fd or -1 on error
+ */
+int drm_open_card_with_nth_filter(int num, int chipset)
+{
+	return __drm_open_with_nth_filter(num, chipset, false);
+}
+
+/**
+ * drm_open_render_with_nth_filter:
+ * @num: number of --device argument
+ * @chipset: OR'd flags for each chipset to search, eg. #DRIVER_INTEL
+ *
+ * Open /dev/dri/renderDX device using multi-device selection API.
+ *
+ * When test require to open more than one device selection uses filter
+ * passed as --device argument. Arguments @num indicate filter number
+ * and @chipset expected device card chipset.
+ *
+ * An open DRM fd or -1 on error
+ */
+int drm_open_render_with_nth_filter(int num, int chipset)
+{
+	return __drm_open_with_nth_filter(num, chipset, true);
+}
+
+/**
+ * drm_open_card:
+ * @card: pointer to igt_device_card structure
+ *
+ * Open /dev/dri/cardX device using multi-device selection API.
+ *
+ * Require filled @card argument (see igt_device_card_match() function).
+ *
+ * An open DRM fd or -1 on error
+ */
+int drm_open_card(struct igt_device_card *card)
+{
+	if (!card || !strlen(card->card))
+		return -1;
+
+	return __open_driver_exact(card->card, card->chipset);
+}
+
+/**
+ * drm_open_render:
+ * @card: pointer to igt_device_card structure
+ *
+ * Open /dev/dri/renderDX device using multi-device selection API.
+ * Require filled @card argument (see igt_device_card_match() function).
+ *
+ * An open DRM fd or -1 on error
+ */
+int drm_open_render(struct igt_device_card *card)
+{
+	if (!card || !strlen(card->render))
+		return -1;
+
+	return __open_driver_exact(card->render, card->chipset);
+}
+
+
 static int at_exit_drm_fd = -1;
 static int at_exit_drm_render_fd = -1;
 
diff --git a/lib/drmtest.h b/lib/drmtest.h
index 614f57e6..fc2a0b57 100644
--- a/lib/drmtest.h
+++ b/lib/drmtest.h
@@ -50,6 +50,7 @@
 #define DRIVER_AMDGPU	(1 << 3)
 #define DRIVER_V3D	(1 << 4)
 #define DRIVER_PANFROST	(1 << 5)
+
 /*
  * Exclude DRVER_VGEM from DRIVER_ANY since if you run on a system
  * with vgem as well as a supported driver, you can end up with a
@@ -81,6 +82,14 @@ int drm_open_driver(int chipset);
 int drm_open_driver_master(int chipset);
 int drm_open_driver_render(int chipset);
 int __drm_open_driver(int chipset);
+int __drm_open_driver_render(int chipset);
+
+/* Multi device API */
+int drm_open_card_with_nth_filter(int num, int chipset);
+int drm_open_render_with_nth_filter(int num, int chipset);
+struct igt_device_card;
+int drm_open_card(struct igt_device_card *card);
+int drm_open_render(struct igt_device_card *card);
 
 void gem_quiescent_gpu(int fd);
 
diff --git a/lib/igt_core.c b/lib/igt_core.c
index 1cbb09f9..a8a11b5c 100644
--- a/lib/igt_core.c
+++ b/lib/igt_core.c
@@ -71,6 +71,7 @@
 #include "igt_sysrq.h"
 #include "igt_rc.h"
 #include "igt_list.h"
+#include "igt_device_scan.h"
 
 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
@@ -245,6 +246,9 @@
  *	[Common]
  *	FrameDumpPath=/tmp # The path to dump frames that fail comparison checks
  *
+ *	# Device selection filter
+ *	Device=pci:vendor=8086,card=0;vgem:
+ *
  *	# The following section is used for configuring the Device Under Test.
  *	# It is not mandatory and allows overriding default values.
  *	[DUT]
@@ -304,6 +308,7 @@ enum {
 	OPT_DEBUG,
 	OPT_INTERACTIVE_DEBUG,
 	OPT_SKIP_CRC,
+	OPT_DEVICE,
 	OPT_HELP = 'h'
 };
 
@@ -320,6 +325,7 @@ static pthread_mutex_t log_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
 GKeyFile *igt_key_file;
 
 char *igt_frame_dump_path;
+char *igt_rc_device;
 
 static bool stderr_needs_sentinel = false;
 
@@ -624,6 +630,7 @@ static void print_usage(const char *help_str, bool output_on_stderr)
 		   "  --skip-crc-compare\n"
 		   "  --help-description\n"
 		   "  --describe\n"
+		   "  --device filter\n"
 		   "  --help|-h\n");
 	if (help_str)
 		fprintf(f, "%s\n", help_str);
@@ -688,6 +695,16 @@ static void common_init_config(void)
 	if (ret != 0)
 		igt_set_autoresume_delay(ret);
 
+	/* No IGT_DEVICE and no --device passed, try .igtrc Common::Device */
+	if (!igt_rc_device)
+		igt_rc_device =
+			g_key_file_get_string(igt_key_file, "Common",
+					      "Device", &error);
+	if (igt_rc_device && !igt_device_filter_count())
+		igt_device_filter_add(igt_rc_device);
+
+	g_clear_error(&error);
+
 out:
 	if (!key_file_env && key_file_loc)
 		free(key_file_loc);
@@ -725,6 +742,11 @@ static void common_init_env(void)
 	if (env) {
 		__set_forced_driver(env);
 	}
+
+	env = getenv("IGT_DEVICE");
+	if (env) {
+		igt_device_filter_add(env);
+	}
 }
 
 static int common_init(int *argc, char **argv,
@@ -743,6 +765,7 @@ static int common_init(int *argc, char **argv,
 		{"debug",             optional_argument, NULL, OPT_DEBUG},
 		{"interactive-debug", optional_argument, NULL, OPT_INTERACTIVE_DEBUG},
 		{"skip-crc-compare",  no_argument,       NULL, OPT_SKIP_CRC},
+		{"device",            required_argument, NULL, OPT_DEVICE},
 		{"help",              no_argument,       NULL, OPT_HELP},
 		{0, 0, 0, 0}
 	};
@@ -865,6 +888,17 @@ static int common_init(int *argc, char **argv,
 		case OPT_SKIP_CRC:
 			igt_skip_crc_compare = true;
 			goto out;
+		case OPT_DEVICE:
+			assert(optarg);
+			/* We need to free all devices passed in
+			 * IGT_DEVICE environment variable.
+			 */
+			if (getenv("IGT_DEVICE") && igt_device_filter_count()) {
+				unsetenv("IGT_DEVICE");
+				igt_device_filter_free_all();
+			}
+			igt_device_filter_add(optarg);
+			break;
 		case OPT_HELP:
 			print_usage(help_str, false);
 			ret = -1;
-- 
2.21.0



More information about the igt-dev mailing list