Module Name: src Committed By: riastradh Date: Sun Dec 19 01:16:13 UTC 2021
Modified Files: src/sys/external/bsd/drm2/dist/drm: drm_syncobj.c Log Message: Tweak fd, timedwait APIs. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c diff -u src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.2 src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.3 --- src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c:1.2 Sat Dec 18 23:44:57 2021 +++ src/sys/external/bsd/drm2/dist/drm/drm_syncobj.c Sun Dec 19 01:16:13 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: drm_syncobj.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $ */ +/* $NetBSD: drm_syncobj.c,v 1.3 2021/12/19 01:16:13 riastradh Exp $ */ /* * Copyright 2017 Red Hat @@ -125,7 +125,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: drm_syncobj.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: drm_syncobj.c,v 1.3 2021/12/19 01:16:13 riastradh Exp $"); #include <linux/anon_inodes.h> #include <linux/file.h> @@ -146,7 +146,12 @@ __KERNEL_RCSID(0, "$NetBSD: drm_syncobj. struct syncobj_wait_entry { struct list_head node; +#ifdef __NetBSD__ + kmutex_t *lock; + kcondvar_t *cv; +#else struct task_struct *task; +#endif struct dma_fence *fence; struct dma_fence_cb fence_cb; u64 point; @@ -499,17 +504,40 @@ static int drm_syncobj_destroy(struct dr return 0; } +#ifdef __NetBSD__ +static int drm_syncobj_fop_close(struct file *file) +#else static int drm_syncobj_file_release(struct inode *inode, struct file *file) +#endif { +#ifdef __NetBSD__ + struct drm_syncobj *syncobj = file->f_data; +#else struct drm_syncobj *syncobj = file->private_data; +#endif drm_syncobj_put(syncobj); return 0; } +#ifdef __NetBSD__ +static const struct fileops drm_syncobj_file_ops = { + .fo_name = "drm_syncobj", + .fo_read = fbadop_read, + .fo_write = fbadop_write, + .fo_ioctl = fbadop_ioctl, + .fo_fcntl = fnullop_fcntl, + .fo_poll = fnullop_poll, + .fo_stat = fbadop_stat, + .fo_close = drm_syncobj_fop_close, + .fo_kqfilter = fnullop_kqfilter, + .fo_restart = fnullop_restart, +}; +#else static const struct file_operations drm_syncobj_file_fops = { .release = drm_syncobj_file_release, }; +#endif /** * drm_syncobj_get_fd - get a file descriptor from a syncobj @@ -524,7 +552,19 @@ int drm_syncobj_get_fd(struct drm_syncob { struct file *file; int fd; +#ifdef __NetBSD__ + int ret; +#endif +#ifdef __NetBSD__ + fd = -1; + /* XXX errno NetBSD->Linux */ + ret = -fd_allocfile(&file, &fd); + if (ret) + return ret; + file->f_data = syncobj; + file->f_ops = &drm_syncobj_file_ops; +#else fd = get_unused_fd_flags(O_CLOEXEC); if (fd < 0) return fd; @@ -536,6 +576,7 @@ int drm_syncobj_get_fd(struct drm_syncob put_unused_fd(fd); return PTR_ERR(file); } +#endif drm_syncobj_get(syncobj); fd_install(fd, file); @@ -569,13 +610,24 @@ static int drm_syncobj_fd_to_handle(stru if (!f.file) return -EINVAL; +#ifdef __NetBSD__ + if (file->f_ops != &drm_syncobj_file_ops) { + fd_putfile(fd); + return -EINVAL; + } +#else if (f.file->f_op != &drm_syncobj_file_fops) { fdput(f); return -EINVAL; } +#endif /* take a reference to put in the idr */ +#ifdef __NetBSD__ + syncobj = f.file->f_data; +#else syncobj = f.file->private_data; +#endif drm_syncobj_get(syncobj); idr_preload(GFP_KERNEL); @@ -590,7 +642,11 @@ static int drm_syncobj_fd_to_handle(stru } else drm_syncobj_put(syncobj); +#ifdef __NetBSD__ + fd_putfile(fd); +#else fdput(f); +#endif return ret; } @@ -618,6 +674,50 @@ static int drm_syncobj_import_sync_file_ static int drm_syncobj_export_sync_file(struct drm_file *file_private, int handle, int *p_fd) { +#ifdef __NetBSD__ + struct dma_fence *fence; + struct sync_file *sync_file; + struct file *fp = NULL; + int fd = -1; + int ret; + + /* Allocate a file and descriptor. */ + /* XXX errno NetBSD->Linux */ + ret = -fd_allocfile(&fp, &fd); + if (ret) + goto out; + + /* Find the fence. */ + ret = drm_syncobj_find_fence(file_private, handle, &fence); + if (ret) + goto out; + + /* Create the sync file. */ + sync_file = sync_file_create(fence, fp); + + /* Release the fence. */ + dma_fence_put(fence); + + /* If the sync file creation failed, bail. */ + if (sync_file == NULL) + goto out; + + /* Success! */ + fd_affix(curproc, fp, fd); + fp = NULL; /* sync_file consumes */ + ret = 0; + +out: + /* If anything went wrong and we still have an unused file, abort. */ + if (fp != NULL) { + fd_abort(curproc, fp, fd); + fd = -1; + } + + /* Return the descriptor or -1. */ + *p_fd = fd; + return ret; +#else int ret; struct dma_fence *fence; struct sync_file *sync_file; @@ -646,6 +746,7 @@ static int drm_syncobj_export_sync_file( err_put_fd: put_unused_fd(fd); return ret; +#endif } /** * drm_syncobj_open - initalizes syncobj file-private structures at devnode open time @@ -683,6 +784,7 @@ drm_syncobj_release(struct drm_file *fil { idr_for_each(&file_private->syncobj_idr, &drm_syncobj_release_handle, file_private); + spin_lock_destroy(&file_private->syncobj_table_lock); idr_destroy(&file_private->syncobj_idr); } @@ -847,7 +949,13 @@ static void syncobj_wait_fence_func(stru struct syncobj_wait_entry *wait = container_of(cb, struct syncobj_wait_entry, fence_cb); +#ifdef __NetBSD__ + mutex_enter(wait->lock); + cv_broadcast(wait->cv); + mutex_exit(wait->lock); +#else wake_up_process(wait->task); +#endif } static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, @@ -868,7 +976,14 @@ static void syncobj_wait_syncobj_func(st wait->fence = fence; } +#ifdef __NetBSD__ + KASSERT(spin_is_locked(&syncobj->lock)); + mutex_enter(wait->lock); + cv_broadcast(wait->cv); + mutex_exit(wait->lock); +#else wake_up_process(wait->task); +#endif list_del_init(&wait->node); } @@ -883,6 +998,12 @@ static signed long drm_syncobj_array_wai struct dma_fence *fence; uint64_t *points; uint32_t signaled_count, i; +#ifdef __NetBSD__ + kmutex_t lock; + kcondvar_t cv; + mutex_init(&lock, MUTEX_DEFAULT, IPL_VM); + cv_init(&cv, "drmsynco"); +#endif points = kmalloc_array(count, sizeof(*points), GFP_KERNEL); if (points == NULL) @@ -911,7 +1032,12 @@ static signed long drm_syncobj_array_wai for (i = 0; i < count; ++i) { struct dma_fence *fence; +#ifdef __NetBSD__ + entries[i].lock = &lock; + entries[i].cv = &cv; +#else entries[i].task = current; +#endif entries[i].point = points[i]; fence = drm_syncobj_fence_get(syncobjs[i]); if (!fence || dma_fence_chain_find_seqno(&fence, points[i])) { @@ -955,7 +1081,9 @@ static signed long drm_syncobj_array_wai } do { +#ifndef __NetBSD__ set_current_state(TASK_INTERRUPTIBLE); +#endif signaled_count = 0; for (i = 0; i < count; ++i) { @@ -988,16 +1116,37 @@ static signed long drm_syncobj_array_wai goto done_waiting; } +#ifdef __NetBSD__ + unsigned long ticks = ret; + unsigned starttime = hardclock_ticks; + mutex_enter(&lock); + ret = -cv_timedwait_sig(&cv, &lock, MIN(ticks, INT_MAX)); + mutex_exit(&lock); + unsigned endtime = hardclock_ticks; + if (ret == -EINTR || ret == -ERESTART) { + ret = -ERESTARTSYS; + } else if (ret == -EWOULDBLOCK) { + if (endtime - starttime < ticks) + ret = ticks - (endtime - starttime); + else + ret = 0; + } else { + KASSERTMSG(ret == 0, "%ld", ret); + } +#else if (signal_pending(current)) { timeout = -ERESTARTSYS; goto done_waiting; } timeout = schedule_timeout(timeout); +#endif } while (1); done_waiting: +#ifndef __NetBSD__ __set_current_state(TASK_RUNNING); +#endif cleanup_entries: for (i = 0; i < count; ++i) { @@ -1011,6 +1160,8 @@ cleanup_entries: err_free_points: kfree(points); + cv_destroy(&cv); + mutex_destroy(&lock); return timeout; }