Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dma-buf/sync_file.c
26278 views
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
static struct sync_file *sync_file_alloc(void)
24
{
25
struct sync_file *sync_file;
26
27
sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL);
28
if (!sync_file)
29
return NULL;
30
31
sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
32
sync_file, 0);
33
if (IS_ERR(sync_file->file))
34
goto err;
35
36
init_waitqueue_head(&sync_file->wq);
37
38
INIT_LIST_HEAD(&sync_file->cb.node);
39
40
return sync_file;
41
42
err:
43
kfree(sync_file);
44
return NULL;
45
}
46
47
static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
48
{
49
struct sync_file *sync_file;
50
51
sync_file = container_of(cb, struct sync_file, cb);
52
53
wake_up_all(&sync_file->wq);
54
}
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
struct sync_file *sync_file_create(struct dma_fence *fence)
66
{
67
struct sync_file *sync_file;
68
69
sync_file = sync_file_alloc();
70
if (!sync_file)
71
return NULL;
72
73
sync_file->fence = dma_fence_get(fence);
74
75
return sync_file;
76
}
77
EXPORT_SYMBOL(sync_file_create);
78
79
static struct sync_file *sync_file_fdget(int fd)
80
{
81
struct file *file = fget(fd);
82
83
if (!file)
84
return NULL;
85
86
if (file->f_op != &sync_file_fops)
87
goto err;
88
89
return file->private_data;
90
91
err:
92
fput(file);
93
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
struct dma_fence *sync_file_get_fence(int fd)
104
{
105
struct sync_file *sync_file;
106
struct dma_fence *fence;
107
108
sync_file = sync_file_fdget(fd);
109
if (!sync_file)
110
return NULL;
111
112
fence = dma_fence_get(sync_file->fence);
113
fput(sync_file->file);
114
115
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
char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
133
{
134
if (sync_file->user_name[0]) {
135
strscpy(buf, sync_file->user_name, len);
136
} else {
137
struct dma_fence *fence = sync_file->fence;
138
const char __rcu *timeline;
139
const char __rcu *driver;
140
141
rcu_read_lock();
142
driver = dma_fence_driver_name(fence);
143
timeline = dma_fence_timeline_name(fence);
144
snprintf(buf, len, "%s-%s%llu-%lld",
145
rcu_dereference(driver),
146
rcu_dereference(timeline),
147
fence->context,
148
fence->seqno);
149
rcu_read_unlock();
150
}
151
152
return buf;
153
}
154
155
/**
156
* sync_file_merge() - merge two sync_files
157
* @name: name of new fence
158
* @a: sync_file a
159
* @b: sync_file b
160
*
161
* Creates a new sync_file which contains copies of all the fences in both
162
* @a and @b. @a and @b remain valid, independent sync_file. Returns the
163
* new merged sync_file or NULL in case of error.
164
*/
165
static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
166
struct sync_file *b)
167
{
168
struct sync_file *sync_file;
169
struct dma_fence *fence;
170
171
sync_file = sync_file_alloc();
172
if (!sync_file)
173
return NULL;
174
175
fence = dma_fence_unwrap_merge(a->fence, b->fence);
176
if (!fence) {
177
fput(sync_file->file);
178
return NULL;
179
}
180
sync_file->fence = fence;
181
strscpy(sync_file->user_name, name, sizeof(sync_file->user_name));
182
return sync_file;
183
}
184
185
static int sync_file_release(struct inode *inode, struct file *file)
186
{
187
struct sync_file *sync_file = file->private_data;
188
189
if (test_bit(POLL_ENABLED, &sync_file->flags))
190
dma_fence_remove_callback(sync_file->fence, &sync_file->cb);
191
dma_fence_put(sync_file->fence);
192
kfree(sync_file);
193
194
return 0;
195
}
196
197
static __poll_t sync_file_poll(struct file *file, poll_table *wait)
198
{
199
struct sync_file *sync_file = file->private_data;
200
201
poll_wait(file, &sync_file->wq, wait);
202
203
if (list_empty(&sync_file->cb.node) &&
204
!test_and_set_bit(POLL_ENABLED, &sync_file->flags)) {
205
if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
206
fence_check_cb_func) < 0)
207
wake_up_all(&sync_file->wq);
208
}
209
210
return dma_fence_is_signaled(sync_file->fence) ? EPOLLIN : 0;
211
}
212
213
static long sync_file_ioctl_merge(struct sync_file *sync_file,
214
unsigned long arg)
215
{
216
int fd = get_unused_fd_flags(O_CLOEXEC);
217
int err;
218
struct sync_file *fence2, *fence3;
219
struct sync_merge_data data;
220
221
if (fd < 0)
222
return fd;
223
224
if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
225
err = -EFAULT;
226
goto err_put_fd;
227
}
228
229
if (data.flags || data.pad) {
230
err = -EINVAL;
231
goto err_put_fd;
232
}
233
234
fence2 = sync_file_fdget(data.fd2);
235
if (!fence2) {
236
err = -ENOENT;
237
goto err_put_fd;
238
}
239
240
data.name[sizeof(data.name) - 1] = '\0';
241
fence3 = sync_file_merge(data.name, sync_file, fence2);
242
if (!fence3) {
243
err = -ENOMEM;
244
goto err_put_fence2;
245
}
246
247
data.fence = fd;
248
if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
249
err = -EFAULT;
250
goto err_put_fence3;
251
}
252
253
fd_install(fd, fence3->file);
254
fput(fence2->file);
255
return 0;
256
257
err_put_fence3:
258
fput(fence3->file);
259
260
err_put_fence2:
261
fput(fence2->file);
262
263
err_put_fd:
264
put_unused_fd(fd);
265
return err;
266
}
267
268
static int sync_fill_fence_info(struct dma_fence *fence,
269
struct sync_fence_info *info)
270
{
271
const char __rcu *timeline;
272
const char __rcu *driver;
273
274
rcu_read_lock();
275
276
driver = dma_fence_driver_name(fence);
277
timeline = dma_fence_timeline_name(fence);
278
279
strscpy(info->obj_name, rcu_dereference(timeline),
280
sizeof(info->obj_name));
281
strscpy(info->driver_name, rcu_dereference(driver),
282
sizeof(info->driver_name));
283
284
info->status = dma_fence_get_status(fence);
285
info->timestamp_ns =
286
dma_fence_is_signaled(fence) ?
287
ktime_to_ns(dma_fence_timestamp(fence)) :
288
ktime_set(0, 0);
289
290
rcu_read_unlock();
291
292
return info->status;
293
}
294
295
static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
296
unsigned long arg)
297
{
298
struct sync_fence_info *fence_info = NULL;
299
struct dma_fence_unwrap iter;
300
struct sync_file_info info;
301
unsigned int num_fences;
302
struct dma_fence *fence;
303
int ret;
304
__u32 size;
305
306
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
307
return -EFAULT;
308
309
if (info.flags || info.pad)
310
return -EINVAL;
311
312
num_fences = 0;
313
dma_fence_unwrap_for_each(fence, &iter, sync_file->fence)
314
++num_fences;
315
316
/*
317
* Passing num_fences = 0 means that userspace doesn't want to
318
* retrieve any sync_fence_info. If num_fences = 0 we skip filling
319
* sync_fence_info and return the actual number of fences on
320
* info->num_fences.
321
*/
322
if (!info.num_fences) {
323
info.status = dma_fence_get_status(sync_file->fence);
324
goto no_fences;
325
} else {
326
info.status = 1;
327
}
328
329
if (info.num_fences < num_fences)
330
return -EINVAL;
331
332
size = num_fences * sizeof(*fence_info);
333
fence_info = kzalloc(size, GFP_KERNEL);
334
if (!fence_info)
335
return -ENOMEM;
336
337
num_fences = 0;
338
dma_fence_unwrap_for_each(fence, &iter, sync_file->fence) {
339
int status;
340
341
status = sync_fill_fence_info(fence, &fence_info[num_fences++]);
342
info.status = info.status <= 0 ? info.status : status;
343
}
344
345
if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
346
size)) {
347
ret = -EFAULT;
348
goto out;
349
}
350
351
no_fences:
352
sync_file_get_name(sync_file, info.name, sizeof(info.name));
353
info.num_fences = num_fences;
354
355
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
356
ret = -EFAULT;
357
else
358
ret = 0;
359
360
out:
361
kfree(fence_info);
362
363
return ret;
364
}
365
366
static int sync_file_ioctl_set_deadline(struct sync_file *sync_file,
367
unsigned long arg)
368
{
369
struct sync_set_deadline ts;
370
371
if (copy_from_user(&ts, (void __user *)arg, sizeof(ts)))
372
return -EFAULT;
373
374
if (ts.pad)
375
return -EINVAL;
376
377
dma_fence_set_deadline(sync_file->fence, ns_to_ktime(ts.deadline_ns));
378
379
return 0;
380
}
381
382
static long sync_file_ioctl(struct file *file, unsigned int cmd,
383
unsigned long arg)
384
{
385
struct sync_file *sync_file = file->private_data;
386
387
switch (cmd) {
388
case SYNC_IOC_MERGE:
389
return sync_file_ioctl_merge(sync_file, arg);
390
391
case SYNC_IOC_FILE_INFO:
392
return sync_file_ioctl_fence_info(sync_file, arg);
393
394
case SYNC_IOC_SET_DEADLINE:
395
return sync_file_ioctl_set_deadline(sync_file, arg);
396
397
default:
398
return -ENOTTY;
399
}
400
}
401
402
static const struct file_operations sync_file_fops = {
403
.release = sync_file_release,
404
.poll = sync_file_poll,
405
.unlocked_ioctl = sync_file_ioctl,
406
.compat_ioctl = compat_ptr_ioctl,
407
};
408
409