1f6ffbd4fSLucas Stach // SPDX-License-Identifier: GPL-2.0 2a8c21a54SThe etnaviv authors /* 3f6ffbd4fSLucas Stach * Copyright (C) 2014-2018 Etnaviv Project 4a8c21a54SThe etnaviv authors */ 5a8c21a54SThe etnaviv authors 66eae41feSSam Ravnborg #include <drm/drm_prime.h> 7a8c21a54SThe etnaviv authors #include <linux/dma-buf.h> 86eae41feSSam Ravnborg 9a8c21a54SThe etnaviv authors #include "etnaviv_drv.h" 10a8c21a54SThe etnaviv authors #include "etnaviv_gem.h" 11a8c21a54SThe etnaviv authors 12d6a8743dSLucas Stach static struct lock_class_key etnaviv_prime_lock_class; 13a8c21a54SThe etnaviv authors 14a8c21a54SThe etnaviv authors struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj) 15a8c21a54SThe etnaviv authors { 16a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 175f4a4a73SLucas Stach int npages = obj->size >> PAGE_SHIFT; 18a8c21a54SThe etnaviv authors 195f4a4a73SLucas Stach if (WARN_ON(!etnaviv_obj->pages)) /* should have already pinned! */ 209e053523SDan Carpenter return ERR_PTR(-EINVAL); 21a8c21a54SThe etnaviv authors 225f4a4a73SLucas Stach return drm_prime_pages_to_sg(etnaviv_obj->pages, npages); 23a8c21a54SThe etnaviv authors } 24a8c21a54SThe etnaviv authors 25a8c21a54SThe etnaviv authors void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj) 26a8c21a54SThe etnaviv authors { 27ce3088fdSLucas Stach return etnaviv_gem_vmap(obj); 28a8c21a54SThe etnaviv authors } 29a8c21a54SThe etnaviv authors 30a8c21a54SThe etnaviv authors void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) 31a8c21a54SThe etnaviv authors { 32a8c21a54SThe etnaviv authors /* TODO msm_gem_vunmap() */ 33a8c21a54SThe etnaviv authors } 34a8c21a54SThe etnaviv authors 355688e57eSLucas Stach int etnaviv_gem_prime_mmap(struct drm_gem_object *obj, 365688e57eSLucas Stach struct vm_area_struct *vma) 375688e57eSLucas Stach { 385688e57eSLucas Stach struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 395688e57eSLucas Stach int ret; 405688e57eSLucas Stach 415688e57eSLucas Stach ret = drm_gem_mmap_obj(obj, obj->size, vma); 425688e57eSLucas Stach if (ret < 0) 435688e57eSLucas Stach return ret; 445688e57eSLucas Stach 455688e57eSLucas Stach return etnaviv_obj->ops->mmap(etnaviv_obj, vma); 465688e57eSLucas Stach } 475688e57eSLucas Stach 48a8c21a54SThe etnaviv authors int etnaviv_gem_prime_pin(struct drm_gem_object *obj) 49a8c21a54SThe etnaviv authors { 50a8c21a54SThe etnaviv authors if (!obj->import_attach) { 51a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 52a8c21a54SThe etnaviv authors 53a8c21a54SThe etnaviv authors mutex_lock(&etnaviv_obj->lock); 54a8c21a54SThe etnaviv authors etnaviv_gem_get_pages(etnaviv_obj); 55a8c21a54SThe etnaviv authors mutex_unlock(&etnaviv_obj->lock); 56a8c21a54SThe etnaviv authors } 57a8c21a54SThe etnaviv authors return 0; 58a8c21a54SThe etnaviv authors } 59a8c21a54SThe etnaviv authors 60a8c21a54SThe etnaviv authors void etnaviv_gem_prime_unpin(struct drm_gem_object *obj) 61a8c21a54SThe etnaviv authors { 62a8c21a54SThe etnaviv authors if (!obj->import_attach) { 63a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 64a8c21a54SThe etnaviv authors 65a8c21a54SThe etnaviv authors mutex_lock(&etnaviv_obj->lock); 66a8c21a54SThe etnaviv authors etnaviv_gem_put_pages(to_etnaviv_bo(obj)); 67a8c21a54SThe etnaviv authors mutex_unlock(&etnaviv_obj->lock); 68a8c21a54SThe etnaviv authors } 69a8c21a54SThe etnaviv authors } 70a8c21a54SThe etnaviv authors 71a8c21a54SThe etnaviv authors static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) 72a8c21a54SThe etnaviv authors { 73a8c21a54SThe etnaviv authors if (etnaviv_obj->vaddr) 74a8c21a54SThe etnaviv authors dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf, 75a8c21a54SThe etnaviv authors etnaviv_obj->vaddr); 76a8c21a54SThe etnaviv authors 77a8c21a54SThe etnaviv authors /* Don't drop the pages for imported dmabuf, as they are not 78a8c21a54SThe etnaviv authors * ours, just free the array we allocated: 79a8c21a54SThe etnaviv authors */ 80a8c21a54SThe etnaviv authors if (etnaviv_obj->pages) 812098105eSMichal Hocko kvfree(etnaviv_obj->pages); 82a8c21a54SThe etnaviv authors 83a8c21a54SThe etnaviv authors drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt); 84a8c21a54SThe etnaviv authors } 85a8c21a54SThe etnaviv authors 86a0a5ab3eSLucas Stach static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj) 87a0a5ab3eSLucas Stach { 88a0a5ab3eSLucas Stach lockdep_assert_held(&etnaviv_obj->lock); 89a0a5ab3eSLucas Stach 90a0a5ab3eSLucas Stach return dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf); 91a0a5ab3eSLucas Stach } 92a0a5ab3eSLucas Stach 93a10e2bdeSLucas Stach static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj, 94a10e2bdeSLucas Stach struct vm_area_struct *vma) 95a10e2bdeSLucas Stach { 96a10e2bdeSLucas Stach return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0); 97a10e2bdeSLucas Stach } 98a10e2bdeSLucas Stach 99a8c21a54SThe etnaviv authors static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = { 100a8c21a54SThe etnaviv authors /* .get_pages should never be called */ 101a8c21a54SThe etnaviv authors .release = etnaviv_gem_prime_release, 102a0a5ab3eSLucas Stach .vmap = etnaviv_gem_prime_vmap_impl, 103a10e2bdeSLucas Stach .mmap = etnaviv_gem_prime_mmap_obj, 104a8c21a54SThe etnaviv authors }; 105a8c21a54SThe etnaviv authors 106a8c21a54SThe etnaviv authors struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev, 107a8c21a54SThe etnaviv authors struct dma_buf_attachment *attach, struct sg_table *sgt) 108a8c21a54SThe etnaviv authors { 109a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj; 110a8c21a54SThe etnaviv authors size_t size = PAGE_ALIGN(attach->dmabuf->size); 111a8c21a54SThe etnaviv authors int ret, npages; 112a8c21a54SThe etnaviv authors 113a8c21a54SThe etnaviv authors ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC, 114a8c21a54SThe etnaviv authors attach->dmabuf->resv, 115a8c21a54SThe etnaviv authors &etnaviv_gem_prime_ops, &etnaviv_obj); 116a8c21a54SThe etnaviv authors if (ret < 0) 117a8c21a54SThe etnaviv authors return ERR_PTR(ret); 118a8c21a54SThe etnaviv authors 119d6a8743dSLucas Stach lockdep_set_class(&etnaviv_obj->lock, &etnaviv_prime_lock_class); 120d6a8743dSLucas Stach 121a8c21a54SThe etnaviv authors npages = size / PAGE_SIZE; 122a8c21a54SThe etnaviv authors 123a8c21a54SThe etnaviv authors etnaviv_obj->sgt = sgt; 1242098105eSMichal Hocko etnaviv_obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); 125a8c21a54SThe etnaviv authors if (!etnaviv_obj->pages) { 126a8c21a54SThe etnaviv authors ret = -ENOMEM; 127a8c21a54SThe etnaviv authors goto fail; 128a8c21a54SThe etnaviv authors } 129a8c21a54SThe etnaviv authors 130a8c21a54SThe etnaviv authors ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages, 131a8c21a54SThe etnaviv authors NULL, npages); 132a8c21a54SThe etnaviv authors if (ret) 133a8c21a54SThe etnaviv authors goto fail; 134a8c21a54SThe etnaviv authors 13554f09288SLucas Stach etnaviv_gem_obj_add(dev, &etnaviv_obj->base); 136a8c21a54SThe etnaviv authors 137a8c21a54SThe etnaviv authors return &etnaviv_obj->base; 138a8c21a54SThe etnaviv authors 139a8c21a54SThe etnaviv authors fail: 14023d1dd03SCihangir Akturk drm_gem_object_put_unlocked(&etnaviv_obj->base); 141a8c21a54SThe etnaviv authors 142a8c21a54SThe etnaviv authors return ERR_PTR(ret); 143a8c21a54SThe etnaviv authors } 144