Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Kamil Konieczny <kamil.konieczny@linux.intel.com>
To: igt-dev@lists.freedesktop.org
Cc: "Kamil Konieczny" <kamil.konieczny@linux.intel.com>,
	"Zbigniew Kempczyński" <zbigniew.kempczynski@intel.com>,
	"Janusz Krzysztofik" <janusz.krzysztofik@linux.intel.com>
Subject: [PATCH i-g-t v6 3/8] lib/drmtest: allow opening cards out of order
Date: Thu,  1 Feb 2024 16:50:42 +0100	[thread overview]
Message-ID: <20240201155047.48608-4-kamil.konieczny@linux.intel.com> (raw)
In-Reply-To: <20240201155047.48608-1-kamil.konieczny@linux.intel.com>

Current __drm_open_driver_another() implementation prevents
opening cards out of order, for example card 3 without previous
opens of 0..2. This can be seen with three GPU cards system and
gem_open_basic test:

sudo IGT_DEVICE=pci:vendor=Intel,card=all build/tests/gem_basic --r multigpu-create-close

IGT-Version: 1.28-g2548a539e (x86_64) (Linux: 6.7.0-rc5 x86_64)
Using IGT_SRANDOM=1706630533 for randomisation
Opened device: /dev/dri/card0
Starting subtest: multigpu-create-close
<g:0> Testing creating and closing an object.
<g:1> Opened device: /dev/dri/card1
<g:1> Testing creating and closing an object.
gem_basic: ../lib/drmtest.c:341: _is_already_opened: Assertion `as_idx <= _opened_fds_count' failed.
Received signal SIGABRT.

Relax that condition. Also relax condition for filtered devices and
allow them to open already opened ones, basically it will allow
running multi-GPU scenarios on single-GPU system with filter:

IGT_DEVICE=pci:vendor=Intel,card=0\;pci:vendor=Intel,card=0

Changes in __search_and_open() was suggested by Zbigniew.

v5:
 removed caching for names of opened cards
 relaxed opening of filtered devices
v6:
 fixed assingment in _is_already_open() (Janusz)
 simplify use of this function

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

diff --git a/lib/drmtest.c b/lib/drmtest.c
index 73d9159af..5bb084508 100644
--- a/lib/drmtest.c
+++ b/lib/drmtest.c
@@ -322,35 +322,54 @@ static int _opened_fds_count;
 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, end = min(_opened_fds_count, as_idx); i < end; ++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) {
+			if (err)
+				*err = i;
+
 			return true;
+		}
 	}
 
 	return false;
@@ -359,23 +378,38 @@ 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;
 
 		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 (fd != -1) {
+			++idx;
+			if (idx < as_idx) {
+				close(fd);
+				continue;
+			}
+
 			return fd;
+		}
 	}
 
 	return -1;
@@ -486,8 +520,7 @@ static bool __get_card_for_nth_filter(int idx, struct igt_device_card *card)
  *   * idx-th filter (starting with 0, filters are semicolon separated) is used
  *   * if there is no idx-th filter, goto 2
  *   * first device maching the filter is selected
- *   * if it's already opened (for indexes = 0..idx-1) we fail with -1
- *   * otherwise open the device and return the fd
+ *   * open the device and return the fd
  *
  * 2. compatibility mode - open the first DRM device we can find that is not
  *    already opened for indexes 0..idx-1, searching up to 16 device nodes
@@ -542,11 +575,10 @@ 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
+		else {
+			_is_already_opened(card.card, idx, NULL); /* check only filesystem boundary */
 			fd = __open_driver_exact(card.card, chipset);
-
+		}
 	} else {
 		/* no filter for device idx, let's open whatever is available */
 		fd = __open_driver("/dev/dri/card", 0, chipset, idx);
-- 
2.42.0


  parent reply	other threads:[~2024-02-01 15:51 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-01 15:50 [PATCH i-g-t v6 0/8] introduce Xe multigpu and other multi-GPU helpers Kamil Konieczny
2024-02-01 15:50 ` [PATCH i-g-t v6 1/8] lib/igt_device_scan: Introduce filtering out non-PCI devices Kamil Konieczny
2024-02-01 15:50 ` [PATCH i-g-t v6 2/8] lib/drmtest: Introduced drm_open_driver_another Kamil Konieczny
2024-02-01 15:50 ` Kamil Konieczny [this message]
2024-02-02 11:38   ` [PATCH i-g-t v6 3/8] lib/drmtest: allow opening cards out of order Janusz Krzysztofik
2024-02-02 15:32     ` Kamil Konieczny
2024-02-01 15:50 ` [PATCH i-g-t v6 4/8] lib/intel_multigpu: Introduce library for multi-GPU scenarios Kamil Konieczny
2024-02-01 15:50 ` [PATCH i-g-t v6 5/8] lib/intel_multigpu: Introduced gem_multigpu_count_class and igt_multi_fork_foreach_gpu Kamil Konieczny
2024-02-01 15:50 ` [PATCH i-g-t v6 6/8] lib/intel_multigpu: Add xe_multi_fork_foreach_gpu Kamil Konieczny
2024-02-01 15:50 ` [PATCH i-g-t v6 7/8] tests/intel/xe_exec_basic: add multigpu subtests Kamil Konieczny
2024-02-01 15:50 ` [PATCH i-g-t v6 8/8] tests/intel/gem_mmap: add basic multi-GPU subtest Kamil Konieczny
2024-02-01 17:03 ` ✓ CI.xeBAT: success for introduce Xe multigpu and other multi-GPU helpers (rev6) Patchwork
2024-02-01 17:21 ` ✓ Fi.CI.BAT: " Patchwork
2024-02-01 19:14 ` ✓ Fi.CI.IGT: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240201155047.48608-4-kamil.konieczny@linux.intel.com \
    --to=kamil.konieczny@linux.intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=janusz.krzysztofik@linux.intel.com \
    --cc=zbigniew.kempczynski@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox