Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/shmem-helpers: Simplify dma-buf importing

- Ditch the ->pages array
- Make it a private gem bo, which means no shmem object, which means
fireworks if anyone calls drm_gem_object_get_pages. But we've just
made sure that's all covered.

v2: Rebase

v3: I forgot to remove the page_count mangling from the free path too.
Noticed by Boris while testing.

Cc: Boris Brezillon <boris.brezillon@collabora.com>
Tested-by: Boris Brezillon <boris.brezillon@collabora.com>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200529140542.2103713-1-daniel.vetter@ffwll.ch

+23 -37
+23 -37
drivers/gpu/drm/drm_gem_shmem_helper.c
··· 35 35 .mmap = drm_gem_shmem_mmap, 36 36 }; 37 37 38 - /** 39 - * drm_gem_shmem_create - Allocate an object with the given size 40 - * @dev: DRM device 41 - * @size: Size of the object to allocate 42 - * 43 - * This function creates a shmem GEM object. 44 - * 45 - * Returns: 46 - * A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative 47 - * error code on failure. 48 - */ 49 - struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size) 38 + static struct drm_gem_shmem_object * 39 + __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private) 50 40 { 51 41 struct drm_gem_shmem_object *shmem; 52 42 struct drm_gem_object *obj; 53 - int ret; 43 + int ret = 0; 54 44 55 45 size = PAGE_ALIGN(size); 56 46 ··· 54 64 if (!obj->funcs) 55 65 obj->funcs = &drm_gem_shmem_funcs; 56 66 57 - ret = drm_gem_object_init(dev, obj, size); 67 + if (private) 68 + drm_gem_private_object_init(dev, obj, size); 69 + else 70 + ret = drm_gem_object_init(dev, obj, size); 58 71 if (ret) 59 72 goto err_free; 60 73 ··· 89 96 90 97 return ERR_PTR(ret); 91 98 } 99 + /** 100 + * drm_gem_shmem_create - Allocate an object with the given size 101 + * @dev: DRM device 102 + * @size: Size of the object to allocate 103 + * 104 + * This function creates a shmem GEM object. 105 + * 106 + * Returns: 107 + * A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative 108 + * error code on failure. 109 + */ 110 + struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size) 111 + { 112 + return __drm_gem_shmem_create(dev, size, false); 113 + } 92 114 EXPORT_SYMBOL_GPL(drm_gem_shmem_create); 93 115 94 116 /** ··· 121 113 WARN_ON(shmem->vmap_use_count); 122 114 123 115 if (obj->import_attach) { 124 - shmem->pages_use_count--; 125 116 drm_prime_gem_destroy(obj, shmem->sgt); 126 - kvfree(shmem->pages); 127 117 } else { 128 118 if (shmem->sgt) { 129 119 dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl, ··· 377 371 struct drm_gem_shmem_object *shmem; 378 372 int ret; 379 373 380 - shmem = drm_gem_shmem_create(dev, size); 374 + shmem = __drm_gem_shmem_create(dev, size, true); 381 375 if (IS_ERR(shmem)) 382 376 return shmem; 383 377 ··· 701 695 struct sg_table *sgt) 702 696 { 703 697 size_t size = PAGE_ALIGN(attach->dmabuf->size); 704 - size_t npages = size >> PAGE_SHIFT; 705 698 struct drm_gem_shmem_object *shmem; 706 - int ret; 707 699 708 700 shmem = drm_gem_shmem_create(dev, size); 709 701 if (IS_ERR(shmem)) 710 702 return ERR_CAST(shmem); 711 703 712 - shmem->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); 713 - if (!shmem->pages) { 714 - ret = -ENOMEM; 715 - goto err_free_gem; 716 - } 717 - 718 - ret = drm_prime_sg_to_page_addr_arrays(sgt, shmem->pages, NULL, npages); 719 - if (ret < 0) 720 - goto err_free_array; 721 - 722 704 shmem->sgt = sgt; 723 - shmem->pages_use_count = 1; /* Permanently pinned from our point of view */ 724 705 725 706 DRM_DEBUG_PRIME("size = %zu\n", size); 726 707 727 708 return &shmem->base; 728 - 729 - err_free_array: 730 - kvfree(shmem->pages); 731 - err_free_gem: 732 - drm_gem_object_put(&shmem->base); 733 - 734 - return ERR_PTR(ret); 735 709 } 736 710 EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_sg_table);