diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c | 80 |
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++; } |