diff options
| author | 2018-06-25 22:29:16 +0000 | |
|---|---|---|
| committer | 2018-06-25 22:29:16 +0000 | |
| commit | a9ee023b3d3fb138f3d4f17347289eebdc20cf07 (patch) | |
| tree | 2d1fef7ee7763bb5dcdfe77e141a4f430cdbbe1e /sys/dev/pci/drm/drm_linux.c | |
| parent | fix NULL dereference in open_listen_match_tcpip() (diff) | |
| download | wireguard-openbsd-a9ee023b3d3fb138f3d4f17347289eebdc20cf07.tar.xz wireguard-openbsd-a9ee023b3d3fb138f3d4f17347289eebdc20cf07.zip | |
Implement DRI3/prime support. This allows graphics buffers to be passed
between processes using file descriptors. This provides an alternative to
eporting them with guesable 32-bit IDs. This implementation does not (yet)
allow sharing of graphics buffers between GPUs.
ok mpi@, visa@
Diffstat (limited to 'sys/dev/pci/drm/drm_linux.c')
| -rw-r--r-- | sys/dev/pci/drm/drm_linux.c | 155 |
1 files changed, 154 insertions, 1 deletions
diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c index 0cd7f50aa55..f98cc72f414 100644 --- a/sys/dev/pci/drm/drm_linux.c +++ b/sys/dev/pci/drm/drm_linux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: drm_linux.c,v 1.23 2018/04/25 01:27:46 jsg Exp $ */ +/* $OpenBSD: drm_linux.c,v 1.24 2018/06/25 22:29:16 kettenis Exp $ */ /* * Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org> * Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org> @@ -19,6 +19,9 @@ #include <dev/pci/drm/drmP.h> #include <dev/pci/ppbreg.h> #include <sys/event.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/stat.h> struct mutex sch_mtx = MUTEX_INITIALIZER(IPL_SCHED); void *sch_ident; @@ -803,3 +806,153 @@ fence_context_alloc(unsigned int num) { return __sync_add_and_fetch(&drm_fence_count, num) - num; } + +int +dmabuf_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred) +{ + return (ENXIO); +} + +int +dmabuf_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred) +{ + return (ENXIO); +} + +int +dmabuf_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p) +{ + return (ENOTTY); +} + +int +dmabuf_poll(struct file *fp, int events, struct proc *p) +{ + return (0); +} + +int +dmabuf_kqfilter(struct file *fp, struct knote *kn) +{ + return (EINVAL); +} + +int +dmabuf_stat(struct file *fp, struct stat *st, struct proc *p) +{ + struct dma_buf *dmabuf = fp->f_data; + + memset(st, 0, sizeof(*st)); + st->st_size = dmabuf->size; + st->st_mode = S_IFIFO; /* XXX */ + return (0); +} + +int +dmabuf_close(struct file *fp, struct proc *p) +{ + struct dma_buf *dmabuf = fp->f_data; + + fp->f_data = NULL; + dmabuf->ops->release(dmabuf); + free(dmabuf, M_DRM, sizeof(struct dma_buf)); + return (0); +} + +struct fileops dmabufops = { + .fo_read = dmabuf_read, + .fo_write = dmabuf_write, + .fo_ioctl = dmabuf_ioctl, + .fo_poll = dmabuf_poll, + .fo_kqfilter = dmabuf_kqfilter, + .fo_stat = dmabuf_stat, + .fo_close = dmabuf_close +}; + +struct dma_buf * +dma_buf_export(const struct dma_buf_export_info *info) +{ + struct proc *p = curproc; + struct filedesc *fdp = p->p_fd; + struct dma_buf *dmabuf; + struct file *fp; + int fd, error; + + fdplock(fdp); + error = falloc(p, &fp, &fd); + if (error) { + fdpunlock(fdp); + return ERR_PTR(-error); + } + fdremove(fdp, fd); + fdpunlock(fdp); + fp->f_type = DTYPE_DMABUF; + fp->f_ops = &dmabufops; + dmabuf = malloc(sizeof(struct dma_buf), M_DRM, M_WAITOK | M_ZERO); + dmabuf->priv = info->priv; + dmabuf->ops = info->ops; + dmabuf->size = info->size; + dmabuf->file = fp; + fp->f_data = dmabuf; + return dmabuf; +} + +struct dma_buf * +dma_buf_get(int fd) +{ + struct proc *p = curproc; + struct filedesc *fdp = p->p_fd; + struct file *fp; + + if ((fp = fd_getfile(fdp, fd)) == NULL) + return ERR_PTR(-EBADF); + + if (fp->f_type != DTYPE_DMABUF) { + FRELE(fp, p); + return ERR_PTR(-EINVAL); + } + + return fp->f_data; +} + +void +dma_buf_put(struct dma_buf *dmabuf) +{ + KASSERT(dmabuf); + KASSERT(dmabuf->file); + + FRELE(dmabuf->file, curproc); +} + +int +dma_buf_fd(struct dma_buf *dmabuf, int flags) +{ + struct proc *p = curproc; + struct filedesc *fdp = p->p_fd; + struct file *fp = dmabuf->file; + int fd, cloexec, error; + + cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0; + + fdplock(fdp); +restart: + if ((error = fdalloc(p, 0, &fd)) != 0) { + if (error == ENOSPC) { + fdexpand(p); + goto restart; + } + fdpunlock(fdp); + return -error; + } + + fdinsert(fdp, fd, cloexec, fp); + fdpunlock(fdp); + + return fd; +} + +void +get_dma_buf(struct dma_buf *dmabuf) +{ + FREF(dmabuf->file); +} |
