Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7019195d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "sync: provide a kernel interface for oneshot syncs"

parents b80cf508 8711c302
Loading
Loading
Loading
Loading
+87 −39
Original line number Diff line number Diff line
@@ -206,14 +206,13 @@ static struct sync_timeline_ops oneshot_timeline_ops = {
	.pt_value_str = oneshot_pt_value_str,
};

static int oneshot_open(struct inode *inode, struct file *file)
struct oneshot_sync_timeline *oneshot_timeline_create(const char *name)
{
	struct oneshot_sync_timeline *timeline = NULL;
	char name[32];
	char task_comm[TASK_COMM_LEN];
	static const char *default_name = "oneshot-timeline";

	get_task_comm(task_comm, current);
	snprintf(name, sizeof(name), "%s-oneshot", task_comm);
	if (name == NULL)
		name = default_name;

	timeline = (struct oneshot_sync_timeline *)
			sync_timeline_create(&oneshot_timeline_ops,
@@ -221,11 +220,35 @@ static int oneshot_open(struct inode *inode, struct file *file)
					     name);

	if (timeline == NULL)
		return -ENOMEM;
		return NULL;

	INIT_LIST_HEAD(&timeline->state_list);
	spin_lock_init(&timeline->lock);

	return timeline;
}
EXPORT_SYMBOL(oneshot_timeline_create);

void oneshot_timeline_destroy(struct oneshot_sync_timeline *timeline)
{
	if (timeline)
		sync_timeline_destroy(&timeline->obj);
}
EXPORT_SYMBOL(oneshot_timeline_destroy);

static int oneshot_open(struct inode *inode, struct file *file)
{
	struct oneshot_sync_timeline *timeline = NULL;
	char name[32];
	char task_comm[TASK_COMM_LEN];

	get_task_comm(task_comm, current);
	snprintf(name, sizeof(name), "%s-oneshot", task_comm);

	timeline = oneshot_timeline_create(name);
	if (timeline == NULL)
		return -ENOMEM;

	file->private_data = timeline;
	return 0;
}
@@ -233,17 +256,40 @@ static int oneshot_open(struct inode *inode, struct file *file)
static int oneshot_release(struct inode *inode, struct file *file)
{
	struct oneshot_sync_timeline *timeline = file->private_data;
	sync_timeline_destroy(&timeline->obj);

	oneshot_timeline_destroy(timeline);

	return 0;
}

static long oneshot_fence_create(struct oneshot_sync_timeline *timeline,
struct sync_fence *oneshot_fence_create(struct oneshot_sync_timeline *timeline,
					const char *name)
{
	struct sync_fence *fence = NULL;
	struct oneshot_sync_pt *pt = NULL;

	pt = oneshot_pt_create(timeline);
	if (pt == NULL)
		return NULL;

	fence = sync_fence_create(name, &pt->sync_pt);
	if (fence == NULL) {
		sync_pt_free(&pt->sync_pt);
		return NULL;
	}

	pt->state->orig_fence = fence;

	return fence;
}
EXPORT_SYMBOL(oneshot_fence_create);

static long oneshot_ioctl_fence_create(struct oneshot_sync_timeline *timeline,
				 unsigned long arg)
{
	struct oneshot_sync_create_fence param;
	int ret = -ENOMEM;
	struct sync_fence *fence = NULL;
	struct oneshot_sync_pt *pt = NULL;
	int fd = get_unused_fd();

	if (fd < 0)
@@ -254,15 +300,11 @@ static long oneshot_fence_create(struct oneshot_sync_timeline *timeline,
		goto out;
	}

	pt = oneshot_pt_create(timeline);
	if (pt == NULL)
		goto out;

	fence = sync_fence_create(param.name, &pt->sync_pt);
	if (fence == NULL)
	fence = oneshot_fence_create(timeline, param.name);
	if (fence == NULL) {
		ret = -ENOMEM;
		goto out;

	pt->state->orig_fence = fence;
	}

	param.fence_fd = fd;

@@ -277,32 +319,20 @@ out:
	if (ret) {
		if (fence)
			sync_fence_put(fence);
		else if (pt)
			sync_pt_free(&pt->sync_pt);
		put_unused_fd(fd);
	}
	return ret;
}

static long oneshot_fence_signal(struct oneshot_sync_timeline *timeline,
				 unsigned long arg)
int oneshot_fence_signal(struct oneshot_sync_timeline *timeline,
			struct sync_fence *fence)
{
	int ret = -EINVAL;
	int fd = -1;
	struct sync_fence *fence = NULL;
	struct oneshot_sync_state *state = NULL;
	bool signaled = false;

	if (get_user(fd, (unsigned int __user *)arg)) {
		ret = -EFAULT;
		goto out;
	}

	fence = sync_fence_fdget(fd);
	if (fence == NULL) {
		ret = -EBADF;
		goto out;
	}
	if (timeline == NULL || fence == NULL)
		return -EINVAL;

	spin_lock(&timeline->lock);
	list_for_each_entry(state, &timeline->state_list, node) {
@@ -322,13 +352,31 @@ static long oneshot_fence_signal(struct oneshot_sync_timeline *timeline,
	}
	spin_unlock(&timeline->lock);
	if (ret == -EINVAL)
		pr_debug("fence fd: %d not from this timeline\n", fd);
		pr_debug("fence: %p not from this timeline\n", fence);

	if (signaled)
		sync_timeline_signal(&timeline->obj);
out:
	if (fence)
	return ret;
}
EXPORT_SYMBOL(oneshot_fence_signal);

static long oneshot_ioctl_fence_signal(struct oneshot_sync_timeline *timeline,
				 unsigned long arg)
{
	int ret = -EINVAL;
	int fd = -1;
	struct sync_fence *fence = NULL;

	if (get_user(fd, (int __user *)arg))
		return -EFAULT;

	fence = sync_fence_fdget(fd);
	if (fence == NULL)
		return -EBADF;

	ret = oneshot_fence_signal(timeline, fence);
	sync_fence_put(fence);

	return ret;
}

@@ -339,10 +387,10 @@ static long oneshot_ioctl(struct file *file, unsigned int cmd,

	switch (cmd) {
	case ONESHOT_SYNC_IOC_CREATE_FENCE:
		return oneshot_fence_create(timeline, arg);
		return oneshot_ioctl_fence_create(timeline, arg);

	case ONESHOT_SYNC_IOC_SIGNAL_FENCE:
		return oneshot_fence_signal(timeline, arg);
		return oneshot_ioctl_fence_signal(timeline, arg);

	default:
		return -ENOTTY;
+40 −0
Original line number Diff line number Diff line
@@ -15,4 +15,44 @@

#include <uapi/linux/oneshot_sync.h>

struct oneshot_sync_timeline;
struct sync_fence;

#ifdef CONFIG_ONESHOT_SYNC

struct oneshot_sync_timeline *oneshot_timeline_create(const char *name);

void oneshot_timeline_destroy(struct oneshot_sync_timeline *);

struct sync_fence *oneshot_fence_create(struct oneshot_sync_timeline *,
					const char *name);

int oneshot_fence_signal(struct oneshot_sync_timeline *, struct sync_fence *);

#else

static inline struct oneshot_sync_timeline *
oneshot_timeline_create(const char *name)
{
	return NULL;
}

void oneshot_timeline_destroy(struct oneshot_sync_timeline *timeline)
{
}

struct sync_fence *oneshot_fence_create(struct oneshot_sync_timeline *timeline,
					const char *name)
{
	return NULL;
}

int oneshot_fence_signal(struct oneshot_sync_timeline *timeline,
			struct sync_fence *fence)
{
	return -EINVAL;
}

#endif

#endif /* LINUX_ONESHOT_SYNC_H */