aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQiang Yu2016-07-14 04:10:55 -0500
committerEmil Velikov2016-07-20 17:38:35 -0500
commit3c20893daa0a56b91869d806ae0d3a8d5d8b4cba (patch)
tree0f5451ee50eb35ba7ad75ceb164bc797dcc494ce /xf86drm.c
parent5d830819480b089f62637fecc3aad11c5d1d5857 (diff)
downloadexternal-libdrm-3c20893daa0a56b91869d806ae0d3a8d5d8b4cba.tar.gz
external-libdrm-3c20893daa0a56b91869d806ae0d3a8d5d8b4cba.tar.xz
external-libdrm-3c20893daa0a56b91869d806ae0d3a8d5d8b4cba.zip
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>
Diffstat (limited to 'xf86drm.c')
-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:
3050 return ret; 3050 return ret;
3051} 3051}
3052 3052
3053/* Consider devices located on the same bus as duplicate and fold the respective
3054 * entries into a single one.
3055 *
3056 * Note: this leaves "gaps" in the array, while preserving the length.
3057 */
3053static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count) 3058static void drmFoldDuplicatedDevices(drmDevicePtr local_devices[], int count)
3054{ 3059{
3055 int node_type, i, j; 3060 int node_type, i, j;
@@ -3088,6 +3093,7 @@ int drmGetDevice(int fd, drmDevicePtr *device)
3088 int maj, min; 3093 int maj, min;
3089 int ret, i, node_count; 3094 int ret, i, node_count;
3090 int max_count = 16; 3095 int max_count = 16;
3096 dev_t find_rdev;
3091 3097
3092 if (fd == -1 || device == NULL) 3098 if (fd == -1 || device == NULL)
3093 return -EINVAL; 3099 return -EINVAL;
@@ -3095,6 +3101,7 @@ int drmGetDevice(int fd, drmDevicePtr *device)
3095 if (fstat(fd, &sbuf)) 3101 if (fstat(fd, &sbuf))
3096 return -errno; 3102 return -errno;
3097 3103
3104 find_rdev = sbuf.st_rdev;
3098 maj = major(sbuf.st_rdev); 3105 maj = major(sbuf.st_rdev);
3099 min = minor(sbuf.st_rdev); 3106 min = minor(sbuf.st_rdev);
3100 3107
@@ -3155,17 +3162,21 @@ int drmGetDevice(int fd, drmDevicePtr *device)
3155 local_devices = temp; 3162 local_devices = temp;
3156 } 3163 }
3157 3164
3158 local_devices[i] = d; 3165 /* store target at local_devices[0] for ease to use below */
3166 if (find_rdev == sbuf.st_rdev && i) {
3167 local_devices[i] = local_devices[0];
3168 local_devices[0] = d;
3169 }
3170 else
3171 local_devices[i] = d;
3159 i++; 3172 i++;
3160 } 3173 }
3161 node_count = i; 3174 node_count = i;
3162 3175
3163 /* Fold nodes into a single device if they share the same bus info */
3164 drmFoldDuplicatedDevices(local_devices, node_count); 3176 drmFoldDuplicatedDevices(local_devices, node_count);
3165 3177
3166 *device = local_devices[0]; 3178 *device = local_devices[0];
3167 for (i = 1; i < node_count && local_devices[i]; i++) 3179 drmFreeDevices(&local_devices[1], node_count - 1);
3168 drmFreeDevice(&local_devices[i]);
3169 3180
3170 closedir(sysdir); 3181 closedir(sysdir);
3171 free(local_devices); 3182 free(local_devices);
@@ -3264,7 +3275,6 @@ int drmGetDevices(drmDevicePtr devices[], int max_devices)
3264 } 3275 }
3265 node_count = i; 3276 node_count = i;
3266 3277
3267 /* Fold nodes into a single device if they share the same bus info */
3268 drmFoldDuplicatedDevices(local_devices, node_count); 3278 drmFoldDuplicatedDevices(local_devices, node_count);
3269 3279
3270 device_count = 0; 3280 device_count = 0;