1 /* 2 * Copyright 2017 Red Hat 3 * Parts ported from amdgpu (fence wait code). 4 * Copyright 2016 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 * IN THE SOFTWARE. 24 * 25 * Authors: 26 * 27 */ 28 29 /** 30 * DOC: Overview 31 * 32 * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are 33 * persistent objects that contain an optional fence. The fence can be updated 34 * with a new fence, or be NULL. 35 * 36 * syncobj's can be waited upon, where it will wait for the underlying 37 * fence. 38 * 39 * syncobj's can be export to fd's and back, these fd's are opaque and 40 * have no other use case, except passing the syncobj between processes. 41 * 42 * Their primary use-case is to implement Vulkan fences and semaphores. 43 * 44 * syncobj have a kref reference count, but also have an optional file. 45 * The file is only created once the syncobj is exported. 46 * The file takes a reference on the kref. 47 */ 48 49 #include <drm/drmP.h> 50 #include <linux/file.h> 51 #include <linux/fs.h> 52 #include <linux/anon_inodes.h> 53 #include <linux/sync_file.h> 54 #include <linux/sched/signal.h> 55 56 #include "drm_internal.h" 57 #include <drm/drm_syncobj.h> 58 59 struct drm_syncobj_stub_fence { 60 struct dma_fence base; 61 spinlock_t lock; 62 }; 63 64 static const char *drm_syncobj_stub_fence_get_name(struct dma_fence *fence) 65 { 66 return "syncobjstub"; 67 } 68 69 static bool drm_syncobj_stub_fence_enable_signaling(struct dma_fence *fence) 70 { 71 return !dma_fence_is_signaled(fence); 72 } 73 74 static void drm_syncobj_stub_fence_release(struct dma_fence *f) 75 { 76 kfree(f); 77 } 78 static const struct dma_fence_ops drm_syncobj_stub_fence_ops = { 79 .get_driver_name = drm_syncobj_stub_fence_get_name, 80 .get_timeline_name = drm_syncobj_stub_fence_get_name, 81 .enable_signaling = drm_syncobj_stub_fence_enable_signaling, 82 .release = drm_syncobj_stub_fence_release, 83 }; 84 85 86 /** 87 * drm_syncobj_find - lookup and reference a sync object. 88 * @file_private: drm file private pointer 89 * @handle: sync object handle to lookup. 90 * 91 * Returns a reference to the syncobj pointed to by handle or NULL. The 92 * reference must be released by calling drm_syncobj_put(). 93 */ 94 struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, 95 u32 handle) 96 { 97 struct drm_syncobj *syncobj; 98 99 spin_lock(&file_private->syncobj_table_lock); 100 101 /* Check if we currently have a reference on the object */ 102 syncobj = idr_find(&file_private->syncobj_idr, handle); 103 if (syncobj) 104 drm_syncobj_get(syncobj); 105 106 spin_unlock(&file_private->syncobj_table_lock); 107 108 return syncobj; 109 } 110 EXPORT_SYMBOL(drm_syncobj_find); 111 112 static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, 113 struct drm_syncobj_cb *cb, 114 drm_syncobj_func_t func) 115 { 116 cb->func = func; 117 list_add_tail(&cb->node, &syncobj->cb_list); 118 } 119 120 static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj, 121 struct dma_fence **fence, 122 struct drm_syncobj_cb *cb, 123 drm_syncobj_func_t func) 124 { 125 int ret; 126 127 *fence = drm_syncobj_fence_get(syncobj); 128 if (*fence) 129 return 1; 130 131 spin_lock(&syncobj->lock); 132 /* We've already tried once to get a fence and failed. Now that we 133 * have the lock, try one more time just to be sure we don't add a 134 * callback when a fence has already been set. 135 */ 136 if (syncobj->fence) { 137 *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, 138 lockdep_is_held(&syncobj->lock))); 139 ret = 1; 140 } else { 141 *fence = NULL; 142 drm_syncobj_add_callback_locked(syncobj, cb, func); 143 ret = 0; 144 } 145 spin_unlock(&syncobj->lock); 146 147 return ret; 148 } 149 150 void drm_syncobj_add_callback(struct drm_syncobj *syncobj, 151 struct drm_syncobj_cb *cb, 152 drm_syncobj_func_t func) 153 { 154 spin_lock(&syncobj->lock); 155 drm_syncobj_add_callback_locked(syncobj, cb, func); 156 spin_unlock(&syncobj->lock); 157 } 158 159 void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, 160 struct drm_syncobj_cb *cb) 161 { 162 spin_lock(&syncobj->lock); 163 list_del_init(&cb->node); 164 spin_unlock(&syncobj->lock); 165 } 166 167 /** 168 * drm_syncobj_replace_fence - replace fence in a sync object. 169 * @syncobj: Sync object to replace fence in 170 * @point: timeline point 171 * @fence: fence to install in sync file. 172 * 173 * This replaces the fence on a sync object, or a timeline point fence. 174 */ 175 void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, 176 u64 point, 177 struct dma_fence *fence) 178 { 179 struct dma_fence *old_fence; 180 struct drm_syncobj_cb *cur, *tmp; 181 182 if (fence) 183 dma_fence_get(fence); 184 185 spin_lock(&syncobj->lock); 186 187 old_fence = rcu_dereference_protected(syncobj->fence, 188 lockdep_is_held(&syncobj->lock)); 189 rcu_assign_pointer(syncobj->fence, fence); 190 191 if (fence != old_fence) { 192 list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { 193 list_del_init(&cur->node); 194 cur->func(syncobj, cur); 195 } 196 } 197 198 spin_unlock(&syncobj->lock); 199 200 dma_fence_put(old_fence); 201 } 202 EXPORT_SYMBOL(drm_syncobj_replace_fence); 203 204 static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj) 205 { 206 struct drm_syncobj_stub_fence *fence; 207 fence = kzalloc(sizeof(*fence), GFP_KERNEL); 208 if (fence == NULL) 209 return -ENOMEM; 210 211 spin_lock_init(&fence->lock); 212 dma_fence_init(&fence->base, &drm_syncobj_stub_fence_ops, 213 &fence->lock, 0, 0); 214 dma_fence_signal(&fence->base); 215 216 drm_syncobj_replace_fence(syncobj, 0, &fence->base); 217 218 dma_fence_put(&fence->base); 219 220 return 0; 221 } 222 223 /** 224 * drm_syncobj_find_fence - lookup and reference the fence in a sync object 225 * @file_private: drm file private pointer 226 * @handle: sync object handle to lookup. 227 * @point: timeline point 228 * @fence: out parameter for the fence 229 * 230 * This is just a convenience function that combines drm_syncobj_find() and 231 * drm_syncobj_fence_get(). 232 * 233 * Returns 0 on success or a negative error value on failure. On success @fence 234 * contains a reference to the fence, which must be released by calling 235 * dma_fence_put(). 236 */ 237 int drm_syncobj_find_fence(struct drm_file *file_private, 238 u32 handle, u64 point, 239 struct dma_fence **fence) 240 { 241 struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); 242 int ret = 0; 243 244 if (!syncobj) 245 return -ENOENT; 246 247 *fence = drm_syncobj_fence_get(syncobj); 248 if (!*fence) { 249 ret = -EINVAL; 250 } 251 drm_syncobj_put(syncobj); 252 return ret; 253 } 254 EXPORT_SYMBOL(drm_syncobj_find_fence); 255 256 /** 257 * drm_syncobj_free - free a sync object. 258 * @kref: kref to free. 259 * 260 * Only to be called from kref_put in drm_syncobj_put. 261 */ 262 void drm_syncobj_free(struct kref *kref) 263 { 264 struct drm_syncobj *syncobj = container_of(kref, 265 struct drm_syncobj, 266 refcount); 267 drm_syncobj_replace_fence(syncobj, 0, NULL); 268 kfree(syncobj); 269 } 270 EXPORT_SYMBOL(drm_syncobj_free); 271 272 /** 273 * drm_syncobj_create - create a new syncobj 274 * @out_syncobj: returned syncobj 275 * @flags: DRM_SYNCOBJ_* flags 276 * @fence: if non-NULL, the syncobj will represent this fence 277 * 278 * This is the first function to create a sync object. After creating, drivers 279 * probably want to make it available to userspace, either through 280 * drm_syncobj_get_handle() or drm_syncobj_get_fd(). 281 * 282 * Returns 0 on success or a negative error value on failure. 283 */ 284 int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags, 285 struct dma_fence *fence) 286 { 287 int ret; 288 struct drm_syncobj *syncobj; 289 290 syncobj = kzalloc(sizeof(struct drm_syncobj), GFP_KERNEL); 291 if (!syncobj) 292 return -ENOMEM; 293 294 kref_init(&syncobj->refcount); 295 INIT_LIST_HEAD(&syncobj->cb_list); 296 spin_lock_init(&syncobj->lock); 297 298 if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) { 299 ret = drm_syncobj_assign_null_handle(syncobj); 300 if (ret < 0) { 301 drm_syncobj_put(syncobj); 302 return ret; 303 } 304 } 305 306 if (fence) 307 drm_syncobj_replace_fence(syncobj, 0, fence); 308 309 *out_syncobj = syncobj; 310 return 0; 311 } 312 EXPORT_SYMBOL(drm_syncobj_create); 313 314 /** 315 * drm_syncobj_get_handle - get a handle from a syncobj 316 * @file_private: drm file private pointer 317 * @syncobj: Sync object to export 318 * @handle: out parameter with the new handle 319 * 320 * Exports a sync object created with drm_syncobj_create() as a handle on 321 * @file_private to userspace. 322 * 323 * Returns 0 on success or a negative error value on failure. 324 */ 325 int drm_syncobj_get_handle(struct drm_file *file_private, 326 struct drm_syncobj *syncobj, u32 *handle) 327 { 328 int ret; 329 330 /* take a reference to put in the idr */ 331 drm_syncobj_get(syncobj); 332 333 idr_preload(GFP_KERNEL); 334 spin_lock(&file_private->syncobj_table_lock); 335 ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0, GFP_NOWAIT); 336 spin_unlock(&file_private->syncobj_table_lock); 337 338 idr_preload_end(); 339 340 if (ret < 0) { 341 drm_syncobj_put(syncobj); 342 return ret; 343 } 344 345 *handle = ret; 346 return 0; 347 } 348 EXPORT_SYMBOL(drm_syncobj_get_handle); 349 350 static int drm_syncobj_create_as_handle(struct drm_file *file_private, 351 u32 *handle, uint32_t flags) 352 { 353 int ret; 354 struct drm_syncobj *syncobj; 355 356 ret = drm_syncobj_create(&syncobj, flags, NULL); 357 if (ret) 358 return ret; 359 360 ret = drm_syncobj_get_handle(file_private, syncobj, handle); 361 drm_syncobj_put(syncobj); 362 return ret; 363 } 364 365 static int drm_syncobj_destroy(struct drm_file *file_private, 366 u32 handle) 367 { 368 struct drm_syncobj *syncobj; 369 370 spin_lock(&file_private->syncobj_table_lock); 371 syncobj = idr_remove(&file_private->syncobj_idr, handle); 372 spin_unlock(&file_private->syncobj_table_lock); 373 374 if (!syncobj) 375 return -EINVAL; 376 377 drm_syncobj_put(syncobj); 378 return 0; 379 } 380 381 static int drm_syncobj_file_release(struct inode *inode, struct file *file) 382 { 383 struct drm_syncobj *syncobj = file->private_data; 384 385 drm_syncobj_put(syncobj); 386 return 0; 387 } 388 389 static const struct file_operations drm_syncobj_file_fops = { 390 .release = drm_syncobj_file_release, 391 }; 392 393 /** 394 * drm_syncobj_get_fd - get a file descriptor from a syncobj 395 * @syncobj: Sync object to export 396 * @p_fd: out parameter with the new file descriptor 397 * 398 * Exports a sync object created with drm_syncobj_create() as a file descriptor. 399 * 400 * Returns 0 on success or a negative error value on failure. 401 */ 402 int drm_syncobj_get_fd(struct drm_syncobj *syncobj, int *p_fd) 403 { 404 struct file *file; 405 int fd; 406 407 fd = get_unused_fd_flags(O_CLOEXEC); 408 if (fd < 0) 409 return fd; 410 411 file = anon_inode_getfile("syncobj_file", 412 &drm_syncobj_file_fops, 413 syncobj, 0); 414 if (IS_ERR(file)) { 415 put_unused_fd(fd); 416 return PTR_ERR(file); 417 } 418 419 drm_syncobj_get(syncobj); 420 fd_install(fd, file); 421 422 *p_fd = fd; 423 return 0; 424 } 425 EXPORT_SYMBOL(drm_syncobj_get_fd); 426 427 static int drm_syncobj_handle_to_fd(struct drm_file *file_private, 428 u32 handle, int *p_fd) 429 { 430 struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); 431 int ret; 432 433 if (!syncobj) 434 return -EINVAL; 435 436 ret = drm_syncobj_get_fd(syncobj, p_fd); 437 drm_syncobj_put(syncobj); 438 return ret; 439 } 440 441 static int drm_syncobj_fd_to_handle(struct drm_file *file_private, 442 int fd, u32 *handle) 443 { 444 struct drm_syncobj *syncobj; 445 struct file *file; 446 int ret; 447 448 file = fget(fd); 449 if (!file) 450 return -EINVAL; 451 452 if (file->f_op != &drm_syncobj_file_fops) { 453 fput(file); 454 return -EINVAL; 455 } 456 457 /* take a reference to put in the idr */ 458 syncobj = file->private_data; 459 drm_syncobj_get(syncobj); 460 461 idr_preload(GFP_KERNEL); 462 spin_lock(&file_private->syncobj_table_lock); 463 ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0, GFP_NOWAIT); 464 spin_unlock(&file_private->syncobj_table_lock); 465 idr_preload_end(); 466 467 if (ret > 0) { 468 *handle = ret; 469 ret = 0; 470 } else 471 drm_syncobj_put(syncobj); 472 473 fput(file); 474 return ret; 475 } 476 477 static int drm_syncobj_import_sync_file_fence(struct drm_file *file_private, 478 int fd, int handle) 479 { 480 struct dma_fence *fence = sync_file_get_fence(fd); 481 struct drm_syncobj *syncobj; 482 483 if (!fence) 484 return -EINVAL; 485 486 syncobj = drm_syncobj_find(file_private, handle); 487 if (!syncobj) { 488 dma_fence_put(fence); 489 return -ENOENT; 490 } 491 492 drm_syncobj_replace_fence(syncobj, 0, fence); 493 dma_fence_put(fence); 494 drm_syncobj_put(syncobj); 495 return 0; 496 } 497 498 static int drm_syncobj_export_sync_file(struct drm_file *file_private, 499 int handle, int *p_fd) 500 { 501 int ret; 502 struct dma_fence *fence; 503 struct sync_file *sync_file; 504 int fd = get_unused_fd_flags(O_CLOEXEC); 505 506 if (fd < 0) 507 return fd; 508 509 ret = drm_syncobj_find_fence(file_private, handle, 0, &fence); 510 if (ret) 511 goto err_put_fd; 512 513 sync_file = sync_file_create(fence); 514 515 dma_fence_put(fence); 516 517 if (!sync_file) { 518 ret = -EINVAL; 519 goto err_put_fd; 520 } 521 522 fd_install(fd, sync_file->file); 523 524 *p_fd = fd; 525 return 0; 526 err_put_fd: 527 put_unused_fd(fd); 528 return ret; 529 } 530 /** 531 * drm_syncobj_open - initalizes syncobj file-private structures at devnode open time 532 * @file_private: drm file-private structure to set up 533 * 534 * Called at device open time, sets up the structure for handling refcounting 535 * of sync objects. 536 */ 537 void 538 drm_syncobj_open(struct drm_file *file_private) 539 { 540 idr_init_base(&file_private->syncobj_idr, 1); 541 spin_lock_init(&file_private->syncobj_table_lock); 542 } 543 544 static int 545 drm_syncobj_release_handle(int id, void *ptr, void *data) 546 { 547 struct drm_syncobj *syncobj = ptr; 548 549 drm_syncobj_put(syncobj); 550 return 0; 551 } 552 553 /** 554 * drm_syncobj_release - release file-private sync object resources 555 * @file_private: drm file-private structure to clean up 556 * 557 * Called at close time when the filp is going away. 558 * 559 * Releases any remaining references on objects by this filp. 560 */ 561 void 562 drm_syncobj_release(struct drm_file *file_private) 563 { 564 idr_for_each(&file_private->syncobj_idr, 565 &drm_syncobj_release_handle, file_private); 566 idr_destroy(&file_private->syncobj_idr); 567 } 568 569 int 570 drm_syncobj_create_ioctl(struct drm_device *dev, void *data, 571 struct drm_file *file_private) 572 { 573 struct drm_syncobj_create *args = data; 574 575 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 576 return -ENODEV; 577 578 /* no valid flags yet */ 579 if (args->flags & ~DRM_SYNCOBJ_CREATE_SIGNALED) 580 return -EINVAL; 581 582 return drm_syncobj_create_as_handle(file_private, 583 &args->handle, args->flags); 584 } 585 586 int 587 drm_syncobj_destroy_ioctl(struct drm_device *dev, void *data, 588 struct drm_file *file_private) 589 { 590 struct drm_syncobj_destroy *args = data; 591 592 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 593 return -ENODEV; 594 595 /* make sure padding is empty */ 596 if (args->pad) 597 return -EINVAL; 598 return drm_syncobj_destroy(file_private, args->handle); 599 } 600 601 int 602 drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data, 603 struct drm_file *file_private) 604 { 605 struct drm_syncobj_handle *args = data; 606 607 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 608 return -ENODEV; 609 610 if (args->pad) 611 return -EINVAL; 612 613 if (args->flags != 0 && 614 args->flags != DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) 615 return -EINVAL; 616 617 if (args->flags & DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE) 618 return drm_syncobj_export_sync_file(file_private, args->handle, 619 &args->fd); 620 621 return drm_syncobj_handle_to_fd(file_private, args->handle, 622 &args->fd); 623 } 624 625 int 626 drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, 627 struct drm_file *file_private) 628 { 629 struct drm_syncobj_handle *args = data; 630 631 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 632 return -ENODEV; 633 634 if (args->pad) 635 return -EINVAL; 636 637 if (args->flags != 0 && 638 args->flags != DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) 639 return -EINVAL; 640 641 if (args->flags & DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE) 642 return drm_syncobj_import_sync_file_fence(file_private, 643 args->fd, 644 args->handle); 645 646 return drm_syncobj_fd_to_handle(file_private, args->fd, 647 &args->handle); 648 } 649 650 struct syncobj_wait_entry { 651 struct task_struct *task; 652 struct dma_fence *fence; 653 struct dma_fence_cb fence_cb; 654 struct drm_syncobj_cb syncobj_cb; 655 }; 656 657 static void syncobj_wait_fence_func(struct dma_fence *fence, 658 struct dma_fence_cb *cb) 659 { 660 struct syncobj_wait_entry *wait = 661 container_of(cb, struct syncobj_wait_entry, fence_cb); 662 663 wake_up_process(wait->task); 664 } 665 666 static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, 667 struct drm_syncobj_cb *cb) 668 { 669 struct syncobj_wait_entry *wait = 670 container_of(cb, struct syncobj_wait_entry, syncobj_cb); 671 672 /* This happens inside the syncobj lock */ 673 wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, 674 lockdep_is_held(&syncobj->lock))); 675 wake_up_process(wait->task); 676 } 677 678 static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, 679 uint32_t count, 680 uint32_t flags, 681 signed long timeout, 682 uint32_t *idx) 683 { 684 struct syncobj_wait_entry *entries; 685 struct dma_fence *fence; 686 signed long ret; 687 uint32_t signaled_count, i; 688 689 entries = kcalloc(count, sizeof(*entries), GFP_KERNEL); 690 if (!entries) 691 return -ENOMEM; 692 693 /* Walk the list of sync objects and initialize entries. We do 694 * this up-front so that we can properly return -EINVAL if there is 695 * a syncobj with a missing fence and then never have the chance of 696 * returning -EINVAL again. 697 */ 698 signaled_count = 0; 699 for (i = 0; i < count; ++i) { 700 entries[i].task = current; 701 entries[i].fence = drm_syncobj_fence_get(syncobjs[i]); 702 if (!entries[i].fence) { 703 if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { 704 continue; 705 } else { 706 ret = -EINVAL; 707 goto cleanup_entries; 708 } 709 } 710 711 if (dma_fence_is_signaled(entries[i].fence)) { 712 if (signaled_count == 0 && idx) 713 *idx = i; 714 signaled_count++; 715 } 716 } 717 718 /* Initialize ret to the max of timeout and 1. That way, the 719 * default return value indicates a successful wait and not a 720 * timeout. 721 */ 722 ret = max_t(signed long, timeout, 1); 723 724 if (signaled_count == count || 725 (signaled_count > 0 && 726 !(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL))) 727 goto cleanup_entries; 728 729 /* There's a very annoying laxness in the dma_fence API here, in 730 * that backends are not required to automatically report when a 731 * fence is signaled prior to fence->ops->enable_signaling() being 732 * called. So here if we fail to match signaled_count, we need to 733 * fallthough and try a 0 timeout wait! 734 */ 735 736 if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { 737 for (i = 0; i < count; ++i) { 738 drm_syncobj_fence_get_or_add_callback(syncobjs[i], 739 &entries[i].fence, 740 &entries[i].syncobj_cb, 741 syncobj_wait_syncobj_func); 742 } 743 } 744 745 do { 746 set_current_state(TASK_INTERRUPTIBLE); 747 748 signaled_count = 0; 749 for (i = 0; i < count; ++i) { 750 fence = entries[i].fence; 751 if (!fence) 752 continue; 753 754 if (dma_fence_is_signaled(fence) || 755 (!entries[i].fence_cb.func && 756 dma_fence_add_callback(fence, 757 &entries[i].fence_cb, 758 syncobj_wait_fence_func))) { 759 /* The fence has been signaled */ 760 if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL) { 761 signaled_count++; 762 } else { 763 if (idx) 764 *idx = i; 765 goto done_waiting; 766 } 767 } 768 } 769 770 if (signaled_count == count) 771 goto done_waiting; 772 773 if (timeout == 0) { 774 /* If we are doing a 0 timeout wait and we got 775 * here, then we just timed out. 776 */ 777 ret = 0; 778 goto done_waiting; 779 } 780 781 ret = schedule_timeout(ret); 782 783 if (ret > 0 && signal_pending(current)) 784 ret = -ERESTARTSYS; 785 } while (ret > 0); 786 787 done_waiting: 788 __set_current_state(TASK_RUNNING); 789 790 cleanup_entries: 791 for (i = 0; i < count; ++i) { 792 if (entries[i].syncobj_cb.func) 793 drm_syncobj_remove_callback(syncobjs[i], 794 &entries[i].syncobj_cb); 795 if (entries[i].fence_cb.func) 796 dma_fence_remove_callback(entries[i].fence, 797 &entries[i].fence_cb); 798 dma_fence_put(entries[i].fence); 799 } 800 kfree(entries); 801 802 return ret; 803 } 804 805 /** 806 * drm_timeout_abs_to_jiffies - calculate jiffies timeout from absolute value 807 * 808 * @timeout_nsec: timeout nsec component in ns, 0 for poll 809 * 810 * Calculate the timeout in jiffies from an absolute time in sec/nsec. 811 */ 812 static signed long drm_timeout_abs_to_jiffies(int64_t timeout_nsec) 813 { 814 ktime_t abs_timeout, now; 815 u64 timeout_ns, timeout_jiffies64; 816 817 /* make 0 timeout means poll - absolute 0 doesn't seem valid */ 818 if (timeout_nsec == 0) 819 return 0; 820 821 abs_timeout = ns_to_ktime(timeout_nsec); 822 now = ktime_get(); 823 824 if (!ktime_after(abs_timeout, now)) 825 return 0; 826 827 timeout_ns = ktime_to_ns(ktime_sub(abs_timeout, now)); 828 829 timeout_jiffies64 = nsecs_to_jiffies64(timeout_ns); 830 /* clamp timeout to avoid infinite timeout */ 831 if (timeout_jiffies64 >= MAX_SCHEDULE_TIMEOUT - 1) 832 return MAX_SCHEDULE_TIMEOUT - 1; 833 834 return timeout_jiffies64 + 1; 835 } 836 837 static int drm_syncobj_array_wait(struct drm_device *dev, 838 struct drm_file *file_private, 839 struct drm_syncobj_wait *wait, 840 struct drm_syncobj **syncobjs) 841 { 842 signed long timeout = drm_timeout_abs_to_jiffies(wait->timeout_nsec); 843 signed long ret = 0; 844 uint32_t first = ~0; 845 846 ret = drm_syncobj_array_wait_timeout(syncobjs, 847 wait->count_handles, 848 wait->flags, 849 timeout, &first); 850 if (ret < 0) 851 return ret; 852 853 wait->first_signaled = first; 854 if (ret == 0) 855 return -ETIME; 856 return 0; 857 } 858 859 static int drm_syncobj_array_find(struct drm_file *file_private, 860 void __user *user_handles, 861 uint32_t count_handles, 862 struct drm_syncobj ***syncobjs_out) 863 { 864 uint32_t i, *handles; 865 struct drm_syncobj **syncobjs; 866 int ret; 867 868 handles = kmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL); 869 if (handles == NULL) 870 return -ENOMEM; 871 872 if (copy_from_user(handles, user_handles, 873 sizeof(uint32_t) * count_handles)) { 874 ret = -EFAULT; 875 goto err_free_handles; 876 } 877 878 syncobjs = kmalloc_array(count_handles, sizeof(*syncobjs), GFP_KERNEL); 879 if (syncobjs == NULL) { 880 ret = -ENOMEM; 881 goto err_free_handles; 882 } 883 884 for (i = 0; i < count_handles; i++) { 885 syncobjs[i] = drm_syncobj_find(file_private, handles[i]); 886 if (!syncobjs[i]) { 887 ret = -ENOENT; 888 goto err_put_syncobjs; 889 } 890 } 891 892 kfree(handles); 893 *syncobjs_out = syncobjs; 894 return 0; 895 896 err_put_syncobjs: 897 while (i-- > 0) 898 drm_syncobj_put(syncobjs[i]); 899 kfree(syncobjs); 900 err_free_handles: 901 kfree(handles); 902 903 return ret; 904 } 905 906 static void drm_syncobj_array_free(struct drm_syncobj **syncobjs, 907 uint32_t count) 908 { 909 uint32_t i; 910 for (i = 0; i < count; i++) 911 drm_syncobj_put(syncobjs[i]); 912 kfree(syncobjs); 913 } 914 915 int 916 drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, 917 struct drm_file *file_private) 918 { 919 struct drm_syncobj_wait *args = data; 920 struct drm_syncobj **syncobjs; 921 int ret = 0; 922 923 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 924 return -ENODEV; 925 926 if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL | 927 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT)) 928 return -EINVAL; 929 930 if (args->count_handles == 0) 931 return -EINVAL; 932 933 ret = drm_syncobj_array_find(file_private, 934 u64_to_user_ptr(args->handles), 935 args->count_handles, 936 &syncobjs); 937 if (ret < 0) 938 return ret; 939 940 ret = drm_syncobj_array_wait(dev, file_private, 941 args, syncobjs); 942 943 drm_syncobj_array_free(syncobjs, args->count_handles); 944 945 return ret; 946 } 947 948 int 949 drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, 950 struct drm_file *file_private) 951 { 952 struct drm_syncobj_array *args = data; 953 struct drm_syncobj **syncobjs; 954 uint32_t i; 955 int ret; 956 957 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 958 return -ENODEV; 959 960 if (args->pad != 0) 961 return -EINVAL; 962 963 if (args->count_handles == 0) 964 return -EINVAL; 965 966 ret = drm_syncobj_array_find(file_private, 967 u64_to_user_ptr(args->handles), 968 args->count_handles, 969 &syncobjs); 970 if (ret < 0) 971 return ret; 972 973 for (i = 0; i < args->count_handles; i++) 974 drm_syncobj_replace_fence(syncobjs[i], 0, NULL); 975 976 drm_syncobj_array_free(syncobjs, args->count_handles); 977 978 return 0; 979 } 980 981 int 982 drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, 983 struct drm_file *file_private) 984 { 985 struct drm_syncobj_array *args = data; 986 struct drm_syncobj **syncobjs; 987 uint32_t i; 988 int ret; 989 990 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 991 return -ENODEV; 992 993 if (args->pad != 0) 994 return -EINVAL; 995 996 if (args->count_handles == 0) 997 return -EINVAL; 998 999 ret = drm_syncobj_array_find(file_private, 1000 u64_to_user_ptr(args->handles), 1001 args->count_handles, 1002 &syncobjs); 1003 if (ret < 0) 1004 return ret; 1005 1006 for (i = 0; i < args->count_handles; i++) { 1007 ret = drm_syncobj_assign_null_handle(syncobjs[i]); 1008 if (ret < 0) 1009 break; 1010 } 1011 1012 drm_syncobj_array_free(syncobjs, args->count_handles); 1013 1014 return ret; 1015 } 1016