6610a206bcb965b696c119ef094842dc5e429b01
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / t6xx / kbase / src / linux / mali_kbase_sync_user.c
1 /*
2  *
3  * (C) COPYRIGHT ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15
16
17
18
19
20 /**
21  * @file mali_kbase_sync_user.c
22  *
23  */
24
25 #ifdef CONFIG_SYNC
26
27 #include <linux/sched.h>
28 #include <linux/fdtable.h>
29 #include <linux/file.h>
30 #include <linux/fs.h>
31 #include <linux/module.h>
32 #include <linux/anon_inodes.h>
33 #include <linux/version.h>
34 #include <linux/uaccess.h>
35 #include <kbase/src/linux/mali_kbase_sync.h>
36 #include <kbase/mali_base_kernel_sync.h>
37
38 static int kbase_stream_close(struct inode *inode, struct file *file)
39 {
40         struct sync_timeline *tl;
41         tl = (struct sync_timeline *)file->private_data;
42         BUG_ON(!tl);
43         sync_timeline_destroy(tl);
44         return 0;
45 }
46
47 static const struct file_operations stream_fops = {
48         .owner = THIS_MODULE,
49         .release = kbase_stream_close,
50 };
51
52 mali_error kbase_stream_create(const char *name, int *const out_fd)
53 {
54         struct sync_timeline *tl;
55         BUG_ON(!out_fd);
56
57         tl = kbase_sync_timeline_alloc(name);
58         if (!tl)
59                 return MALI_ERROR_FUNCTION_FAILED;
60
61         *out_fd = anon_inode_getfd(name, &stream_fops, tl, O_RDONLY | O_CLOEXEC);
62
63         if (*out_fd < 0) {
64                 sync_timeline_destroy(tl);
65                 return MALI_ERROR_FUNCTION_FAILED;
66         } else {
67                 return MALI_ERROR_NONE;
68         }
69 }
70
71 int kbase_stream_create_fence(int tl_fd)
72 {
73         struct sync_timeline *tl;
74         struct sync_pt *pt;
75         struct sync_fence *fence;
76 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
77         struct files_struct *files;
78         struct fdtable *fdt;
79 #endif
80         int fd;
81         struct file *tl_file;
82
83         tl_file = fget(tl_fd);
84         if (tl_file == NULL)
85                 return -EBADF;
86
87         if (tl_file->f_op != &stream_fops) {
88                 fd = -EBADF;
89                 goto out;
90         }
91
92         tl = tl_file->private_data;
93
94         pt = kbase_sync_pt_alloc(tl);
95         if (!pt) {
96                 fd = -EFAULT;
97                 goto out;
98         }
99
100         fence = sync_fence_create("mali_fence", pt);
101         if (!fence) {
102                 sync_pt_free(pt);
103                 fd = -EFAULT;
104                 goto out;
105         }
106
107         /* from here the fence owns the sync_pt */
108
109         /* create a fd representing the fence */
110 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
111         fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
112         if (fd < 0) {
113                 sync_fence_put(fence);
114                 goto out;
115         }
116 #else
117         fd = get_unused_fd();
118         if (fd < 0) {
119                 sync_fence_put(fence);
120                 goto out;
121         }
122
123         files = current->files;
124         spin_lock(&files->file_lock);
125         fdt = files_fdtable(files);
126 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
127         __set_close_on_exec(fd, fdt);
128 #else
129         FD_SET(fd, fdt->close_on_exec);
130 #endif
131         spin_unlock(&files->file_lock);
132 #endif  /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */
133
134         /* bind fence to the new fd */
135         sync_fence_install(fence, fd);
136
137  out:
138         fput(tl_file);
139
140         return fd;
141 }
142
143 mali_error kbase_fence_validate(int fd)
144 {
145         struct sync_fence *fence;
146         fence = sync_fence_fdget(fd);
147         if (NULL != fence) {
148                 sync_fence_put(fence);
149                 return MALI_ERROR_NONE;
150         } else {
151                 return MALI_ERROR_FUNCTION_FAILED;
152         }
153 }
154
155 #endif                          /* CONFIG_SYNC */