[PATCH i-g-t v6 3/8] lib/drmtest: allow opening cards out of order
Kamil Konieczny
kamil.konieczny at linux.intel.com
Thu Feb 1 15:50:42 UTC 2024
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 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 | 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
More information about the igt-dev
mailing list