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;
 }

Reply via email to