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 6a8c21a54SThe etnaviv authors #include <linux/dma-buf.h> 7a8c21a54SThe etnaviv authors #include "etnaviv_drv.h" 8a8c21a54SThe etnaviv authors #include "etnaviv_gem.h" 9a8c21a54SThe etnaviv authors 10d6a8743dSLucas Stach static struct lock_class_key etnaviv_prime_lock_class; 11a8c21a54SThe etnaviv authors 12a8c21a54SThe etnaviv authors struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj) 13a8c21a54SThe etnaviv authors { 14a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 155f4a4a73SLucas Stach int npages = obj->size >> PAGE_SHIFT; 16a8c21a54SThe etnaviv authors 175f4a4a73SLucas Stach if (WARN_ON(!etnaviv_obj->pages)) /* should have already pinned! */ 189e053523SDan Carpenter return ERR_PTR(-EINVAL); 19a8c21a54SThe etnaviv authors 205f4a4a73SLucas Stach return drm_prime_pages_to_sg(etnaviv_obj->pages, npages); 21a8c21a54SThe etnaviv authors } 22a8c21a54SThe etnaviv authors 23a8c21a54SThe etnaviv authors void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj) 24a8c21a54SThe etnaviv authors { 25ce3088fdSLucas Stach return etnaviv_gem_vmap(obj); 26a8c21a54SThe etnaviv authors } 27a8c21a54SThe etnaviv authors 28a8c21a54SThe etnaviv authors void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) 29a8c21a54SThe etnaviv authors { 30a8c21a54SThe etnaviv authors /* TODO msm_gem_vunmap() */ 31a8c21a54SThe etnaviv authors } 32a8c21a54SThe etnaviv authors 335688e57eSLucas Stach int etnaviv_gem_prime_mmap(struct drm_gem_object *obj, 345688e57eSLucas Stach struct vm_area_struct *vma) 355688e57eSLucas Stach { 365688e57eSLucas Stach struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 375688e57eSLucas Stach int ret; 385688e57eSLucas Stach 395688e57eSLucas Stach ret = drm_gem_mmap_obj(obj, obj->size, vma); 405688e57eSLucas Stach if (ret < 0) 415688e57eSLucas Stach return ret; 425688e57eSLucas Stach 435688e57eSLucas Stach return etnaviv_obj->ops->mmap(etnaviv_obj, vma); 445688e57eSLucas Stach } 455688e57eSLucas Stach 46a8c21a54SThe etnaviv authors int etnaviv_gem_prime_pin(struct drm_gem_object *obj) 47a8c21a54SThe etnaviv authors { 48a8c21a54SThe etnaviv authors if (!obj->import_attach) { 49a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 50a8c21a54SThe etnaviv authors 51a8c21a54SThe etnaviv authors mutex_lock(&etnaviv_obj->lock); 52a8c21a54SThe etnaviv authors etnaviv_gem_get_pages(etnaviv_obj); 53a8c21a54SThe etnaviv authors mutex_unlock(&etnaviv_obj->lock); 54a8c21a54SThe etnaviv authors } 55a8c21a54SThe etnaviv authors return 0; 56a8c21a54SThe etnaviv authors } 57a8c21a54SThe etnaviv authors 58a8c21a54SThe etnaviv authors void etnaviv_gem_prime_unpin(struct drm_gem_object *obj) 59a8c21a54SThe etnaviv authors { 60a8c21a54SThe etnaviv authors if (!obj->import_attach) { 61a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 62a8c21a54SThe etnaviv authors 63a8c21a54SThe etnaviv authors mutex_lock(&etnaviv_obj->lock); 64a8c21a54SThe etnaviv authors etnaviv_gem_put_pages(to_etnaviv_bo(obj)); 65a8c21a54SThe etnaviv authors mutex_unlock(&etnaviv_obj->lock); 66a8c21a54SThe etnaviv authors } 67a8c21a54SThe etnaviv authors } 68a8c21a54SThe etnaviv authors 69a8c21a54SThe etnaviv authors static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) 70a8c21a54SThe etnaviv authors { 71a8c21a54SThe etnaviv authors if (etnaviv_obj->vaddr) 72a8c21a54SThe etnaviv authors dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf, 73a8c21a54SThe etnaviv authors etnaviv_obj->vaddr); 74a8c21a54SThe etnaviv authors 75a8c21a54SThe etnaviv authors /* Don't drop the pages for imported dmabuf, as they are not 76a8c21a54SThe etnaviv authors * ours, just free the array we allocated: 77a8c21a54SThe etnaviv authors */ 78a8c21a54SThe etnaviv authors if (etnaviv_obj->pages) 792098105eSMichal Hocko kvfree(etnaviv_obj->pages); 80a8c21a54SThe etnaviv authors 81a8c21a54SThe etnaviv authors drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt); 82a8c21a54SThe etnaviv authors } 83a8c21a54SThe etnaviv authors 84a0a5ab3eSLucas Stach static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj) 85a0a5ab3eSLucas Stach { 86a0a5ab3eSLucas Stach lockdep_assert_held(&etnaviv_obj->lock); 87a0a5ab3eSLucas Stach 88a0a5ab3eSLucas Stach return dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf); 89a0a5ab3eSLucas Stach } 90a0a5ab3eSLucas Stach 91a10e2bdeSLucas Stach static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj, 92a10e2bdeSLucas Stach struct vm_area_struct *vma) 93a10e2bdeSLucas Stach { 94a10e2bdeSLucas Stach return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0); 95a10e2bdeSLucas Stach } 96a10e2bdeSLucas Stach 97a8c21a54SThe etnaviv authors static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = { 98a8c21a54SThe etnaviv authors /* .get_pages should never be called */ 99a8c21a54SThe etnaviv authors .release = etnaviv_gem_prime_release, 100a0a5ab3eSLucas Stach .vmap = etnaviv_gem_prime_vmap_impl, 101a10e2bdeSLucas Stach .mmap = etnaviv_gem_prime_mmap_obj, 102a8c21a54SThe etnaviv authors }; 103a8c21a54SThe etnaviv authors 104a8c21a54SThe etnaviv authors struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev, 105a8c21a54SThe etnaviv authors struct dma_buf_attachment *attach, struct sg_table *sgt) 106a8c21a54SThe etnaviv authors { 107a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj; 108a8c21a54SThe etnaviv authors size_t size = PAGE_ALIGN(attach->dmabuf->size); 109a8c21a54SThe etnaviv authors int ret, npages; 110a8c21a54SThe etnaviv authors 111a8c21a54SThe etnaviv authors ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC, 112a8c21a54SThe etnaviv authors attach->dmabuf->resv, 113a8c21a54SThe etnaviv authors &etnaviv_gem_prime_ops, &etnaviv_obj); 114a8c21a54SThe etnaviv authors if (ret < 0) 115a8c21a54SThe etnaviv authors return ERR_PTR(ret); 116a8c21a54SThe etnaviv authors 117d6a8743dSLucas Stach lockdep_set_class(&etnaviv_obj->lock, &etnaviv_prime_lock_class); 118d6a8743dSLucas Stach 119a8c21a54SThe etnaviv authors npages = size / PAGE_SIZE; 120a8c21a54SThe etnaviv authors 121a8c21a54SThe etnaviv authors etnaviv_obj->sgt = sgt; 1222098105eSMichal Hocko etnaviv_obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); 123a8c21a54SThe etnaviv authors if (!etnaviv_obj->pages) { 124a8c21a54SThe etnaviv authors ret = -ENOMEM; 125a8c21a54SThe etnaviv authors goto fail; 126a8c21a54SThe etnaviv authors } 127a8c21a54SThe etnaviv authors 128a8c21a54SThe etnaviv authors ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages, 129a8c21a54SThe etnaviv authors NULL, npages); 130a8c21a54SThe etnaviv authors if (ret) 131a8c21a54SThe etnaviv authors goto fail; 132a8c21a54SThe etnaviv authors 13354f09288SLucas Stach etnaviv_gem_obj_add(dev, &etnaviv_obj->base); 134a8c21a54SThe etnaviv authors 135a8c21a54SThe etnaviv authors return &etnaviv_obj->base; 136a8c21a54SThe etnaviv authors 137a8c21a54SThe etnaviv authors fail: 13823d1dd03SCihangir Akturk drm_gem_object_put_unlocked(&etnaviv_obj->base); 139a8c21a54SThe etnaviv authors 140a8c21a54SThe etnaviv authors return ERR_PTR(ret); 141a8c21a54SThe etnaviv authors } 1428555137eSEric Anholt 1438555137eSEric Anholt struct reservation_object *etnaviv_gem_prime_res_obj(struct drm_gem_object *obj) 1448555137eSEric Anholt { 1458555137eSEric Anholt struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 1468555137eSEric Anholt 1478555137eSEric Anholt return etnaviv_obj->resv; 1488555137eSEric Anholt } 149