1 /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 /************************************************************************** 3 * 4 * Copyright (c) 2009-2013 VMware, Inc., Palo Alto, CA., USA 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25 * USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 /* 29 * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> 30 * 31 * While no substantial code is shared, the prime code is inspired by 32 * drm_prime.c, with 33 * Authors: 34 * Dave Airlie <airlied@redhat.com> 35 * Rob Clark <rob.clark@linaro.org> 36 */ 37 /** @file ttm_ref_object.c 38 * 39 * Base- and reference object implementation for the various 40 * ttm objects. Implements reference counting, minimal security checks 41 * and release on file close. 42 */ 43 44 45 /** 46 * struct ttm_object_file 47 * 48 * @tdev: Pointer to the ttm_object_device. 49 * 50 * @lock: Lock that protects the ref_list list and the 51 * ref_hash hash tables. 52 * 53 * @ref_list: List of ttm_ref_objects to be destroyed at 54 * file release. 55 * 56 * @ref_hash: Hash tables of ref objects, one per ttm_ref_type, 57 * for fast lookup of ref objects given a base object. 58 */ 59 60 #define pr_fmt(fmt) "[TTM] " fmt 61 62 #include <drm/ttm/ttm_object.h> 63 #include <drm/ttm/ttm_module.h> 64 #include <linux/list.h> 65 #include <linux/spinlock.h> 66 #include <linux/slab.h> 67 #include <linux/module.h> 68 #include <linux/atomic.h> 69 70 struct ttm_object_file { 71 struct ttm_object_device *tdev; 72 struct spinlock lock; 73 struct list_head ref_list; 74 struct drm_open_hash ref_hash[TTM_REF_NUM]; 75 struct kref refcount; 76 }; 77 78 /** 79 * struct ttm_object_device 80 * 81 * @object_lock: lock that protects the object_hash hash table. 82 * 83 * @object_hash: hash table for fast lookup of object global names. 84 * 85 * @object_count: Per device object count. 86 * 87 * This is the per-device data structure needed for ttm object management. 88 */ 89 90 struct ttm_object_device { 91 struct spinlock object_lock; 92 struct drm_open_hash object_hash; 93 atomic_t object_count; 94 struct ttm_mem_global *mem_glob; 95 struct dma_buf_ops ops; 96 void (*dmabuf_release)(struct dma_buf *dma_buf); 97 size_t dma_buf_size; 98 }; 99 100 /** 101 * struct ttm_ref_object 102 * 103 * @hash: Hash entry for the per-file object reference hash. 104 * 105 * @head: List entry for the per-file list of ref-objects. 106 * 107 * @kref: Ref count. 108 * 109 * @obj: Base object this ref object is referencing. 110 * 111 * @ref_type: Type of ref object. 112 * 113 * This is similar to an idr object, but it also has a hash table entry 114 * that allows lookup with a pointer to the referenced object as a key. In 115 * that way, one can easily detect whether a base object is referenced by 116 * a particular ttm_object_file. It also carries a ref count to avoid creating 117 * multiple ref objects if a ttm_object_file references the same base 118 * object more than once. 119 */ 120 121 struct ttm_ref_object { 122 struct rcu_head rcu_head; 123 struct drm_hash_item hash; 124 struct list_head head; 125 struct kref kref; 126 enum ttm_ref_type ref_type; 127 struct ttm_base_object *obj; 128 struct ttm_object_file *tfile; 129 }; 130 131 static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf); 132 133 static inline struct ttm_object_file * 134 ttm_object_file_ref(struct ttm_object_file *tfile) 135 { 136 kref_get(&tfile->refcount); 137 return tfile; 138 } 139 140 static void ttm_object_file_destroy(struct kref *kref) 141 { 142 struct ttm_object_file *tfile = 143 container_of(kref, struct ttm_object_file, refcount); 144 145 kfree(tfile); 146 } 147 148 149 static inline void ttm_object_file_unref(struct ttm_object_file **p_tfile) 150 { 151 struct ttm_object_file *tfile = *p_tfile; 152 153 *p_tfile = NULL; 154 kref_put(&tfile->refcount, ttm_object_file_destroy); 155 } 156 157 158 int ttm_base_object_init(struct ttm_object_file *tfile, 159 struct ttm_base_object *base, 160 bool shareable, 161 enum ttm_object_type object_type, 162 void (*refcount_release) (struct ttm_base_object **), 163 void (*ref_obj_release) (struct ttm_base_object *, 164 enum ttm_ref_type ref_type)) 165 { 166 struct ttm_object_device *tdev = tfile->tdev; 167 int ret; 168 169 base->shareable = shareable; 170 base->tfile = ttm_object_file_ref(tfile); 171 base->refcount_release = refcount_release; 172 base->ref_obj_release = ref_obj_release; 173 base->object_type = object_type; 174 kref_init(&base->refcount); 175 spin_lock(&tdev->object_lock); 176 ret = drm_ht_just_insert_please_rcu(&tdev->object_hash, 177 &base->hash, 178 (unsigned long)base, 31, 0, 0); 179 spin_unlock(&tdev->object_lock); 180 if (unlikely(ret != 0)) 181 goto out_err0; 182 183 ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false); 184 if (unlikely(ret != 0)) 185 goto out_err1; 186 187 ttm_base_object_unref(&base); 188 189 return 0; 190 out_err1: 191 spin_lock(&tdev->object_lock); 192 (void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash); 193 spin_unlock(&tdev->object_lock); 194 out_err0: 195 return ret; 196 } 197 EXPORT_SYMBOL(ttm_base_object_init); 198 199 static void ttm_release_base(struct kref *kref) 200 { 201 struct ttm_base_object *base = 202 container_of(kref, struct ttm_base_object, refcount); 203 struct ttm_object_device *tdev = base->tfile->tdev; 204 205 spin_lock(&tdev->object_lock); 206 (void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash); 207 spin_unlock(&tdev->object_lock); 208 209 /* 210 * Note: We don't use synchronize_rcu() here because it's far 211 * too slow. It's up to the user to free the object using 212 * call_rcu() or ttm_base_object_kfree(). 213 */ 214 215 ttm_object_file_unref(&base->tfile); 216 if (base->refcount_release) 217 base->refcount_release(&base); 218 } 219 220 void ttm_base_object_unref(struct ttm_base_object **p_base) 221 { 222 struct ttm_base_object *base = *p_base; 223 224 *p_base = NULL; 225 226 kref_put(&base->refcount, ttm_release_base); 227 } 228 EXPORT_SYMBOL(ttm_base_object_unref); 229 230 struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, 231 uint32_t key) 232 { 233 struct ttm_base_object *base = NULL; 234 struct drm_hash_item *hash; 235 struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 236 int ret; 237 238 rcu_read_lock(); 239 ret = drm_ht_find_item_rcu(ht, key, &hash); 240 241 if (likely(ret == 0)) { 242 base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj; 243 if (!kref_get_unless_zero(&base->refcount)) 244 base = NULL; 245 } 246 rcu_read_unlock(); 247 248 return base; 249 } 250 EXPORT_SYMBOL(ttm_base_object_lookup); 251 252 struct ttm_base_object * 253 ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key) 254 { 255 struct ttm_base_object *base = NULL; 256 struct drm_hash_item *hash; 257 struct drm_open_hash *ht = &tdev->object_hash; 258 int ret; 259 260 rcu_read_lock(); 261 ret = drm_ht_find_item_rcu(ht, key, &hash); 262 263 if (likely(ret == 0)) { 264 base = drm_hash_entry(hash, struct ttm_base_object, hash); 265 if (!kref_get_unless_zero(&base->refcount)) 266 base = NULL; 267 } 268 rcu_read_unlock(); 269 270 return base; 271 } 272 EXPORT_SYMBOL(ttm_base_object_lookup_for_ref); 273 274 /** 275 * ttm_ref_object_exists - Check whether a caller has a valid ref object 276 * (has opened) a base object. 277 * 278 * @tfile: Pointer to a struct ttm_object_file identifying the caller. 279 * @base: Pointer to a struct base object. 280 * 281 * Checks wether the caller identified by @tfile has put a valid USAGE 282 * reference object on the base object identified by @base. 283 */ 284 bool ttm_ref_object_exists(struct ttm_object_file *tfile, 285 struct ttm_base_object *base) 286 { 287 struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE]; 288 struct drm_hash_item *hash; 289 struct ttm_ref_object *ref; 290 291 rcu_read_lock(); 292 if (unlikely(drm_ht_find_item_rcu(ht, base->hash.key, &hash) != 0)) 293 goto out_false; 294 295 /* 296 * Verify that the ref object is really pointing to our base object. 297 * Our base object could actually be dead, and the ref object pointing 298 * to another base object with the same handle. 299 */ 300 ref = drm_hash_entry(hash, struct ttm_ref_object, hash); 301 if (unlikely(base != ref->obj)) 302 goto out_false; 303 304 /* 305 * Verify that the ref->obj pointer was actually valid! 306 */ 307 rmb(); 308 if (unlikely(kref_read(&ref->kref) == 0)) 309 goto out_false; 310 311 rcu_read_unlock(); 312 return true; 313 314 out_false: 315 rcu_read_unlock(); 316 return false; 317 } 318 EXPORT_SYMBOL(ttm_ref_object_exists); 319 320 int ttm_ref_object_add(struct ttm_object_file *tfile, 321 struct ttm_base_object *base, 322 enum ttm_ref_type ref_type, bool *existed, 323 bool require_existed) 324 { 325 struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; 326 struct ttm_ref_object *ref; 327 struct drm_hash_item *hash; 328 struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 329 struct ttm_operation_ctx ctx = { 330 .interruptible = false, 331 .no_wait_gpu = false 332 }; 333 int ret = -EINVAL; 334 335 if (base->tfile != tfile && !base->shareable) 336 return -EPERM; 337 338 if (existed != NULL) 339 *existed = true; 340 341 while (ret == -EINVAL) { 342 rcu_read_lock(); 343 ret = drm_ht_find_item_rcu(ht, base->hash.key, &hash); 344 345 if (ret == 0) { 346 ref = drm_hash_entry(hash, struct ttm_ref_object, hash); 347 if (kref_get_unless_zero(&ref->kref)) { 348 rcu_read_unlock(); 349 break; 350 } 351 } 352 353 rcu_read_unlock(); 354 if (require_existed) 355 return -EPERM; 356 357 ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), 358 &ctx); 359 if (unlikely(ret != 0)) 360 return ret; 361 ref = kmalloc(sizeof(*ref), M_DRM, GFP_KERNEL); 362 if (unlikely(ref == NULL)) { 363 ttm_mem_global_free(mem_glob, sizeof(*ref)); 364 return -ENOMEM; 365 } 366 367 ref->hash.key = base->hash.key; 368 ref->obj = base; 369 ref->tfile = tfile; 370 ref->ref_type = ref_type; 371 kref_init(&ref->kref); 372 373 spin_lock(&tfile->lock); 374 ret = drm_ht_insert_item_rcu(ht, &ref->hash); 375 376 if (likely(ret == 0)) { 377 list_add_tail(&ref->head, &tfile->ref_list); 378 kref_get(&base->refcount); 379 spin_unlock(&tfile->lock); 380 if (existed != NULL) 381 *existed = false; 382 break; 383 } 384 385 spin_unlock(&tfile->lock); 386 BUG_ON(ret != -EINVAL); 387 388 ttm_mem_global_free(mem_glob, sizeof(*ref)); 389 kfree(ref); 390 } 391 392 return ret; 393 } 394 EXPORT_SYMBOL(ttm_ref_object_add); 395 396 static void ttm_ref_object_release(struct kref *kref) 397 { 398 struct ttm_ref_object *ref = 399 container_of(kref, struct ttm_ref_object, kref); 400 struct ttm_base_object *base = ref->obj; 401 struct ttm_object_file *tfile = ref->tfile; 402 struct drm_open_hash *ht; 403 struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 404 405 ht = &tfile->ref_hash[ref->ref_type]; 406 (void)drm_ht_remove_item_rcu(ht, &ref->hash); 407 list_del(&ref->head); 408 spin_unlock(&tfile->lock); 409 410 if (ref->ref_type != TTM_REF_USAGE && base->ref_obj_release) 411 base->ref_obj_release(base, ref->ref_type); 412 413 ttm_base_object_unref(&ref->obj); 414 ttm_mem_global_free(mem_glob, sizeof(*ref)); 415 kfree_rcu(ref, rcu_head); 416 spin_lock(&tfile->lock); 417 } 418 419 int ttm_ref_object_base_unref(struct ttm_object_file *tfile, 420 unsigned long key, enum ttm_ref_type ref_type) 421 { 422 struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; 423 struct ttm_ref_object *ref; 424 struct drm_hash_item *hash; 425 int ret; 426 427 spin_lock(&tfile->lock); 428 ret = drm_ht_find_item(ht, key, &hash); 429 if (unlikely(ret != 0)) { 430 spin_unlock(&tfile->lock); 431 return -EINVAL; 432 } 433 ref = drm_hash_entry(hash, struct ttm_ref_object, hash); 434 kref_put(&ref->kref, ttm_ref_object_release); 435 spin_unlock(&tfile->lock); 436 return 0; 437 } 438 EXPORT_SYMBOL(ttm_ref_object_base_unref); 439 440 void ttm_object_file_release(struct ttm_object_file **p_tfile) 441 { 442 struct ttm_ref_object *ref; 443 struct list_head *list; 444 unsigned int i; 445 struct ttm_object_file *tfile = *p_tfile; 446 447 *p_tfile = NULL; 448 spin_lock(&tfile->lock); 449 450 /* 451 * Since we release the lock within the loop, we have to 452 * restart it from the beginning each time. 453 */ 454 455 while (!list_empty(&tfile->ref_list)) { 456 list = tfile->ref_list.next; 457 ref = list_entry(list, struct ttm_ref_object, head); 458 ttm_ref_object_release(&ref->kref); 459 } 460 461 spin_unlock(&tfile->lock); 462 for (i = 0; i < TTM_REF_NUM; ++i) 463 drm_ht_remove(&tfile->ref_hash[i]); 464 465 ttm_object_file_unref(&tfile); 466 } 467 EXPORT_SYMBOL(ttm_object_file_release); 468 469 struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev, 470 unsigned int hash_order) 471 { 472 struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), M_DRM, GFP_KERNEL); 473 unsigned int i; 474 unsigned int j = 0; 475 int ret; 476 477 if (unlikely(tfile == NULL)) 478 return NULL; 479 480 spin_init(&tfile->lock, "ttmofl"); 481 tfile->tdev = tdev; 482 kref_init(&tfile->refcount); 483 INIT_LIST_HEAD(&tfile->ref_list); 484 485 for (i = 0; i < TTM_REF_NUM; ++i) { 486 ret = drm_ht_create(&tfile->ref_hash[i], hash_order); 487 if (ret) { 488 j = i; 489 goto out_err; 490 } 491 } 492 493 return tfile; 494 out_err: 495 for (i = 0; i < j; ++i) 496 drm_ht_remove(&tfile->ref_hash[i]); 497 498 kfree(tfile); 499 500 return NULL; 501 } 502 EXPORT_SYMBOL(ttm_object_file_init); 503 504 struct ttm_object_device * 505 ttm_object_device_init(struct ttm_mem_global *mem_glob, 506 unsigned int hash_order, 507 const struct dma_buf_ops *ops) 508 { 509 struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), M_DRM, GFP_KERNEL); 510 int ret; 511 512 if (unlikely(tdev == NULL)) 513 return NULL; 514 515 tdev->mem_glob = mem_glob; 516 spin_init(&tdev->object_lock, "ttmodol"); 517 atomic_set(&tdev->object_count, 0); 518 ret = drm_ht_create(&tdev->object_hash, hash_order); 519 if (ret != 0) 520 goto out_no_object_hash; 521 522 tdev->ops = *ops; 523 tdev->dmabuf_release = tdev->ops.release; 524 tdev->ops.release = ttm_prime_dmabuf_release; 525 tdev->dma_buf_size = ttm_round_pot(sizeof(struct dma_buf)) + 526 ttm_round_pot(sizeof(struct file)); 527 return tdev; 528 529 out_no_object_hash: 530 kfree(tdev); 531 return NULL; 532 } 533 EXPORT_SYMBOL(ttm_object_device_init); 534 535 void ttm_object_device_release(struct ttm_object_device **p_tdev) 536 { 537 struct ttm_object_device *tdev = *p_tdev; 538 539 *p_tdev = NULL; 540 541 drm_ht_remove(&tdev->object_hash); 542 543 kfree(tdev); 544 } 545 EXPORT_SYMBOL(ttm_object_device_release); 546 547 /** 548 * get_dma_buf_unless_doomed - get a dma_buf reference if possible. 549 * 550 * @dma_buf: Non-refcounted pointer to a struct dma-buf. 551 * 552 * Obtain a file reference from a lookup structure that doesn't refcount 553 * the file, but synchronizes with its release method to make sure it has 554 * not been freed yet. See for example kref_get_unless_zero documentation. 555 * Returns true if refcounting succeeds, false otherwise. 556 * 557 * Nobody really wants this as a public API yet, so let it mature here 558 * for some time... 559 */ 560 static bool __must_check get_dma_buf_unless_doomed(struct dma_buf *dmabuf) 561 { 562 return false; 563 #if 0 564 return atomic_long_inc_not_zero(&dmabuf->file->f_count) != 0L; 565 #endif 566 } 567 568 /** 569 * ttm_prime_refcount_release - refcount release method for a prime object. 570 * 571 * @p_base: Pointer to ttm_base_object pointer. 572 * 573 * This is a wrapper that calls the refcount_release founction of the 574 * underlying object. At the same time it cleans up the prime object. 575 * This function is called when all references to the base object we 576 * derive from are gone. 577 */ 578 static void ttm_prime_refcount_release(struct ttm_base_object **p_base) 579 { 580 struct ttm_base_object *base = *p_base; 581 struct ttm_prime_object *prime; 582 583 *p_base = NULL; 584 prime = container_of(base, struct ttm_prime_object, base); 585 BUG_ON(prime->dma_buf != NULL); 586 mutex_destroy(&prime->mutex); 587 if (prime->refcount_release) 588 prime->refcount_release(&base); 589 } 590 591 /** 592 * ttm_prime_dmabuf_release - Release method for the dma-bufs we export 593 * 594 * @dma_buf: 595 * 596 * This function first calls the dma_buf release method the driver 597 * provides. Then it cleans up our dma_buf pointer used for lookup, 598 * and finally releases the reference the dma_buf has on our base 599 * object. 600 */ 601 static void ttm_prime_dmabuf_release(struct dma_buf *dma_buf) 602 { 603 struct ttm_prime_object *prime = 604 (struct ttm_prime_object *) dma_buf->priv; 605 struct ttm_base_object *base = &prime->base; 606 struct ttm_object_device *tdev = base->tfile->tdev; 607 608 if (tdev->dmabuf_release) 609 tdev->dmabuf_release(dma_buf); 610 mutex_lock(&prime->mutex); 611 if (prime->dma_buf == dma_buf) 612 prime->dma_buf = NULL; 613 mutex_unlock(&prime->mutex); 614 ttm_mem_global_free(tdev->mem_glob, tdev->dma_buf_size); 615 ttm_base_object_unref(&base); 616 } 617 618 /** 619 * ttm_prime_fd_to_handle - Get a base object handle from a prime fd 620 * 621 * @tfile: A struct ttm_object_file identifying the caller. 622 * @fd: The prime / dmabuf fd. 623 * @handle: The returned handle. 624 * 625 * This function returns a handle to an object that previously exported 626 * a dma-buf. Note that we don't handle imports yet, because we simply 627 * have no consumers of that implementation. 628 */ 629 int ttm_prime_fd_to_handle(struct ttm_object_file *tfile, 630 int fd, u32 *handle) 631 { 632 struct ttm_object_device *tdev = tfile->tdev; 633 struct dma_buf *dma_buf; 634 struct ttm_prime_object *prime; 635 struct ttm_base_object *base; 636 int ret; 637 638 dma_buf = dma_buf_get(fd); 639 if (IS_ERR(dma_buf)) 640 return PTR_ERR(dma_buf); 641 642 if (dma_buf->ops != &tdev->ops) 643 return -ENOSYS; 644 645 prime = (struct ttm_prime_object *) dma_buf->priv; 646 base = &prime->base; 647 *handle = base->hash.key; 648 ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false); 649 650 dma_buf_put(dma_buf); 651 652 return ret; 653 } 654 EXPORT_SYMBOL_GPL(ttm_prime_fd_to_handle); 655 656 /** 657 * ttm_prime_handle_to_fd - Return a dma_buf fd from a ttm prime object 658 * 659 * @tfile: Struct ttm_object_file identifying the caller. 660 * @handle: Handle to the object we're exporting from. 661 * @flags: flags for dma-buf creation. We just pass them on. 662 * @prime_fd: The returned file descriptor. 663 * 664 */ 665 int ttm_prime_handle_to_fd(struct ttm_object_file *tfile, 666 uint32_t handle, uint32_t flags, 667 int *prime_fd) 668 { 669 struct ttm_object_device *tdev = tfile->tdev; 670 struct ttm_base_object *base; 671 struct dma_buf *dma_buf; 672 struct ttm_prime_object *prime; 673 int ret; 674 675 base = ttm_base_object_lookup(tfile, handle); 676 if (unlikely(base == NULL || 677 base->object_type != ttm_prime_type)) { 678 ret = -ENOENT; 679 goto out_unref; 680 } 681 682 prime = container_of(base, struct ttm_prime_object, base); 683 if (unlikely(!base->shareable)) { 684 ret = -EPERM; 685 goto out_unref; 686 } 687 688 ret = mutex_lock_interruptible(&prime->mutex); 689 if (unlikely(ret != 0)) { 690 ret = -ERESTARTSYS; 691 goto out_unref; 692 } 693 694 dma_buf = prime->dma_buf; 695 if (!dma_buf || !get_dma_buf_unless_doomed(dma_buf)) { 696 DEFINE_DMA_BUF_EXPORT_INFO(exp_info); 697 struct ttm_operation_ctx ctx = { 698 .interruptible = true, 699 .no_wait_gpu = false 700 }; 701 exp_info.ops = &tdev->ops; 702 exp_info.size = prime->size; 703 exp_info.flags = flags; 704 exp_info.priv = prime; 705 706 /* 707 * Need to create a new dma_buf, with memory accounting. 708 */ 709 ret = ttm_mem_global_alloc(tdev->mem_glob, tdev->dma_buf_size, 710 &ctx); 711 if (unlikely(ret != 0)) { 712 mutex_unlock(&prime->mutex); 713 goto out_unref; 714 } 715 716 dma_buf = dma_buf_export(&exp_info); 717 if (IS_ERR(dma_buf)) { 718 ret = PTR_ERR(dma_buf); 719 ttm_mem_global_free(tdev->mem_glob, 720 tdev->dma_buf_size); 721 mutex_unlock(&prime->mutex); 722 goto out_unref; 723 } 724 725 /* 726 * dma_buf has taken the base object reference 727 */ 728 base = NULL; 729 prime->dma_buf = dma_buf; 730 } 731 mutex_unlock(&prime->mutex); 732 733 ret = dma_buf_fd(dma_buf, flags); 734 if (ret >= 0) { 735 *prime_fd = ret; 736 ret = 0; 737 } else 738 dma_buf_put(dma_buf); 739 740 out_unref: 741 if (base) 742 ttm_base_object_unref(&base); 743 return ret; 744 } 745 EXPORT_SYMBOL_GPL(ttm_prime_handle_to_fd); 746 747 /** 748 * ttm_prime_object_init - Initialize a ttm_prime_object 749 * 750 * @tfile: struct ttm_object_file identifying the caller 751 * @size: The size of the dma_bufs we export. 752 * @prime: The object to be initialized. 753 * @shareable: See ttm_base_object_init 754 * @type: See ttm_base_object_init 755 * @refcount_release: See ttm_base_object_init 756 * @ref_obj_release: See ttm_base_object_init 757 * 758 * Initializes an object which is compatible with the drm_prime model 759 * for data sharing between processes and devices. 760 */ 761 int ttm_prime_object_init(struct ttm_object_file *tfile, size_t size, 762 struct ttm_prime_object *prime, bool shareable, 763 enum ttm_object_type type, 764 void (*refcount_release) (struct ttm_base_object **), 765 void (*ref_obj_release) (struct ttm_base_object *, 766 enum ttm_ref_type ref_type)) 767 { 768 lockinit(&prime->mutex, "ttmpom", 0, LK_CANRECURSE); 769 prime->size = PAGE_ALIGN(size); 770 prime->real_type = type; 771 prime->dma_buf = NULL; 772 prime->refcount_release = refcount_release; 773 return ttm_base_object_init(tfile, &prime->base, shareable, 774 ttm_prime_type, 775 ttm_prime_refcount_release, 776 ref_obj_release); 777 } 778 EXPORT_SYMBOL(ttm_prime_object_init); 779