blob: 3a8f210314400eb19e55e61f5b7390c8ea331902 [file] [log] [blame]
Erik Gilling7ad530b2013-02-28 16:42:57 -08001/*
2 * drivers/base/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
Erik Gillingaf7582f2013-02-28 16:43:00 -080017#include <linux/debugfs.h>
Erik Gilling8edb4ad2013-02-28 16:43:06 -080018#include <linux/export.h>
Erik Gilling7ad530b2013-02-28 16:42:57 -080019#include <linux/file.h>
20#include <linux/fs.h>
21#include <linux/kernel.h>
Erik Gilling57b505b2013-02-28 16:43:04 -080022#include <linux/poll.h>
Erik Gilling7ad530b2013-02-28 16:42:57 -080023#include <linux/sched.h>
Erik Gillingaf7582f2013-02-28 16:43:00 -080024#include <linux/seq_file.h>
Erik Gilling7ad530b2013-02-28 16:42:57 -080025#include <linux/slab.h>
26#include <linux/uaccess.h>
27#include <linux/anon_inodes.h>
28
29#include "sync.h"
30
Erik Gillingb699a642013-02-28 16:43:23 -080031#define CREATE_TRACE_POINTS
32#include "trace/sync.h"
33
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020034static const struct fence_ops android_fence_ops;
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -020035static const struct file_operations sync_file_fops;
Erik Gillingaf7582f2013-02-28 16:43:00 -080036
Erik Gilling7ad530b2013-02-28 16:42:57 -080037struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
38 int size, const char *name)
39{
40 struct sync_timeline *obj;
41
42 if (size < sizeof(struct sync_timeline))
43 return NULL;
44
45 obj = kzalloc(size, GFP_KERNEL);
Ioana Ciornei375fb532015-11-01 16:38:20 +020046 if (!obj)
Erik Gilling7ad530b2013-02-28 16:42:57 -080047 return NULL;
48
Erik Gillingc5b86b72013-02-28 16:43:11 -080049 kref_init(&obj->kref);
Erik Gilling7ad530b2013-02-28 16:42:57 -080050 obj->ops = ops;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020051 obj->context = fence_context_alloc(1);
Erik Gilling7ad530b2013-02-28 16:42:57 -080052 strlcpy(obj->name, name, sizeof(obj->name));
53
54 INIT_LIST_HEAD(&obj->child_list_head);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020055 INIT_LIST_HEAD(&obj->active_list_head);
Erik Gilling7ad530b2013-02-28 16:42:57 -080056 spin_lock_init(&obj->child_list_lock);
57
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020058 sync_timeline_debug_add(obj);
Erik Gillingaf7582f2013-02-28 16:43:00 -080059
Erik Gilling7ad530b2013-02-28 16:42:57 -080060 return obj;
61}
Erik Gilling8edb4ad2013-02-28 16:43:06 -080062EXPORT_SYMBOL(sync_timeline_create);
Erik Gilling7ad530b2013-02-28 16:42:57 -080063
Erik Gillingc5b86b72013-02-28 16:43:11 -080064static void sync_timeline_free(struct kref *kref)
Erik Gillingaf7582f2013-02-28 16:43:00 -080065{
Erik Gillingc5b86b72013-02-28 16:43:11 -080066 struct sync_timeline *obj =
67 container_of(kref, struct sync_timeline, kref);
Erik Gillingaf7582f2013-02-28 16:43:00 -080068
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020069 sync_timeline_debug_remove(obj);
Erik Gillingaf7582f2013-02-28 16:43:00 -080070
71 kfree(obj);
72}
73
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020074static void sync_timeline_get(struct sync_timeline *obj)
75{
76 kref_get(&obj->kref);
77}
78
79static void sync_timeline_put(struct sync_timeline *obj)
80{
81 kref_put(&obj->kref, sync_timeline_free);
82}
83
Erik Gilling7ad530b2013-02-28 16:42:57 -080084void sync_timeline_destroy(struct sync_timeline *obj)
85{
Erik Gilling7ad530b2013-02-28 16:42:57 -080086 obj->destroyed = true;
Niv Yehezkel29606602014-05-24 10:28:07 -040087 /*
88 * Ensure timeline is marked as destroyed before
89 * changing timeline's fences status.
90 */
Prakash Kamliyaac5b7052014-02-04 16:08:35 -080091 smp_wmb();
Erik Gilling7ad530b2013-02-28 16:42:57 -080092
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +020093 sync_timeline_put(obj);
Erik Gilling7ad530b2013-02-28 16:42:57 -080094}
Erik Gilling8edb4ad2013-02-28 16:43:06 -080095EXPORT_SYMBOL(sync_timeline_destroy);
Erik Gilling7ad530b2013-02-28 16:42:57 -080096
Erik Gilling7ad530b2013-02-28 16:42:57 -080097void sync_timeline_signal(struct sync_timeline *obj)
98{
99 unsigned long flags;
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200100 struct fence *fence, *next;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800101
Erik Gillingb699a642013-02-28 16:43:23 -0800102 trace_sync_timeline(obj);
103
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200104 spin_lock_irqsave(&obj->child_list_lock, flags);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800105
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200106 list_for_each_entry_safe(fence, next, &obj->active_list_head,
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200107 active_list) {
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200108 if (fence_is_signaled_locked(fence))
109 list_del_init(&fence->active_list);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800110 }
111
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200112 spin_unlock_irqrestore(&obj->child_list_lock, flags);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800113}
Erik Gilling8edb4ad2013-02-28 16:43:06 -0800114EXPORT_SYMBOL(sync_timeline_signal);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800115
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200116struct fence *sync_pt_create(struct sync_timeline *obj, int size)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800117{
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200118 unsigned long flags;
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200119 struct fence *fence;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800120
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200121 if (size < sizeof(*fence))
Erik Gilling7ad530b2013-02-28 16:42:57 -0800122 return NULL;
123
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200124 fence = kzalloc(size, GFP_KERNEL);
125 if (!fence)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800126 return NULL;
127
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200128 spin_lock_irqsave(&obj->child_list_lock, flags);
129 sync_timeline_get(obj);
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200130 fence_init(fence, &android_fence_ops, &obj->child_list_lock,
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200131 obj->context, ++obj->value);
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200132 list_add_tail(&fence->child_list, &obj->child_list_head);
133 INIT_LIST_HEAD(&fence->active_list);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200134 spin_unlock_irqrestore(&obj->child_list_lock, flags);
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200135 return fence;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800136}
Erik Gilling8edb4ad2013-02-28 16:43:06 -0800137EXPORT_SYMBOL(sync_pt_create);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800138
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200139static struct sync_file *sync_file_alloc(int size, const char *name)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800140{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200141 struct sync_file *sync_file;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800142
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200143 sync_file = kzalloc(size, GFP_KERNEL);
144 if (!sync_file)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800145 return NULL;
146
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200147 sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
148 sync_file, 0);
149 if (IS_ERR(sync_file->file))
Erik Gilling7ad530b2013-02-28 16:42:57 -0800150 goto err;
151
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200152 kref_init(&sync_file->kref);
153 strlcpy(sync_file->name, name, sizeof(sync_file->name));
Erik Gilling7ad530b2013-02-28 16:42:57 -0800154
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200155 init_waitqueue_head(&sync_file->wq);
Erik Gillingaf7582f2013-02-28 16:43:00 -0800156
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200157 return sync_file;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800158
159err:
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200160 kfree(sync_file);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800161 return NULL;
162}
163
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200164static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
165{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200166 struct sync_file_cb *check;
167 struct sync_file *sync_file;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200168
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200169 check = container_of(cb, struct sync_file_cb, cb);
170 sync_file = check->sync_file;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200171
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200172 if (atomic_dec_and_test(&sync_file->status))
173 wake_up_all(&sync_file->wq);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200174}
175
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200176/* TODO: implement a create which takes more that one fence */
Gustavo Padovand52ef2c2016-01-21 10:49:24 -0200177struct sync_file *sync_file_create(const char *name, struct fence *fence)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800178{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200179 struct sync_file *sync_file;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800180
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200181 sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1]),
182 name);
183 if (!sync_file)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800184 return NULL;
185
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200186 sync_file->num_fences = 1;
187 atomic_set(&sync_file->status, 1);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800188
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200189 sync_file->cbs[0].fence = fence;
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200190 sync_file->cbs[0].sync_file = sync_file;
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200191 if (fence_add_callback(fence, &sync_file->cbs[0].cb,
192 fence_check_cb_func))
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200193 atomic_dec(&sync_file->status);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200194
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200195 sync_file_debug_add(sync_file);
Erik Gillingeeb2f572013-02-28 16:43:19 -0800196
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200197 return sync_file;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800198}
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200199EXPORT_SYMBOL(sync_file_create);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800200
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200201struct sync_file *sync_file_fdget(int fd)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800202{
203 struct file *file = fget(fd);
204
Ioana Ciornei375fb532015-11-01 16:38:20 +0200205 if (!file)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800206 return NULL;
207
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200208 if (file->f_op != &sync_file_fops)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800209 goto err;
210
211 return file->private_data;
212
213err:
214 fput(file);
215 return NULL;
216}
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200217EXPORT_SYMBOL(sync_file_fdget);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800218
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200219void sync_file_put(struct sync_file *sync_file)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800220{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200221 fput(sync_file->file);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800222}
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200223EXPORT_SYMBOL(sync_file_put);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800224
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200225void sync_file_install(struct sync_file *sync_file, int fd)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800226{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200227 fd_install(fd, sync_file->file);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800228}
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200229EXPORT_SYMBOL(sync_file_install);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800230
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200231static void sync_file_add_pt(struct sync_file *sync_file, int *i,
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200232 struct fence *fence)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800233{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200234 sync_file->cbs[*i].fence = fence;
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200235 sync_file->cbs[*i].sync_file = sync_file;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800236
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200237 if (!fence_add_callback(fence, &sync_file->cbs[*i].cb,
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200238 fence_check_cb_func)) {
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200239 fence_get(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200240 (*i)++;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800241 }
Erik Gilling7ad530b2013-02-28 16:42:57 -0800242}
243
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200244struct sync_file *sync_file_merge(const char *name,
245 struct sync_file *a, struct sync_file *b)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800246{
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200247 int num_fences = a->num_fences + b->num_fences;
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200248 struct sync_file *sync_file;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200249 int i, i_a, i_b;
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200250 unsigned long size = offsetof(struct sync_file, cbs[num_fences]);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800251
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200252 sync_file = sync_file_alloc(size, name);
253 if (!sync_file)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800254 return NULL;
255
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200256 atomic_set(&sync_file->status, num_fences);
Ørjan Eide713648f2013-02-28 16:43:24 -0800257
Erik Gillingeeb2f572013-02-28 16:43:19 -0800258 /*
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200259 * Assume sync_file a and b are both ordered and have no
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200260 * duplicates with the same context.
261 *
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200262 * If a sync_file can only be created with sync_file_merge
263 * and sync_file_create, this is a reasonable assumption.
Erik Gillingeeb2f572013-02-28 16:43:19 -0800264 */
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200265 for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) {
Gustavo Padovanc88b26d2016-01-21 10:49:20 -0200266 struct fence *pt_a = a->cbs[i_a].fence;
267 struct fence *pt_b = b->cbs[i_b].fence;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800268
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200269 if (pt_a->context < pt_b->context) {
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200270 sync_file_add_pt(sync_file, &i, pt_a);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200271
272 i_a++;
273 } else if (pt_a->context > pt_b->context) {
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200274 sync_file_add_pt(sync_file, &i, pt_b);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200275
276 i_b++;
277 } else {
278 if (pt_a->seqno - pt_b->seqno <= INT_MAX)
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200279 sync_file_add_pt(sync_file, &i, pt_a);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200280 else
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200281 sync_file_add_pt(sync_file, &i, pt_b);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200282
283 i_a++;
284 i_b++;
285 }
286 }
287
288 for (; i_a < a->num_fences; i_a++)
Gustavo Padovanc88b26d2016-01-21 10:49:20 -0200289 sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200290
291 for (; i_b < b->num_fences; i_b++)
Gustavo Padovanc88b26d2016-01-21 10:49:20 -0200292 sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200293
294 if (num_fences > i)
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200295 atomic_sub(num_fences - i, &sync_file->status);
296 sync_file->num_fences = i;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200297
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200298 sync_file_debug_add(sync_file);
299 return sync_file;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800300}
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200301EXPORT_SYMBOL(sync_file_merge);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800302
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200303static const char *android_fence_get_driver_name(struct fence *fence)
304{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200305 struct sync_timeline *parent = fence_parent(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200306
307 return parent->ops->driver_name;
308}
309
310static const char *android_fence_get_timeline_name(struct fence *fence)
311{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200312 struct sync_timeline *parent = fence_parent(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200313
314 return parent->name;
315}
316
317static void android_fence_release(struct fence *fence)
318{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200319 struct sync_timeline *parent = fence_parent(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200320 unsigned long flags;
321
322 spin_lock_irqsave(fence->lock, flags);
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200323 list_del(&fence->child_list);
324 if (WARN_ON_ONCE(!list_empty(&fence->active_list)))
325 list_del(&fence->active_list);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200326 spin_unlock_irqrestore(fence->lock, flags);
327
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200328 sync_timeline_put(parent);
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200329 fence_free(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200330}
331
332static bool android_fence_signaled(struct fence *fence)
333{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200334 struct sync_timeline *parent = fence_parent(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200335 int ret;
336
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200337 ret = parent->ops->has_signaled(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200338 if (ret < 0)
339 fence->status = ret;
340 return ret;
341}
342
343static bool android_fence_enable_signaling(struct fence *fence)
344{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200345 struct sync_timeline *parent = fence_parent(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200346
347 if (android_fence_signaled(fence))
348 return false;
349
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200350 list_add_tail(&fence->active_list, &parent->active_list_head);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200351 return true;
352}
353
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200354static void android_fence_value_str(struct fence *fence,
355 char *str, int size)
356{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200357 struct sync_timeline *parent = fence_parent(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200358
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200359 if (!parent->ops->fence_value_str) {
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200360 if (size)
361 *str = 0;
362 return;
363 }
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200364 parent->ops->fence_value_str(fence, str, size);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200365}
366
367static void android_fence_timeline_value_str(struct fence *fence,
368 char *str, int size)
369{
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200370 struct sync_timeline *parent = fence_parent(fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200371
372 if (!parent->ops->timeline_value_str) {
373 if (size)
374 *str = 0;
375 return;
376 }
377 parent->ops->timeline_value_str(parent, str, size);
378}
379
380static const struct fence_ops android_fence_ops = {
381 .get_driver_name = android_fence_get_driver_name,
382 .get_timeline_name = android_fence_get_timeline_name,
383 .enable_signaling = android_fence_enable_signaling,
384 .signaled = android_fence_signaled,
385 .wait = fence_default_wait,
386 .release = android_fence_release,
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200387 .fence_value_str = android_fence_value_str,
388 .timeline_value_str = android_fence_timeline_value_str,
389};
390
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200391static void sync_file_free(struct kref *kref)
Erik Gilling01544172013-02-28 16:43:10 -0800392{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200393 struct sync_file *sync_file = container_of(kref, struct sync_file,
394 kref);
Dmitry Torokhov699f6852015-12-14 17:34:08 -0800395 int i;
Erik Gilling01544172013-02-28 16:43:10 -0800396
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200397 for (i = 0; i < sync_file->num_fences; ++i) {
Gustavo Padovanc88b26d2016-01-21 10:49:20 -0200398 fence_remove_callback(sync_file->cbs[i].fence,
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200399 &sync_file->cbs[i].cb);
Gustavo Padovanc88b26d2016-01-21 10:49:20 -0200400 fence_put(sync_file->cbs[i].fence);
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200401 }
Erik Gilling01544172013-02-28 16:43:10 -0800402
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200403 kfree(sync_file);
Erik Gilling01544172013-02-28 16:43:10 -0800404}
405
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200406static int sync_file_release(struct inode *inode, struct file *file)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800407{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200408 struct sync_file *sync_file = file->private_data;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800409
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200410 sync_file_debug_remove(sync_file);
Erik Gillingcc3c5cd2013-02-28 16:43:08 -0800411
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200412 kref_put(&sync_file->kref, sync_file_free);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800413 return 0;
414}
415
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200416static unsigned int sync_file_poll(struct file *file, poll_table *wait)
Erik Gilling57b505b2013-02-28 16:43:04 -0800417{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200418 struct sync_file *sync_file = file->private_data;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200419 int status;
Erik Gilling57b505b2013-02-28 16:43:04 -0800420
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200421 poll_wait(file, &sync_file->wq, wait);
Erik Gilling57b505b2013-02-28 16:43:04 -0800422
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200423 status = atomic_read(&sync_file->status);
Erik Gillingc6792122013-02-28 16:43:18 -0800424
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200425 if (!status)
Erik Gilling57b505b2013-02-28 16:43:04 -0800426 return POLLIN;
Janani Ravichandran5f9001d2016-02-18 17:39:11 -0500427 if (status < 0)
Erik Gilling57b505b2013-02-28 16:43:04 -0800428 return POLLERR;
Lucas Tanure6a44b502014-07-15 00:32:35 -0300429 return 0;
Erik Gilling57b505b2013-02-28 16:43:04 -0800430}
431
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200432static long sync_file_ioctl_merge(struct sync_file *sync_file,
433 unsigned long arg)
Erik Gilling7ad530b2013-02-28 16:42:57 -0800434{
Yann Droneaud9c6cd3b2013-08-15 15:10:54 +0200435 int fd = get_unused_fd_flags(O_CLOEXEC);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800436 int err;
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200437 struct sync_file *fence2, *fence3;
Erik Gilling7ad530b2013-02-28 16:42:57 -0800438 struct sync_merge_data data;
439
Rebecca Schultz Zavin92ea915a2013-02-28 16:43:12 -0800440 if (fd < 0)
441 return fd;
442
443 if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
444 err = -EFAULT;
445 goto err_put_fd;
446 }
Erik Gilling7ad530b2013-02-28 16:42:57 -0800447
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200448 fence2 = sync_file_fdget(data.fd2);
Ioana Ciornei375fb532015-11-01 16:38:20 +0200449 if (!fence2) {
Erik Gilling7ad530b2013-02-28 16:42:57 -0800450 err = -ENOENT;
451 goto err_put_fd;
452 }
453
454 data.name[sizeof(data.name) - 1] = '\0';
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200455 fence3 = sync_file_merge(data.name, sync_file, fence2);
Ioana Ciornei375fb532015-11-01 16:38:20 +0200456 if (!fence3) {
Erik Gilling7ad530b2013-02-28 16:42:57 -0800457 err = -ENOMEM;
458 goto err_put_fence2;
459 }
460
461 data.fence = fd;
462 if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
463 err = -EFAULT;
464 goto err_put_fence3;
465 }
466
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200467 sync_file_install(fence3, fd);
468 sync_file_put(fence2);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800469 return 0;
470
471err_put_fence3:
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200472 sync_file_put(fence3);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800473
474err_put_fence2:
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200475 sync_file_put(fence2);
Erik Gilling7ad530b2013-02-28 16:42:57 -0800476
477err_put_fd:
478 put_unused_fd(fd);
479 return err;
480}
481
Gustavo Padovane1786342016-02-03 11:25:31 -0200482static int sync_fill_fence_info(struct fence *fence, void *data, int size)
Erik Gilling79ba1522013-02-28 16:43:02 -0800483{
Gustavo Padovane1786342016-02-03 11:25:31 -0200484 struct sync_fence_info *info = data;
Erik Gilling79ba1522013-02-28 16:43:02 -0800485
Gustavo Padovane1786342016-02-03 11:25:31 -0200486 if (size < sizeof(*info))
Erik Gilling79ba1522013-02-28 16:43:02 -0800487 return -ENOMEM;
488
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200489 strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
490 sizeof(info->obj_name));
491 strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
Erik Gilling79ba1522013-02-28 16:43:02 -0800492 sizeof(info->driver_name));
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200493 if (fence_is_signaled(fence))
494 info->status = fence->status >= 0 ? 1 : fence->status;
495 else
496 info->status = 0;
497 info->timestamp_ns = ktime_to_ns(fence->timestamp);
Erik Gilling79ba1522013-02-28 16:43:02 -0800498
Gustavo Padovan323de432016-02-03 11:25:34 -0200499 return sizeof(*info);
Erik Gilling79ba1522013-02-28 16:43:02 -0800500}
501
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200502static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
Erik Gilling79ba1522013-02-28 16:43:02 -0800503 unsigned long arg)
504{
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200505 struct sync_file_info *info;
Erik Gilling79ba1522013-02-28 16:43:02 -0800506 __u32 size;
507 __u32 len = 0;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200508 int ret, i;
Erik Gilling79ba1522013-02-28 16:43:02 -0800509
510 if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
511 return -EFAULT;
512
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200513 if (size < sizeof(struct sync_file_info))
Erik Gilling79ba1522013-02-28 16:43:02 -0800514 return -EINVAL;
515
516 if (size > 4096)
517 size = 4096;
518
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200519 info = kzalloc(size, GFP_KERNEL);
520 if (!info)
Erik Gilling79ba1522013-02-28 16:43:02 -0800521 return -ENOMEM;
522
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200523 strlcpy(info->name, sync_file->name, sizeof(info->name));
524 info->status = atomic_read(&sync_file->status);
525 if (info->status >= 0)
526 info->status = !info->status;
Maarten Lankhorst0f0d8402014-07-01 12:57:31 +0200527
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200528 len = sizeof(struct sync_file_info);
Erik Gilling79ba1522013-02-28 16:43:02 -0800529
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200530 for (i = 0; i < sync_file->num_fences; ++i) {
Gustavo Padovanb55b54b2016-01-21 10:49:21 -0200531 struct fence *fence = sync_file->cbs[i].fence;
Erik Gilling79ba1522013-02-28 16:43:02 -0800532
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200533 ret = sync_fill_fence_info(fence, (u8 *)info + len, size - len);
Erik Gilling79ba1522013-02-28 16:43:02 -0800534
535 if (ret < 0)
536 goto out;
537
538 len += ret;
539 }
540
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200541 info->len = len;
Erik Gilling79ba1522013-02-28 16:43:02 -0800542
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200543 if (copy_to_user((void __user *)arg, info, len))
Erik Gilling79ba1522013-02-28 16:43:02 -0800544 ret = -EFAULT;
545 else
546 ret = 0;
547
548out:
Gustavo Padovanb5b24ac2016-02-03 11:25:32 -0200549 kfree(info);
Erik Gilling79ba1522013-02-28 16:43:02 -0800550
551 return ret;
552}
Erik Gilling7ad530b2013-02-28 16:42:57 -0800553
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200554static long sync_file_ioctl(struct file *file, unsigned int cmd,
Erik Gilling7ad530b2013-02-28 16:42:57 -0800555 unsigned long arg)
556{
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200557 struct sync_file *sync_file = file->private_data;
Dipak Zope7b1046e2014-08-19 04:21:54 -0400558
Erik Gilling7ad530b2013-02-28 16:42:57 -0800559 switch (cmd) {
Erik Gilling7ad530b2013-02-28 16:42:57 -0800560 case SYNC_IOC_MERGE:
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200561 return sync_file_ioctl_merge(sync_file, arg);
Erik Gillingaf7582f2013-02-28 16:43:00 -0800562
Erik Gilling79ba1522013-02-28 16:43:02 -0800563 case SYNC_IOC_FENCE_INFO:
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200564 return sync_file_ioctl_fence_info(sync_file, arg);
Erik Gilling79ba1522013-02-28 16:43:02 -0800565
Erik Gilling7ad530b2013-02-28 16:42:57 -0800566 default:
567 return -ENOTTY;
568 }
569}
570
Gustavo Padovand7fdb0a2016-01-21 10:49:19 -0200571static const struct file_operations sync_file_fops = {
572 .release = sync_file_release,
573 .poll = sync_file_poll,
574 .unlocked_ioctl = sync_file_ioctl,
575 .compat_ioctl = sync_file_ioctl,
Erik Gillingaf7582f2013-02-28 16:43:00 -0800576};
577