]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/android/sw_sync.c
staging/android: move sw_sync related code to sw_sync.c
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / android / sw_sync.c
CommitLineData
1867a23b
GP
1/*
2 * drivers/dma-buf/sw_sync.c
3 *
4 * Copyright (C) 2012 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/file.h>
18#include <linux/fs.h>
19#include <linux/uaccess.h>
20#include <linux/sync_file.h>
21
22#include "uapi/sw_sync.h"
23#include "sync.h"
24
25/*
26 * *WARNING*
27 *
28 * improper use of this can result in deadlocking kernel drivers from userspace.
29 */
30
31/* opening sw_sync create a new sync obj */
32static int sw_sync_debugfs_open(struct inode *inode, struct file *file)
33{
34 struct sync_timeline *obj;
35 char task_comm[TASK_COMM_LEN];
36
37 get_task_comm(task_comm, current);
38
39 obj = sync_timeline_create("sw_sync", task_comm);
40 if (!obj)
41 return -ENOMEM;
42
43 file->private_data = obj;
44
45 return 0;
46}
47
48static int sw_sync_debugfs_release(struct inode *inode, struct file *file)
49{
50 struct sync_timeline *obj = file->private_data;
51
52 sync_timeline_destroy(obj);
53 return 0;
54}
55
56static long sw_sync_ioctl_create_fence(struct sync_timeline *obj,
57 unsigned long arg)
58{
59 int fd = get_unused_fd_flags(O_CLOEXEC);
60 int err;
61 struct sync_pt *pt;
62 struct sync_file *sync_file;
63 struct sw_sync_create_fence_data data;
64
65 if (fd < 0)
66 return fd;
67
68 if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
69 err = -EFAULT;
70 goto err;
71 }
72
73 pt = sync_pt_create(obj, sizeof(*pt), data.value);
74 if (!pt) {
75 err = -ENOMEM;
76 goto err;
77 }
78
79 sync_file = sync_file_create(&pt->base);
80 if (!sync_file) {
81 fence_put(&pt->base);
82 err = -ENOMEM;
83 goto err;
84 }
85
86 data.fence = fd;
87 if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
88 fput(sync_file->file);
89 err = -EFAULT;
90 goto err;
91 }
92
93 fd_install(fd, sync_file->file);
94
95 return 0;
96
97err:
98 put_unused_fd(fd);
99 return err;
100}
101
102static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg)
103{
104 u32 value;
105
106 if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
107 return -EFAULT;
108
109 sync_timeline_signal(obj, value);
110
111 return 0;
112}
113
114static long sw_sync_ioctl(struct file *file, unsigned int cmd,
115 unsigned long arg)
116{
117 struct sync_timeline *obj = file->private_data;
118
119 switch (cmd) {
120 case SW_SYNC_IOC_CREATE_FENCE:
121 return sw_sync_ioctl_create_fence(obj, arg);
122
123 case SW_SYNC_IOC_INC:
124 return sw_sync_ioctl_inc(obj, arg);
125
126 default:
127 return -ENOTTY;
128 }
129}
130
131const struct file_operations sw_sync_debugfs_fops = {
132 .open = sw_sync_debugfs_open,
133 .release = sw_sync_debugfs_release,
134 .unlocked_ioctl = sw_sync_ioctl,
135 .compat_ioctl = sw_sync_ioctl,
136};