Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * drivers/dma-buf/sync_file.c
4 : *
5 : * Copyright (C) 2012 Google, Inc.
6 : */
7 :
8 : #include <linux/dma-fence-unwrap.h>
9 : #include <linux/export.h>
10 : #include <linux/file.h>
11 : #include <linux/fs.h>
12 : #include <linux/kernel.h>
13 : #include <linux/poll.h>
14 : #include <linux/sched.h>
15 : #include <linux/slab.h>
16 : #include <linux/uaccess.h>
17 : #include <linux/anon_inodes.h>
18 : #include <linux/sync_file.h>
19 : #include <uapi/linux/sync_file.h>
20 :
21 : static const struct file_operations sync_file_fops;
22 :
23 0 : static struct sync_file *sync_file_alloc(void)
24 : {
25 : struct sync_file *sync_file;
26 :
27 0 : sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL);
28 0 : if (!sync_file)
29 : return NULL;
30 :
31 0 : sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
32 : sync_file, 0);
33 0 : if (IS_ERR(sync_file->file))
34 : goto err;
35 :
36 0 : init_waitqueue_head(&sync_file->wq);
37 :
38 0 : INIT_LIST_HEAD(&sync_file->cb.node);
39 :
40 0 : return sync_file;
41 :
42 : err:
43 0 : kfree(sync_file);
44 0 : return NULL;
45 : }
46 :
47 0 : static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
48 : {
49 : struct sync_file *sync_file;
50 :
51 0 : sync_file = container_of(cb, struct sync_file, cb);
52 :
53 0 : wake_up_all(&sync_file->wq);
54 0 : }
55 :
56 : /**
57 : * sync_file_create() - creates a sync file
58 : * @fence: fence to add to the sync_fence
59 : *
60 : * Creates a sync_file containg @fence. This function acquires and additional
61 : * reference of @fence for the newly-created &sync_file, if it succeeds. The
62 : * sync_file can be released with fput(sync_file->file). Returns the
63 : * sync_file or NULL in case of error.
64 : */
65 0 : struct sync_file *sync_file_create(struct dma_fence *fence)
66 : {
67 : struct sync_file *sync_file;
68 :
69 0 : sync_file = sync_file_alloc();
70 0 : if (!sync_file)
71 : return NULL;
72 :
73 0 : sync_file->fence = dma_fence_get(fence);
74 :
75 0 : return sync_file;
76 : }
77 : EXPORT_SYMBOL(sync_file_create);
78 :
79 0 : static struct sync_file *sync_file_fdget(int fd)
80 : {
81 0 : struct file *file = fget(fd);
82 :
83 0 : if (!file)
84 : return NULL;
85 :
86 0 : if (file->f_op != &sync_file_fops)
87 : goto err;
88 :
89 0 : return file->private_data;
90 :
91 : err:
92 0 : fput(file);
93 0 : return NULL;
94 : }
95 :
96 : /**
97 : * sync_file_get_fence - get the fence related to the sync_file fd
98 : * @fd: sync_file fd to get the fence from
99 : *
100 : * Ensures @fd references a valid sync_file and returns a fence that
101 : * represents all fence in the sync_file. On error NULL is returned.
102 : */
103 0 : struct dma_fence *sync_file_get_fence(int fd)
104 : {
105 : struct sync_file *sync_file;
106 : struct dma_fence *fence;
107 :
108 0 : sync_file = sync_file_fdget(fd);
109 0 : if (!sync_file)
110 : return NULL;
111 :
112 0 : fence = dma_fence_get(sync_file->fence);
113 0 : fput(sync_file->file);
114 :
115 0 : return fence;
116 : }
117 : EXPORT_SYMBOL(sync_file_get_fence);
118 :
119 : /**
120 : * sync_file_get_name - get the name of the sync_file
121 : * @sync_file: sync_file to get the fence from
122 : * @buf: destination buffer to copy sync_file name into
123 : * @len: available size of destination buffer.
124 : *
125 : * Each sync_file may have a name assigned either by the user (when merging
126 : * sync_files together) or created from the fence it contains. In the latter
127 : * case construction of the name is deferred until use, and so requires
128 : * sync_file_get_name().
129 : *
130 : * Returns: a string representing the name.
131 : */
132 0 : char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
133 : {
134 0 : if (sync_file->user_name[0]) {
135 0 : strscpy(buf, sync_file->user_name, len);
136 : } else {
137 0 : struct dma_fence *fence = sync_file->fence;
138 :
139 0 : snprintf(buf, len, "%s-%s%llu-%lld",
140 0 : fence->ops->get_driver_name(fence),
141 0 : fence->ops->get_timeline_name(fence),
142 : fence->context,
143 : fence->seqno);
144 : }
145 :
146 0 : return buf;
147 : }
148 :
149 : /**
150 : * sync_file_merge() - merge two sync_files
151 : * @name: name of new fence
152 : * @a: sync_file a
153 : * @b: sync_file b
154 : *
155 : * Creates a new sync_file which contains copies of all the fences in both
156 : * @a and @b. @a and @b remain valid, independent sync_file. Returns the
157 : * new merged sync_file or NULL in case of error.
158 : */
159 0 : static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
160 : struct sync_file *b)
161 : {
162 : struct sync_file *sync_file;
163 : struct dma_fence *fence;
164 :
165 0 : sync_file = sync_file_alloc();
166 0 : if (!sync_file)
167 : return NULL;
168 :
169 0 : fence = dma_fence_unwrap_merge(a->fence, b->fence);
170 0 : if (!fence) {
171 0 : fput(sync_file->file);
172 : return NULL;
173 : }
174 0 : sync_file->fence = fence;
175 0 : strscpy(sync_file->user_name, name, sizeof(sync_file->user_name));
176 : return sync_file;
177 : }
178 :
179 0 : static int sync_file_release(struct inode *inode, struct file *file)
180 : {
181 0 : struct sync_file *sync_file = file->private_data;
182 :
183 0 : if (test_bit(POLL_ENABLED, &sync_file->flags))
184 0 : dma_fence_remove_callback(sync_file->fence, &sync_file->cb);
185 0 : dma_fence_put(sync_file->fence);
186 0 : kfree(sync_file);
187 :
188 0 : return 0;
189 : }
190 :
191 0 : static __poll_t sync_file_poll(struct file *file, poll_table *wait)
192 : {
193 0 : struct sync_file *sync_file = file->private_data;
194 :
195 0 : poll_wait(file, &sync_file->wq, wait);
196 :
197 0 : if (list_empty(&sync_file->cb.node) &&
198 0 : !test_and_set_bit(POLL_ENABLED, &sync_file->flags)) {
199 0 : if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
200 : fence_check_cb_func) < 0)
201 0 : wake_up_all(&sync_file->wq);
202 : }
203 :
204 0 : return dma_fence_is_signaled(sync_file->fence) ? EPOLLIN : 0;
205 : }
206 :
207 0 : static long sync_file_ioctl_merge(struct sync_file *sync_file,
208 : unsigned long arg)
209 : {
210 0 : int fd = get_unused_fd_flags(O_CLOEXEC);
211 : int err;
212 : struct sync_file *fence2, *fence3;
213 : struct sync_merge_data data;
214 :
215 0 : if (fd < 0)
216 0 : return fd;
217 :
218 0 : if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
219 : err = -EFAULT;
220 : goto err_put_fd;
221 : }
222 :
223 0 : if (data.flags || data.pad) {
224 : err = -EINVAL;
225 : goto err_put_fd;
226 : }
227 :
228 0 : fence2 = sync_file_fdget(data.fd2);
229 0 : if (!fence2) {
230 : err = -ENOENT;
231 : goto err_put_fd;
232 : }
233 :
234 0 : data.name[sizeof(data.name) - 1] = '\0';
235 0 : fence3 = sync_file_merge(data.name, sync_file, fence2);
236 0 : if (!fence3) {
237 : err = -ENOMEM;
238 : goto err_put_fence2;
239 : }
240 :
241 0 : data.fence = fd;
242 0 : if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
243 0 : err = -EFAULT;
244 : goto err_put_fence3;
245 : }
246 :
247 0 : fd_install(fd, fence3->file);
248 0 : fput(fence2->file);
249 0 : return 0;
250 :
251 : err_put_fence3:
252 0 : fput(fence3->file);
253 :
254 : err_put_fence2:
255 0 : fput(fence2->file);
256 :
257 : err_put_fd:
258 0 : put_unused_fd(fd);
259 0 : return err;
260 : }
261 :
262 0 : static int sync_fill_fence_info(struct dma_fence *fence,
263 : struct sync_fence_info *info)
264 : {
265 0 : strscpy(info->obj_name, fence->ops->get_timeline_name(fence),
266 : sizeof(info->obj_name));
267 0 : strscpy(info->driver_name, fence->ops->get_driver_name(fence),
268 : sizeof(info->driver_name));
269 :
270 0 : info->status = dma_fence_get_status(fence);
271 0 : while (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) &&
272 0 : !test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags))
273 : cpu_relax();
274 0 : info->timestamp_ns =
275 0 : test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ?
276 0 : ktime_to_ns(fence->timestamp) :
277 : ktime_set(0, 0);
278 :
279 0 : return info->status;
280 : }
281 :
282 0 : static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
283 : unsigned long arg)
284 : {
285 0 : struct sync_fence_info *fence_info = NULL;
286 : struct dma_fence_unwrap iter;
287 : struct sync_file_info info;
288 : unsigned int num_fences;
289 : struct dma_fence *fence;
290 : int ret;
291 : __u32 size;
292 :
293 0 : if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
294 : return -EFAULT;
295 :
296 0 : if (info.flags || info.pad)
297 : return -EINVAL;
298 :
299 0 : num_fences = 0;
300 0 : dma_fence_unwrap_for_each(fence, &iter, sync_file->fence)
301 0 : ++num_fences;
302 :
303 : /*
304 : * Passing num_fences = 0 means that userspace doesn't want to
305 : * retrieve any sync_fence_info. If num_fences = 0 we skip filling
306 : * sync_fence_info and return the actual number of fences on
307 : * info->num_fences.
308 : */
309 0 : if (!info.num_fences) {
310 0 : info.status = dma_fence_get_status(sync_file->fence);
311 0 : goto no_fences;
312 : } else {
313 0 : info.status = 1;
314 : }
315 :
316 0 : if (info.num_fences < num_fences)
317 : return -EINVAL;
318 :
319 0 : size = num_fences * sizeof(*fence_info);
320 0 : fence_info = kzalloc(size, GFP_KERNEL);
321 0 : if (!fence_info)
322 : return -ENOMEM;
323 :
324 0 : num_fences = 0;
325 0 : dma_fence_unwrap_for_each(fence, &iter, sync_file->fence) {
326 : int status;
327 :
328 0 : status = sync_fill_fence_info(fence, &fence_info[num_fences++]);
329 0 : info.status = info.status <= 0 ? info.status : status;
330 : }
331 :
332 0 : if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
333 : size)) {
334 : ret = -EFAULT;
335 : goto out;
336 : }
337 :
338 : no_fences:
339 0 : sync_file_get_name(sync_file, info.name, sizeof(info.name));
340 0 : info.num_fences = num_fences;
341 :
342 0 : if (copy_to_user((void __user *)arg, &info, sizeof(info)))
343 : ret = -EFAULT;
344 : else
345 0 : ret = 0;
346 :
347 : out:
348 0 : kfree(fence_info);
349 :
350 0 : return ret;
351 : }
352 :
353 0 : static long sync_file_ioctl(struct file *file, unsigned int cmd,
354 : unsigned long arg)
355 : {
356 0 : struct sync_file *sync_file = file->private_data;
357 :
358 0 : switch (cmd) {
359 : case SYNC_IOC_MERGE:
360 0 : return sync_file_ioctl_merge(sync_file, arg);
361 :
362 : case SYNC_IOC_FILE_INFO:
363 0 : return sync_file_ioctl_fence_info(sync_file, arg);
364 :
365 : default:
366 : return -ENOTTY;
367 : }
368 : }
369 :
370 : static const struct file_operations sync_file_fops = {
371 : .release = sync_file_release,
372 : .poll = sync_file_poll,
373 : .unlocked_ioctl = sync_file_ioctl,
374 : .compat_ioctl = compat_ptr_ioctl,
375 : };
|