[PATCH i-g-t v4 3/8] lib/drmtest: allow opening cards out of order

Kamil Konieczny kamil.konieczny at linux.intel.com
Fri Jan 26 17:31:43 UTC 2024


Current __drm_open_driver_another() implementation prevents
opening cards out of order, for example card 0 and card 3. Relax
that condition. While at this, add some more error checks and
prints and also allow user to open already opened card if the
index is the same.

While at this add also caching for names of opened cards.

Changes in __search_and_open() was suggested by Zbigniew.

Cc: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>
Cc: Janusz Krzysztofik <janusz.krzysztofik at linux.intel.com>
Signed-off-by: Kamil Konieczny <kamil.konieczny at linux.intel.com>
---
 lib/drmtest.c | 100 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 83 insertions(+), 17 deletions(-)

diff --git a/lib/drmtest.c b/lib/drmtest.c
index 73d9159af..80809571b 100644
--- a/lib/drmtest.c
+++ b/lib/drmtest.c
@@ -315,42 +315,81 @@ err:
 static struct {
 	int fd;
 	struct stat stat;
+	char *fname;
 }_opened_fds[64];
 
 static int _opened_fds_count;
 
+static void _set_opened_fname(int idx, char *name)
+{
+	assert(idx < ARRAY_SIZE(_opened_fds));
+	assert(idx >= 0);
+
+	if (!name) {
+		if (_opened_fds[idx].fname)
+			free(_opened_fds[idx].fname);
+
+		_opened_fds[idx].fname = name;
+		return;
+	}
+
+	if (_opened_fds[idx].fname && !strcmp(name, _opened_fds[idx].fname))
+		return;
+
+	free(_opened_fds[idx].fname);
+	_opened_fds[idx].fname = strdup(name);
+}
+
 static void _set_opened_fd(int idx, int fd)
 {
 	assert(idx < ARRAY_SIZE(_opened_fds));
-	assert(idx <= _opened_fds_count);
+	assert(idx >= 0);
 
 	_opened_fds[idx].fd = fd;
 
 	assert(fstat(fd, &_opened_fds[idx].stat) == 0);
 
-	_opened_fds_count = idx+1;
+	for (int n = _opened_fds_count; n < idx; n++)
+		_opened_fds[n].fd = -1;
+
+	if (idx >= _opened_fds_count)
+		_opened_fds_count = idx + 1;
 }
 
-static bool _is_already_opened(const char *path, int as_idx)
+/* in *err returns -errno or index to _opened_fds[] */
+static bool _is_already_opened(const char *path, int as_idx, int *err)
 {
 	struct stat new;
 
 	assert(as_idx < ARRAY_SIZE(_opened_fds));
-	assert(as_idx <= _opened_fds_count);
+	assert(as_idx >= 0);
 
 	/*
 	 * we cannot even stat the device, so it's of no use - let's claim it's
 	 * already opened
 	 */
-	if (igt_debug_on(stat(path, &new) != 0))
+	if (igt_debug_on(stat(path, &new) != 0)) {
+		if (err)
+			*err = -errno;
+
 		return true;
+	}
+
+	if (err)
+		*err = 0;
+
+	for (int i = 0; i < _opened_fds_count && i < as_idx; ++i) {
+		if (_opened_fds[i].fd == -1)
+			continue;
 
-	for (int i = 0; i < as_idx; ++i) {
 		/* did we cross filesystem boundary? */
 		assert(_opened_fds[i].stat.st_dev == new.st_dev);
 
-		if (_opened_fds[i].stat.st_ino == new.st_ino)
+		if (_opened_fds[i].stat.st_ino == new.st_ino) {
+			*err = i;
+
 			return true;
+		}
 	}
 
 	return false;
@@ -359,23 +398,40 @@ static bool _is_already_opened(const char *path, int as_idx)
 static int __search_and_open(const char *base, int offset, unsigned int chipset, int as_idx)
 {
 	const char *forced;
+	int err;
 
 	forced = forced_driver();
 	if (forced)
 		igt_debug("Force option used: Using driver %s\n", forced);
 
-	for (int i = 0; i < 16; i++) {
+	for (int i = 0, idx = -1; i < 16 && idx < as_idx; i++) {
 		char name[80];
-		int fd;
+		int fd = -1;
 
 		sprintf(name, "%s%u", base, i + offset);
 
-		if (_is_already_opened(name, as_idx))
-			continue;
+		if (_is_already_opened(name, as_idx, &err)) {
+			if (err < 0)
+				continue;
+
+			if (idx + 1 < as_idx) {
+				++idx;
+				continue;
+			}
+		}
 
-		fd = __drm_open_device(name, chipset);
-		if (fd != -1)
+		if (err >= 0)
+			fd = __drm_open_device(name, chipset);
+		if (fd != -1) {
+			++idx;
+			if (idx < as_idx) {
+				close(fd);
+				continue;
+			}
+
+			_set_opened_fname(as_idx, name);
 			return fd;
+		}
 	}
 
 	return -1;
@@ -542,11 +598,21 @@ int __drm_open_driver_another(int idx, int chipset)
 		if (!found || !strlen(card.card))
 			igt_warn("No card matches the filter! [%s]\n",
 				 igt_device_filter_get(idx));
-		else if (_is_already_opened(card.card, idx))
-			igt_warn("card maching filter %d is already opened\n", idx);
-		else
-			fd = __open_driver_exact(card.card, chipset);
+		else {
+			int ret;
 
+			if (_is_already_opened(card.card, idx, &ret))
+				if (ret >= 0 && idx != ret)
+					igt_warn("card maching filter %d is already opened at idx %d\nfilenames: %s::%s",
+						 idx, ret, card.card, _opened_fds[ret].fname);
+				else
+					fd = __open_driver_exact(card.card, chipset);
+			else
+				fd = __open_driver_exact(card.card, chipset);
+
+			if (fd != -1)
+				_set_opened_fname(idx, card.card);
+		}
 	} else {
 		/* no filter for device idx, let's open whatever is available */
 		fd = __open_driver("/dev/dri/card", 0, chipset, idx);
-- 
2.42.0



More information about the igt-dev mailing list