1a8c21a54SThe etnaviv authors /* 2a8c21a54SThe etnaviv authors * Copyright (C) 2013 Red Hat 3a8c21a54SThe etnaviv authors * Author: Rob Clark <robdclark@gmail.com> 4a8c21a54SThe etnaviv authors * 5a8c21a54SThe etnaviv authors * This program is free software; you can redistribute it and/or modify it 6a8c21a54SThe etnaviv authors * under the terms of the GNU General Public License version 2 as published by 7a8c21a54SThe etnaviv authors * the Free Software Foundation. 8a8c21a54SThe etnaviv authors * 9a8c21a54SThe etnaviv authors * This program is distributed in the hope that it will be useful, but WITHOUT 10a8c21a54SThe etnaviv authors * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11a8c21a54SThe etnaviv authors * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12a8c21a54SThe etnaviv authors * more details. 13a8c21a54SThe etnaviv authors * 14a8c21a54SThe etnaviv authors * You should have received a copy of the GNU General Public License along with 15a8c21a54SThe etnaviv authors * this program. If not, see <http://www.gnu.org/licenses/>. 16a8c21a54SThe etnaviv authors */ 17a8c21a54SThe etnaviv authors 18a8c21a54SThe etnaviv authors #include <linux/dma-buf.h> 19a8c21a54SThe etnaviv authors #include "etnaviv_drv.h" 20a8c21a54SThe etnaviv authors #include "etnaviv_gem.h" 21a8c21a54SThe etnaviv authors 22a8c21a54SThe etnaviv authors 23a8c21a54SThe etnaviv authors struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj) 24a8c21a54SThe etnaviv authors { 25a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 26a8c21a54SThe etnaviv authors 27a8c21a54SThe etnaviv authors BUG_ON(!etnaviv_obj->sgt); /* should have already pinned! */ 28a8c21a54SThe etnaviv authors 29a8c21a54SThe etnaviv authors return etnaviv_obj->sgt; 30a8c21a54SThe etnaviv authors } 31a8c21a54SThe etnaviv authors 32a8c21a54SThe etnaviv authors void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj) 33a8c21a54SThe etnaviv authors { 34a8c21a54SThe etnaviv authors return etnaviv_gem_vaddr(obj); 35a8c21a54SThe etnaviv authors } 36a8c21a54SThe etnaviv authors 37a8c21a54SThe etnaviv authors void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) 38a8c21a54SThe etnaviv authors { 39a8c21a54SThe etnaviv authors /* TODO msm_gem_vunmap() */ 40a8c21a54SThe etnaviv authors } 41a8c21a54SThe etnaviv authors 42a8c21a54SThe etnaviv authors int etnaviv_gem_prime_pin(struct drm_gem_object *obj) 43a8c21a54SThe etnaviv authors { 44a8c21a54SThe etnaviv authors if (!obj->import_attach) { 45a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 46a8c21a54SThe etnaviv authors 47a8c21a54SThe etnaviv authors mutex_lock(&etnaviv_obj->lock); 48a8c21a54SThe etnaviv authors etnaviv_gem_get_pages(etnaviv_obj); 49a8c21a54SThe etnaviv authors mutex_unlock(&etnaviv_obj->lock); 50a8c21a54SThe etnaviv authors } 51a8c21a54SThe etnaviv authors return 0; 52a8c21a54SThe etnaviv authors } 53a8c21a54SThe etnaviv authors 54a8c21a54SThe etnaviv authors void etnaviv_gem_prime_unpin(struct drm_gem_object *obj) 55a8c21a54SThe etnaviv authors { 56a8c21a54SThe etnaviv authors if (!obj->import_attach) { 57a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 58a8c21a54SThe etnaviv authors 59a8c21a54SThe etnaviv authors mutex_lock(&etnaviv_obj->lock); 60a8c21a54SThe etnaviv authors etnaviv_gem_put_pages(to_etnaviv_bo(obj)); 61a8c21a54SThe etnaviv authors mutex_unlock(&etnaviv_obj->lock); 62a8c21a54SThe etnaviv authors } 63a8c21a54SThe etnaviv authors } 64a8c21a54SThe etnaviv authors 65a8c21a54SThe etnaviv authors static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj) 66a8c21a54SThe etnaviv authors { 67a8c21a54SThe etnaviv authors if (etnaviv_obj->vaddr) 68a8c21a54SThe etnaviv authors dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf, 69a8c21a54SThe etnaviv authors etnaviv_obj->vaddr); 70a8c21a54SThe etnaviv authors 71a8c21a54SThe etnaviv authors /* Don't drop the pages for imported dmabuf, as they are not 72a8c21a54SThe etnaviv authors * ours, just free the array we allocated: 73a8c21a54SThe etnaviv authors */ 74a8c21a54SThe etnaviv authors if (etnaviv_obj->pages) 75a8c21a54SThe etnaviv authors drm_free_large(etnaviv_obj->pages); 76a8c21a54SThe etnaviv authors 77a8c21a54SThe etnaviv authors drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt); 78a8c21a54SThe etnaviv authors } 79a8c21a54SThe etnaviv authors 80a8c21a54SThe etnaviv authors static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = { 81a8c21a54SThe etnaviv authors /* .get_pages should never be called */ 82a8c21a54SThe etnaviv authors .release = etnaviv_gem_prime_release, 83a8c21a54SThe etnaviv authors }; 84a8c21a54SThe etnaviv authors 85a8c21a54SThe etnaviv authors struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev, 86a8c21a54SThe etnaviv authors struct dma_buf_attachment *attach, struct sg_table *sgt) 87a8c21a54SThe etnaviv authors { 88a8c21a54SThe etnaviv authors struct etnaviv_gem_object *etnaviv_obj; 89a8c21a54SThe etnaviv authors size_t size = PAGE_ALIGN(attach->dmabuf->size); 90a8c21a54SThe etnaviv authors int ret, npages; 91a8c21a54SThe etnaviv authors 92a8c21a54SThe etnaviv authors ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC, 93a8c21a54SThe etnaviv authors attach->dmabuf->resv, 94a8c21a54SThe etnaviv authors &etnaviv_gem_prime_ops, &etnaviv_obj); 95a8c21a54SThe etnaviv authors if (ret < 0) 96a8c21a54SThe etnaviv authors return ERR_PTR(ret); 97a8c21a54SThe etnaviv authors 98a8c21a54SThe etnaviv authors npages = size / PAGE_SIZE; 99a8c21a54SThe etnaviv authors 100a8c21a54SThe etnaviv authors etnaviv_obj->sgt = sgt; 101a8c21a54SThe etnaviv authors etnaviv_obj->pages = drm_malloc_ab(npages, sizeof(struct page *)); 102a8c21a54SThe etnaviv authors if (!etnaviv_obj->pages) { 103a8c21a54SThe etnaviv authors ret = -ENOMEM; 104a8c21a54SThe etnaviv authors goto fail; 105a8c21a54SThe etnaviv authors } 106a8c21a54SThe etnaviv authors 107a8c21a54SThe etnaviv authors ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages, 108a8c21a54SThe etnaviv authors NULL, npages); 109a8c21a54SThe etnaviv authors if (ret) 110a8c21a54SThe etnaviv authors goto fail; 111a8c21a54SThe etnaviv authors 112a8c21a54SThe etnaviv authors ret = etnaviv_gem_obj_add(dev, &etnaviv_obj->base); 113a8c21a54SThe etnaviv authors if (ret) 114a8c21a54SThe etnaviv authors goto fail; 115a8c21a54SThe etnaviv authors 116a8c21a54SThe etnaviv authors return &etnaviv_obj->base; 117a8c21a54SThe etnaviv authors 118a8c21a54SThe etnaviv authors fail: 119a8c21a54SThe etnaviv authors drm_gem_object_unreference_unlocked(&etnaviv_obj->base); 120a8c21a54SThe etnaviv authors 121a8c21a54SThe etnaviv authors return ERR_PTR(ret); 122a8c21a54SThe etnaviv authors } 123