Branch data 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/export.h>
9 : : #include <linux/file.h>
10 : : #include <linux/fs.h>
11 : : #include <linux/kernel.h>
12 : : #include <linux/poll.h>
13 : : #include <linux/sched.h>
14 : : #include <linux/slab.h>
15 : : #include <linux/uaccess.h>
16 : : #include <linux/anon_inodes.h>
17 : : #include <linux/sync_file.h>
18 : : #include <uapi/linux/sync_file.h>
19 : :
20 : : static const struct file_operations sync_file_fops;
21 : :
22 : 0 : static struct sync_file *sync_file_alloc(void)
23 : : {
24 : 0 : struct sync_file *sync_file;
25 : :
26 : 0 : sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL);
27 [ # # ]: 0 : if (!sync_file)
28 : : return NULL;
29 : :
30 : 0 : sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
31 : : sync_file, 0);
32 [ # # ]: 0 : if (IS_ERR(sync_file->file))
33 : 0 : goto err;
34 : :
35 : 0 : init_waitqueue_head(&sync_file->wq);
36 : :
37 : 0 : INIT_LIST_HEAD(&sync_file->cb.node);
38 : :
39 : 0 : return sync_file;
40 : :
41 : : err:
42 : 0 : kfree(sync_file);
43 : 0 : return NULL;
44 : : }
45 : :
46 : 0 : static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
47 : : {
48 : 0 : struct sync_file *sync_file;
49 : :
50 : 0 : sync_file = container_of(cb, struct sync_file, cb);
51 : :
52 : 0 : wake_up_all(&sync_file->wq);
53 : 0 : }
54 : :
55 : : /**
56 : : * sync_file_create() - creates a sync file
57 : : * @fence: fence to add to the sync_fence
58 : : *
59 : : * Creates a sync_file containg @fence. This function acquires and additional
60 : : * reference of @fence for the newly-created &sync_file, if it succeeds. The
61 : : * sync_file can be released with fput(sync_file->file). Returns the
62 : : * sync_file or NULL in case of error.
63 : : */
64 : 0 : struct sync_file *sync_file_create(struct dma_fence *fence)
65 : : {
66 : 0 : struct sync_file *sync_file;
67 : :
68 : 0 : sync_file = sync_file_alloc();
69 [ # # ]: 0 : if (!sync_file)
70 : : return NULL;
71 : :
72 [ # # ]: 0 : sync_file->fence = dma_fence_get(fence);
73 : :
74 : 0 : return sync_file;
75 : : }
76 : : EXPORT_SYMBOL(sync_file_create);
77 : :
78 : 0 : static struct sync_file *sync_file_fdget(int fd)
79 : : {
80 : 0 : struct file *file = fget(fd);
81 : :
82 [ # # ]: 0 : if (!file)
83 : : return NULL;
84 : :
85 [ # # ]: 0 : if (file->f_op != &sync_file_fops)
86 : 0 : goto err;
87 : :
88 : 0 : return file->private_data;
89 : :
90 : : err:
91 : 0 : fput(file);
92 : 0 : return NULL;
93 : : }
94 : :
95 : : /**
96 : : * sync_file_get_fence - get the fence related to the sync_file fd
97 : : * @fd: sync_file fd to get the fence from
98 : : *
99 : : * Ensures @fd references a valid sync_file and returns a fence that
100 : : * represents all fence in the sync_file. On error NULL is returned.
101 : : */
102 : 0 : struct dma_fence *sync_file_get_fence(int fd)
103 : : {
104 : 0 : struct sync_file *sync_file;
105 : 0 : struct dma_fence *fence;
106 : :
107 : 0 : sync_file = sync_file_fdget(fd);
108 [ # # ]: 0 : if (!sync_file)
109 : : return NULL;
110 : :
111 [ # # ]: 0 : fence = dma_fence_get(sync_file->fence);
112 : 0 : fput(sync_file->file);
113 : :
114 : 0 : return fence;
115 : : }
116 : : EXPORT_SYMBOL(sync_file_get_fence);
117 : :
118 : : /**
119 : : * sync_file_get_name - get the name of the sync_file
120 : : * @sync_file: sync_file to get the fence from
121 : : * @buf: destination buffer to copy sync_file name into
122 : : * @len: available size of destination buffer.
123 : : *
124 : : * Each sync_file may have a name assigned either by the user (when merging
125 : : * sync_files together) or created from the fence it contains. In the latter
126 : : * case construction of the name is deferred until use, and so requires
127 : : * sync_file_get_name().
128 : : *
129 : : * Returns: a string representing the name.
130 : : */
131 : 0 : char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
132 : : {
133 [ # # ]: 0 : if (sync_file->user_name[0]) {
134 : 0 : strlcpy(buf, sync_file->user_name, len);
135 : : } else {
136 : 0 : struct dma_fence *fence = sync_file->fence;
137 : :
138 : 0 : snprintf(buf, len, "%s-%s%llu-%lld",
139 : 0 : fence->ops->get_driver_name(fence),
140 : 0 : fence->ops->get_timeline_name(fence),
141 : : fence->context,
142 : : fence->seqno);
143 : : }
144 : :
145 : 0 : return buf;
146 : : }
147 : :
148 : : static int sync_file_set_fence(struct sync_file *sync_file,
149 : : struct dma_fence **fences, int num_fences)
150 : : {
151 : : struct dma_fence_array *array;
152 : :
153 : : /*
154 : : * The reference for the fences in the new sync_file and held
155 : : * in add_fence() during the merge procedure, so for num_fences == 1
156 : : * we already own a new reference to the fence. For num_fence > 1
157 : : * we own the reference of the dma_fence_array creation.
158 : : */
159 : : if (num_fences == 1) {
160 : : sync_file->fence = fences[0];
161 : : kfree(fences);
162 : : } else {
163 : : array = dma_fence_array_create(num_fences, fences,
164 : : dma_fence_context_alloc(1),
165 : : 1, false);
166 : : if (!array)
167 : : return -ENOMEM;
168 : :
169 : : sync_file->fence = &array->base;
170 : : }
171 : :
172 : : return 0;
173 : : }
174 : :
175 : 0 : static struct dma_fence **get_fences(struct sync_file *sync_file,
176 : : int *num_fences)
177 : : {
178 : 0 : if (dma_fence_is_array(sync_file->fence)) {
179 : 0 : struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
180 : :
181 : 0 : *num_fences = array->num_fences;
182 : 0 : return array->fences;
183 : : }
184 : :
185 : 0 : *num_fences = 1;
186 : 0 : return &sync_file->fence;
187 : : }
188 : :
189 : 0 : static void add_fence(struct dma_fence **fences,
190 : : int *i, struct dma_fence *fence)
191 : : {
192 : 0 : fences[*i] = fence;
193 : :
194 [ # # ]: 0 : if (!dma_fence_is_signaled(fence)) {
195 [ # # ]: 0 : dma_fence_get(fence);
196 : 0 : (*i)++;
197 : : }
198 : 0 : }
199 : :
200 : : /**
201 : : * sync_file_merge() - merge two sync_files
202 : : * @name: name of new fence
203 : : * @a: sync_file a
204 : : * @b: sync_file b
205 : : *
206 : : * Creates a new sync_file which contains copies of all the fences in both
207 : : * @a and @b. @a and @b remain valid, independent sync_file. Returns the
208 : : * new merged sync_file or NULL in case of error.
209 : : */
210 : 0 : static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
211 : : struct sync_file *b)
212 : : {
213 : 0 : struct sync_file *sync_file;
214 : 0 : struct dma_fence **fences, **nfences, **a_fences, **b_fences;
215 : 0 : int i, i_a, i_b, num_fences, a_num_fences, b_num_fences;
216 : :
217 : 0 : sync_file = sync_file_alloc();
218 [ # # ]: 0 : if (!sync_file)
219 : : return NULL;
220 : :
221 [ # # ]: 0 : a_fences = get_fences(a, &a_num_fences);
222 [ # # ]: 0 : b_fences = get_fences(b, &b_num_fences);
223 [ # # ]: 0 : if (a_num_fences > INT_MAX - b_num_fences)
224 : 0 : goto err;
225 : :
226 : 0 : num_fences = a_num_fences + b_num_fences;
227 : :
228 : 0 : fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
229 [ # # ]: 0 : if (!fences)
230 : 0 : goto err;
231 : :
232 : : /*
233 : : * Assume sync_file a and b are both ordered and have no
234 : : * duplicates with the same context.
235 : : *
236 : : * If a sync_file can only be created with sync_file_merge
237 : : * and sync_file_create, this is a reasonable assumption.
238 : : */
239 [ # # # # ]: 0 : for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
240 : 0 : struct dma_fence *pt_a = a_fences[i_a];
241 : 0 : struct dma_fence *pt_b = b_fences[i_b];
242 : :
243 [ # # ]: 0 : if (pt_a->context < pt_b->context) {
244 : 0 : add_fence(fences, &i, pt_a);
245 : :
246 : 0 : i_a++;
247 [ # # ]: 0 : } else if (pt_a->context > pt_b->context) {
248 : 0 : add_fence(fences, &i, pt_b);
249 : :
250 : 0 : i_b++;
251 : : } else {
252 [ # # # # ]: 0 : if (__dma_fence_is_later(pt_a->seqno, pt_b->seqno,
253 : : pt_a->ops))
254 : 0 : add_fence(fences, &i, pt_a);
255 : : else
256 : 0 : add_fence(fences, &i, pt_b);
257 : :
258 : 0 : i_a++;
259 : 0 : i_b++;
260 : : }
261 : : }
262 : :
263 [ # # ]: 0 : for (; i_a < a_num_fences; i_a++)
264 : 0 : add_fence(fences, &i, a_fences[i_a]);
265 : :
266 [ # # ]: 0 : for (; i_b < b_num_fences; i_b++)
267 : 0 : add_fence(fences, &i, b_fences[i_b]);
268 : :
269 [ # # ]: 0 : if (i == 0)
270 [ # # ]: 0 : fences[i++] = dma_fence_get(a_fences[0]);
271 : :
272 [ # # ]: 0 : if (num_fences > i) {
273 : 0 : nfences = krealloc(fences, i * sizeof(*fences),
274 : : GFP_KERNEL);
275 [ # # ]: 0 : if (!nfences)
276 : 0 : goto err;
277 : :
278 : : fences = nfences;
279 : : }
280 : :
281 [ # # ]: 0 : if (sync_file_set_fence(sync_file, fences, i) < 0) {
282 : 0 : kfree(fences);
283 : 0 : goto err;
284 : : }
285 : :
286 : 0 : strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
287 : 0 : return sync_file;
288 : :
289 : 0 : err:
290 : 0 : fput(sync_file->file);
291 : 0 : return NULL;
292 : :
293 : : }
294 : :
295 : 0 : static int sync_file_release(struct inode *inode, struct file *file)
296 : : {
297 : 0 : struct sync_file *sync_file = file->private_data;
298 : :
299 [ # # ]: 0 : if (test_bit(POLL_ENABLED, &sync_file->flags))
300 : 0 : dma_fence_remove_callback(sync_file->fence, &sync_file->cb);
301 : 0 : dma_fence_put(sync_file->fence);
302 : 0 : kfree(sync_file);
303 : :
304 : 0 : return 0;
305 : : }
306 : :
307 : 0 : static __poll_t sync_file_poll(struct file *file, poll_table *wait)
308 : : {
309 : 0 : struct sync_file *sync_file = file->private_data;
310 : :
311 [ # # ]: 0 : poll_wait(file, &sync_file->wq, wait);
312 : :
313 [ # # # # ]: 0 : if (list_empty(&sync_file->cb.node) &&
314 : 0 : !test_and_set_bit(POLL_ENABLED, &sync_file->flags)) {
315 [ # # ]: 0 : if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
316 : : fence_check_cb_func) < 0)
317 : 0 : wake_up_all(&sync_file->wq);
318 : : }
319 : :
320 [ # # ]: 0 : return dma_fence_is_signaled(sync_file->fence) ? EPOLLIN : 0;
321 : : }
322 : :
323 : 0 : static long sync_file_ioctl_merge(struct sync_file *sync_file,
324 : : unsigned long arg)
325 : : {
326 : 0 : int fd = get_unused_fd_flags(O_CLOEXEC);
327 : 0 : int err;
328 : 0 : struct sync_file *fence2, *fence3;
329 : 0 : struct sync_merge_data data;
330 : :
331 [ # # ]: 0 : if (fd < 0)
332 : 0 : return fd;
333 : :
334 [ # # ]: 0 : if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
335 : 0 : err = -EFAULT;
336 : 0 : goto err_put_fd;
337 : : }
338 : :
339 [ # # # # ]: 0 : if (data.flags || data.pad) {
340 : 0 : err = -EINVAL;
341 : 0 : goto err_put_fd;
342 : : }
343 : :
344 : 0 : fence2 = sync_file_fdget(data.fd2);
345 [ # # ]: 0 : if (!fence2) {
346 : 0 : err = -ENOENT;
347 : 0 : goto err_put_fd;
348 : : }
349 : :
350 : 0 : data.name[sizeof(data.name) - 1] = '\0';
351 : 0 : fence3 = sync_file_merge(data.name, sync_file, fence2);
352 [ # # ]: 0 : if (!fence3) {
353 : 0 : err = -ENOMEM;
354 : 0 : goto err_put_fence2;
355 : : }
356 : :
357 : 0 : data.fence = fd;
358 [ # # ]: 0 : if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
359 : 0 : err = -EFAULT;
360 : 0 : goto err_put_fence3;
361 : : }
362 : :
363 : 0 : fd_install(fd, fence3->file);
364 : 0 : fput(fence2->file);
365 : 0 : return 0;
366 : :
367 : : err_put_fence3:
368 : 0 : fput(fence3->file);
369 : :
370 : 0 : err_put_fence2:
371 : 0 : fput(fence2->file);
372 : :
373 : 0 : err_put_fd:
374 : 0 : put_unused_fd(fd);
375 : 0 : return err;
376 : : }
377 : :
378 : 0 : static int sync_fill_fence_info(struct dma_fence *fence,
379 : : struct sync_fence_info *info)
380 : : {
381 : 0 : strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
382 : : sizeof(info->obj_name));
383 : 0 : strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
384 : : sizeof(info->driver_name));
385 : :
386 : 0 : info->status = dma_fence_get_status(fence);
387 [ # # # # ]: 0 : while (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) &&
388 : : !test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags))
389 : 0 : cpu_relax();
390 : 0 : info->timestamp_ns =
391 : : test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ?
392 [ # # ]: 0 : ktime_to_ns(fence->timestamp) :
393 : : ktime_set(0, 0);
394 : :
395 : 0 : return info->status;
396 : : }
397 : :
398 : 0 : static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
399 : : unsigned long arg)
400 : : {
401 : 0 : struct sync_file_info info;
402 : 0 : struct sync_fence_info *fence_info = NULL;
403 : 0 : struct dma_fence **fences;
404 : 0 : __u32 size;
405 : 0 : int num_fences, ret, i;
406 : :
407 [ # # ]: 0 : if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
408 : : return -EFAULT;
409 : :
410 [ # # # # ]: 0 : if (info.flags || info.pad)
411 : : return -EINVAL;
412 : :
413 [ # # ]: 0 : fences = get_fences(sync_file, &num_fences);
414 : :
415 : : /*
416 : : * Passing num_fences = 0 means that userspace doesn't want to
417 : : * retrieve any sync_fence_info. If num_fences = 0 we skip filling
418 : : * sync_fence_info and return the actual number of fences on
419 : : * info->num_fences.
420 : : */
421 [ # # ]: 0 : if (!info.num_fences) {
422 : 0 : info.status = dma_fence_get_status(sync_file->fence);
423 : 0 : goto no_fences;
424 : : } else {
425 : 0 : info.status = 1;
426 : : }
427 : :
428 [ # # ]: 0 : if (info.num_fences < num_fences)
429 : : return -EINVAL;
430 : :
431 : 0 : size = num_fences * sizeof(*fence_info);
432 : 0 : fence_info = kzalloc(size, GFP_KERNEL);
433 [ # # ]: 0 : if (!fence_info)
434 : : return -ENOMEM;
435 : :
436 [ # # ]: 0 : for (i = 0; i < num_fences; i++) {
437 : 0 : int status = sync_fill_fence_info(fences[i], &fence_info[i]);
438 [ # # ]: 0 : info.status = info.status <= 0 ? info.status : status;
439 : : }
440 : :
441 [ # # # # ]: 0 : if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
442 : : size)) {
443 : 0 : ret = -EFAULT;
444 : 0 : goto out;
445 : : }
446 : :
447 : 0 : no_fences:
448 : 0 : sync_file_get_name(sync_file, info.name, sizeof(info.name));
449 : 0 : info.num_fences = num_fences;
450 : :
451 [ # # ]: 0 : if (copy_to_user((void __user *)arg, &info, sizeof(info)))
452 : : ret = -EFAULT;
453 : : else
454 : 0 : ret = 0;
455 : :
456 : 0 : out:
457 : 0 : kfree(fence_info);
458 : :
459 : 0 : return ret;
460 : : }
461 : :
462 : 0 : static long sync_file_ioctl(struct file *file, unsigned int cmd,
463 : : unsigned long arg)
464 : : {
465 : 0 : struct sync_file *sync_file = file->private_data;
466 : :
467 [ # # # ]: 0 : switch (cmd) {
468 : 0 : case SYNC_IOC_MERGE:
469 : 0 : return sync_file_ioctl_merge(sync_file, arg);
470 : :
471 : 0 : case SYNC_IOC_FILE_INFO:
472 : 0 : return sync_file_ioctl_fence_info(sync_file, arg);
473 : :
474 : : default:
475 : : return -ENOTTY;
476 : : }
477 : : }
478 : :
479 : : static const struct file_operations sync_file_fops = {
480 : : .release = sync_file_release,
481 : : .poll = sync_file_poll,
482 : : .unlocked_ioctl = sync_file_ioctl,
483 : : .compat_ioctl = compat_ptr_ioctl,
484 : : };
|