From 61c1bba6b4d9ccd6369b7a98413218e87fdef6c1 Mon Sep 17 00:00:00 2001 From: jsg Date: Thu, 20 Jan 2022 03:43:30 +0000 Subject: [PATCH] initial support for drm sync files, fences associated with file descriptors for explicit fencing tested with libdrm's amdgpu_test syncobj timeline tests and vkcube on intel broadwell with Mesa 21.3 (which hangs without sync file support after the 'anv: Assume syncobj support' Mesa commit) feedback and ok visa@ --- sys/dev/pci/drm/drm_linux.c | 187 +++++++++++++++++++++- sys/dev/pci/drm/i915/gem/i915_gem_shmem.c | 2 + sys/dev/pci/drm/include/linux/file.h | 13 +- sys/dev/pci/drm/include/linux/sync_file.h | 17 +- sys/kern/kern_pledge.c | 4 +- sys/sys/file.h | 3 +- 6 files changed, 201 insertions(+), 25 deletions(-) diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c index 0591c34267f..6b7eb4ed118 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.86 2022/01/17 03:54:03 jsg Exp $ */ +/* $OpenBSD: drm_linux.c,v 1.87 2022/01/20 03:43:31 jsg Exp $ */ /* * Copyright (c) 2013 Jonathan Gray * Copyright (c) 2015, 2016 Mark Kettenis @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -2782,3 +2783,187 @@ interval_tree_insert(struct interval_tree_node *node, rb_link_node(&node->rb, parent, iter); rb_insert_color_cached(&node->rb, root, false); } + +int +syncfile_read(struct file *fp, struct uio *uio, int fflags) +{ + return ENXIO; +} + +int +syncfile_write(struct file *fp, struct uio *uio, int fflags) +{ + return ENXIO; +} + +int +syncfile_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p) +{ + return ENOTTY; +} + +int +syncfile_poll(struct file *fp, int events, struct proc *p) +{ + return 0; +} + +int +syncfile_kqfilter(struct file *fp, struct knote *kn) +{ + return EINVAL; +} + +int +syncfile_stat(struct file *fp, struct stat *st, struct proc *p) +{ + memset(st, 0, sizeof(*st)); + st->st_mode = S_IFIFO; /* XXX */ + return 0; +} + +int +syncfile_close(struct file *fp, struct proc *p) +{ + struct sync_file *sf = fp->f_data; + + dma_fence_put(sf->fence); + fp->f_data = NULL; + free(sf, M_DRM, sizeof(struct sync_file)); + return 0; +} + +int +syncfile_seek(struct file *fp, off_t *offset, int whence, struct proc *p) +{ + off_t newoff; + + if (*offset != 0) + return EINVAL; + + switch (whence) { + case SEEK_SET: + newoff = 0; + break; + case SEEK_END: + newoff = 0; + break; + default: + return EINVAL; + } + mtx_enter(&fp->f_mtx); + fp->f_offset = newoff; + mtx_leave(&fp->f_mtx); + *offset = newoff; + return 0; +} + +const struct fileops syncfileops = { + .fo_read = syncfile_read, + .fo_write = syncfile_write, + .fo_ioctl = syncfile_ioctl, + .fo_poll = syncfile_poll, + .fo_kqfilter = syncfile_kqfilter, + .fo_stat = syncfile_stat, + .fo_close = syncfile_close, + .fo_seek = syncfile_seek, +}; + +void +fd_install(int fd, struct file *fp) +{ + struct proc *p = curproc; + struct filedesc *fdp = p->p_fd; + + if (fp->f_type != DTYPE_SYNC) + return; + + fdplock(fdp); + /* all callers use get_unused_fd_flags(O_CLOEXEC) */ + fdinsert(fdp, fd, UF_EXCLOSE, fp); + fdpunlock(fdp); +} + +void +fput(struct file *fp) +{ + if (fp->f_type != DTYPE_SYNC) + return; + + FRELE(fp, curproc); +} + +int +get_unused_fd_flags(unsigned int flags) +{ + struct proc *p = curproc; + struct filedesc *fdp = p->p_fd; + int error, fd; + + KASSERT((flags & O_CLOEXEC) != 0); + + fdplock(fdp); +retryalloc: + if ((error = fdalloc(p, 0, &fd)) != 0) { + if (error == ENOSPC) { + fdexpand(p); + goto retryalloc; + } + fdpunlock(fdp); + return -1; + } + fdpunlock(fdp); + + return fd; +} + +void +put_unused_fd(int fd) +{ + struct filedesc *fdp = curproc->p_fd; + + fdplock(fdp); + fdremove(fdp, fd); + fdpunlock(fdp); +} + +struct dma_fence * +sync_file_get_fence(int fd) +{ + struct proc *p = curproc; + struct filedesc *fdp = p->p_fd; + struct file *fp; + struct sync_file *sf; + struct dma_fence *f; + + if ((fp = fd_getfile(fdp, fd)) == NULL) + return NULL; + + if (fp->f_type != DTYPE_SYNC) { + FRELE(fp, p); + return NULL; + } + sf = fp->f_data; + f = dma_fence_get(sf->fence); + FRELE(sf->file, p); + return f; +} + +struct sync_file * +sync_file_create(struct dma_fence *fence) +{ + struct proc *p = curproc; + struct sync_file *sf; + struct file *fp; + + fp = fnew(p); + if (fp == NULL) + return NULL; + fp->f_type = DTYPE_SYNC; + fp->f_ops = &syncfileops; + sf = malloc(sizeof(struct sync_file), M_DRM, M_WAITOK | M_ZERO); + sf->file = fp; + sf->fence = dma_fence_get(fence); + fp->f_data = sf; + return sf; +} diff --git a/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c b/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c index 57fb137638e..5d05dcc985e 100644 --- a/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c +++ b/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c @@ -539,7 +539,9 @@ static void shmem_release(struct drm_i915_gem_object *obj) if (i915_gem_object_has_struct_page(obj)) i915_gem_object_release_memory_region(obj); +#ifdef __linux__ fput(obj->base.filp); +#endif } const struct drm_i915_gem_object_ops i915_gem_shmem_ops = { diff --git a/sys/dev/pci/drm/include/linux/file.h b/sys/dev/pci/drm/include/linux/file.h index 69c80d7161a..f59981db185 100644 --- a/sys/dev/pci/drm/include/linux/file.h +++ b/sys/dev/pci/drm/include/linux/file.h @@ -7,15 +7,10 @@ #include #include -#define fput(a) -#define fd_install(a, b) -#define put_unused_fd(a) +void fd_install(int, struct file *); +void fput(struct file *); -static inline int -get_unused_fd_flags(unsigned int flags) -{ - printf("%s: stub\n", __func__); - return -1; -} +int get_unused_fd_flags(unsigned int); +void put_unused_fd(int); #endif diff --git a/sys/dev/pci/drm/include/linux/sync_file.h b/sys/dev/pci/drm/include/linux/sync_file.h index e8daa6d7877..aa949314b06 100644 --- a/sys/dev/pci/drm/include/linux/sync_file.h +++ b/sys/dev/pci/drm/include/linux/sync_file.h @@ -7,20 +7,11 @@ #include struct sync_file { + struct file *file; + struct dma_fence *fence; }; -static inline struct dma_fence * -sync_file_get_fence(int fd) -{ - printf("%s: stub\n", __func__); - return NULL; -} - -static inline struct sync_file * -sync_file_create(struct dma_fence *fence) -{ - printf("%s: stub\n", __func__); - return NULL; -} +struct dma_fence *sync_file_get_fence(int); +struct sync_file *sync_file_create(struct dma_fence *); #endif diff --git a/sys/kern/kern_pledge.c b/sys/kern/kern_pledge.c index c97091bf77f..6687bf91f09 100644 --- a/sys/kern/kern_pledge.c +++ b/sys/kern/kern_pledge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_pledge.c,v 1.277 2021/12/23 18:50:32 guenther Exp $ */ +/* $OpenBSD: kern_pledge.c,v 1.278 2022/01/20 03:43:30 jsg Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -771,6 +771,7 @@ pledge_recvfd(struct proc *p, struct file *fp) case DTYPE_SOCKET: case DTYPE_PIPE: case DTYPE_DMABUF: + case DTYPE_SYNC: return (0); case DTYPE_VNODE: vp = fp->f_data; @@ -798,6 +799,7 @@ pledge_sendfd(struct proc *p, struct file *fp) case DTYPE_SOCKET: case DTYPE_PIPE: case DTYPE_DMABUF: + case DTYPE_SYNC: return (0); case DTYPE_VNODE: vp = fp->f_data; diff --git a/sys/sys/file.h b/sys/sys/file.h index 19136100ed8..0a9105e1f2c 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -1,4 +1,4 @@ -/* $OpenBSD: file.h,v 1.64 2021/10/25 10:24:54 claudio Exp $ */ +/* $OpenBSD: file.h,v 1.65 2022/01/20 03:43:31 jsg Exp $ */ /* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */ /* @@ -45,6 +45,7 @@ #define DTYPE_PIPE 3 /* pipe */ #define DTYPE_KQUEUE 4 /* event queue */ #define DTYPE_DMABUF 5 /* DMA buffer (for DRM) */ +#define DTYPE_SYNC 6 /* sync file (for DRM) */ #ifdef _KERNEL struct proc; -- 2.20.1