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