summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c80
1 files changed, 77 insertions, 3 deletions
diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
index 7abdec33428..eb90149b5d9 100644
--- a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
+++ b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
@@ -48,6 +48,11 @@
#include "util/u_dl.h"
#include "util/u_debug.h"
+#define DRM_RENDER_NODE_DEV_NAME_FORMAT "%s/renderD%d"
+#define DRM_RENDER_NODE_MAX_NODES 63
+#define DRM_RENDER_NODE_MIN_MINOR 128
+#define DRM_RENDER_NODE_MAX_MINOR (DRM_RENDER_NODE_MIN_MINOR + DRM_RENDER_NODE_MAX_NODES)
+
struct pipe_loader_drm_device {
struct pipe_loader_device base;
struct util_dl_library *lib;
@@ -151,18 +156,87 @@ open_drm_minor(int minor)
return open(path, O_RDWR, 0);
}
+static int
+open_drm_render_node_minor(int minor)
+{
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), DRM_RENDER_NODE_DEV_NAME_FORMAT, DRM_DIR_NAME,
+ minor);
+ return open(path, O_RDWR, 0);
+}
+
int
pipe_loader_drm_probe(struct pipe_loader_device **devs, int ndev)
{
- int i, j, fd;
+ int i, k, fd, num_render_node_devs;
+ int j = 0;
+
+ struct {
+ unsigned vendor_id;
+ unsigned chip_id;
+ } render_node_devs[DRM_RENDER_NODE_MAX_NODES];
+
+ /* Look for render nodes first */
+ for (i = DRM_RENDER_NODE_MIN_MINOR, j = 0;
+ i <= DRM_RENDER_NODE_MAX_MINOR; i++) {
+ fd = open_drm_render_node_minor(i);
+ struct pipe_loader_device *dev;
+ if (fd < 0)
+ continue;
- for (i = 0, j = 0; i < DRM_MAX_MINOR; i++) {
+ if (!pipe_loader_drm_probe_fd(&dev, fd, false)) {
+ close(fd);
+ continue;
+ }
+
+ render_node_devs[j].vendor_id = dev->u.pci.vendor_id;
+ render_node_devs[j].chip_id = dev->u.pci.chip_id;
+
+ if (j < ndev) {
+ devs[j] = dev;
+ } else {
+ close(fd);
+ dev->ops->release(&dev);
+ }
+ j++;
+ }
+
+ num_render_node_devs = j;
+
+ /* Next look for drm devices. */
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ struct pipe_loader_device *dev;
+ boolean duplicate = FALSE;
fd = open_drm_minor(i);
if (fd < 0)
continue;
- if (j >= ndev || !pipe_loader_drm_probe_fd(&devs[j], fd, true))
+ if (!pipe_loader_drm_probe_fd(&dev, fd, true)) {
close(fd);
+ continue;
+ }
+
+ /* Check to make sure we aren't already accessing this device via
+ * render nodes.
+ */
+ for (k = 0; k < num_render_node_devs; k++) {
+ if (dev->u.pci.vendor_id == render_node_devs[k].vendor_id &&
+ dev->u.pci.chip_id == render_node_devs[k].chip_id) {
+ close(fd);
+ dev->ops->release(&dev);
+ duplicate = TRUE;
+ break;
+ }
+ }
+
+ if (duplicate)
+ continue;
+
+ if (j < ndev) {
+ devs[j] = dev;
+ } else {
+ dev->ops->release(&dev);
+ }
j++;
}