diff options
| author | Jonathan Gray <jsg@jsg.id.au> | 2016-12-01 15:18:43 +1100 |
|---|---|---|
| committer | Emil Velikov <emil.l.velikov@gmail.com> | 2016-12-05 17:53:11 +0000 |
| commit | 08257927231e4f51c38e1d2bdbb8db0c2d4aec40 (patch) | |
| tree | 536b6251b077815068de2a861758c3e4878de2a9 | |
| parent | fd190564daa4cd530833a94606646730a5c0ee6c (diff) | |
xf86drm: implement an OpenBSD specific drmGetDevice2
DRI devices on OpenBSD are not in their own directory. They reside in
/dev with a large number of statically generated /dev nodes.
Avoid stat'ing all of /dev on OpenBSD by implementing this custom path.
v2:
- use drmGetMinorType to get node type
- adapt to drmProcessPciDevice changes
- verify drmParseSubsystemType type is PCI
- add a comment describing why this was added
Signed-off-by: Jonathan Gray <jsg@jsg.id.au>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
| -rw-r--r-- | xf86drm.c | 62 |
1 files changed, 62 insertions, 0 deletions
@@ -3251,6 +3251,67 @@ drm_device_validate_flags(uint32_t flags) */ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device) { +#ifdef __OpenBSD__ + /* + * DRI device nodes on OpenBSD are not in their own directory, they reside + * in /dev along with a large number of statically generated /dev nodes. + * Avoid stat'ing all of /dev needlessly by implementing this custom path. + */ + drmDevicePtr d; + struct stat sbuf; + char node[PATH_MAX + 1]; + const char *dev_name; + int node_type, subsystem_type; + int maj, min, n, ret; + + if (fd == -1 || device == NULL) + return -EINVAL; + + if (fstat(fd, &sbuf)) + return -errno; + + maj = major(sbuf.st_rdev); + min = minor(sbuf.st_rdev); + + if (maj != DRM_MAJOR || !S_ISCHR(sbuf.st_mode)) + return -EINVAL; + + node_type = drmGetMinorType(min); + if (node_type == -1) + return -ENODEV; + + switch (node_type) { + case DRM_NODE_PRIMARY: + dev_name = DRM_DEV_NAME; + break; + case DRM_NODE_CONTROL: + dev_name = DRM_CONTROL_DEV_NAME; + break; + case DRM_NODE_RENDER: + dev_name = DRM_RENDER_DEV_NAME; + break; + default: + return -EINVAL; + }; + + n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min); + if (n == -1 || n >= PATH_MAX) + return -errno; + if (stat(node, &sbuf)) + return -EINVAL; + + subsystem_type = drmParseSubsystemType(maj, min); + if (subsystem_type != DRM_BUS_PCI) + return -ENODEV; + + ret = drmProcessPciDevice(&d, node, node_type, maj, min, true, flags); + if (ret) + return ret; + + *device = d; + + return 0; +#else drmDevicePtr *local_devices; drmDevicePtr d; DIR *sysdir; @@ -3360,6 +3421,7 @@ free_devices: free_locals: free(local_devices); return ret; +#endif } /** |
