summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQiang Yu <Qiang.Yu@amd.com>2016-07-14 17:10:55 +0800
committerEmil Velikov <emil.l.velikov@gmail.com>2016-07-20 23:38:35 +0100
commit3c20893daa0a56b91869d806ae0d3a8d5d8b4cba (patch)
tree0f5451ee50eb35ba7ad75ceb164bc797dcc494ce
parent5d830819480b089f62637fecc3aad11c5d1d5857 (diff)
drm: drmGetDevice return correct device on multi GPU setups
Currently drmGetDevice always returns the first device it finds under /dev/dri/. Move the target device to the start of the list during iteration. This way during deduplication it'll preserve its place and will be returned to the user. v2: Keep the memory leak separate. v3: Move the drmFoldDuplicatedDevices description Signed-off-by: Qiang Yu <Qiang.Yu@amd.com> [Emil Velikov: move drmFoldDuplicatedDevices description, add changelog, reword commit message] Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
-rw-r--r--xf86drm.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/xf86drm.c b/xf86drm.c
index 8a858efa..9bd82b2c 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -3050,6 +3050,11 @@ free_device:
return ret;
}
+/* Consider devices located on the same bus as duplicate and fold the respective
+ * entries into a single one.
+ *
+ * Note: this leaves "gaps" in the array, while preserving the length.
+ */
static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count)
{
int node_type, i, j;
@@ -3088,6 +3093,7 @@ int drmGetDevice(int fd, drmDevicePtr *device)
int maj, min;
int ret, i, node_count;
int max_count = 16;
+ dev_t find_rdev;
if (fd == -1 || device == NULL)
return -EINVAL;
@@ -3095,6 +3101,7 @@ int drmGetDevice(int fd, drmDevicePtr *device)
if (fstat(fd, &sbuf))
return -errno;
+ find_rdev = sbuf.st_rdev;
maj = major(sbuf.st_rdev);
min = minor(sbuf.st_rdev);
@@ -3155,17 +3162,21 @@ int drmGetDevice(int fd, drmDevicePtr *device)
local_devices = temp;
}
- local_devices[i] = d;
+ /* store target at local_devices[0] for ease to use below */
+ if (find_rdev == sbuf.st_rdev && i) {
+ local_devices[i] = local_devices[0];
+ local_devices[0] = d;
+ }
+ else
+ local_devices[i] = d;
i++;
}
node_count = i;
- /* Fold nodes into a single device if they share the same bus info */
drmFoldDuplicatedDevices(local_devices, node_count);
*device = local_devices[0];
- for (i = 1; i < node_count && local_devices[i]; i++)
- drmFreeDevice(&local_devices[i]);
+ drmFreeDevices(&local_devices[1], node_count - 1);
closedir(sysdir);
free(local_devices);
@@ -3264,7 +3275,6 @@ int drmGetDevices(drmDevicePtr devices[], int max_devices)
}
node_count = i;
- /* Fold nodes into a single device if they share the same bus info */
drmFoldDuplicatedDevices(local_devices, node_count);
device_count = 0;