Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2014-2018 Etnaviv Project
  4 */
  5
  6#include <drm/drm_prime.h>
  7#include <linux/dma-buf.h>
 
  8
  9#include "etnaviv_drv.h"
 10#include "etnaviv_gem.h"
 11
 
 
 12static struct lock_class_key etnaviv_prime_lock_class;
 13
 14struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
 15{
 16	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 17	int npages = obj->size >> PAGE_SHIFT;
 18
 19	if (WARN_ON(!etnaviv_obj->pages))  /* should have already pinned! */
 20		return ERR_PTR(-EINVAL);
 21
 22	return drm_prime_pages_to_sg(etnaviv_obj->pages, npages);
 23}
 24
 25void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj)
 26{
 27	return etnaviv_gem_vmap(obj);
 28}
 29
 30void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
 31{
 32	/* TODO msm_gem_vunmap() */
 33}
 34
 35int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
 36			   struct vm_area_struct *vma)
 37{
 38	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 39	int ret;
 40
 41	ret = drm_gem_mmap_obj(obj, obj->size, vma);
 42	if (ret < 0)
 43		return ret;
 44
 45	return etnaviv_obj->ops->mmap(etnaviv_obj, vma);
 46}
 47
 48int etnaviv_gem_prime_pin(struct drm_gem_object *obj)
 49{
 50	if (!obj->import_attach) {
 51		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 52
 53		mutex_lock(&etnaviv_obj->lock);
 54		etnaviv_gem_get_pages(etnaviv_obj);
 55		mutex_unlock(&etnaviv_obj->lock);
 56	}
 57	return 0;
 58}
 59
 60void etnaviv_gem_prime_unpin(struct drm_gem_object *obj)
 61{
 62	if (!obj->import_attach) {
 63		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 64
 65		mutex_lock(&etnaviv_obj->lock);
 66		etnaviv_gem_put_pages(to_etnaviv_bo(obj));
 67		mutex_unlock(&etnaviv_obj->lock);
 68	}
 69}
 70
 71static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj)
 72{
 
 
 73	if (etnaviv_obj->vaddr)
 74		dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf,
 75			       etnaviv_obj->vaddr);
 76
 77	/* Don't drop the pages for imported dmabuf, as they are not
 78	 * ours, just free the array we allocated:
 79	 */
 80	if (etnaviv_obj->pages)
 81		kvfree(etnaviv_obj->pages);
 82
 83	drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt);
 84}
 85
 86static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
 87{
 
 
 
 88	lockdep_assert_held(&etnaviv_obj->lock);
 89
 90	return dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf);
 
 
 
 91}
 92
 93static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
 94		struct vm_area_struct *vma)
 95{
 96	return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
 97}
 98
 99static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
100	/* .get_pages should never be called */
101	.release = etnaviv_gem_prime_release,
102	.vmap = etnaviv_gem_prime_vmap_impl,
103	.mmap = etnaviv_gem_prime_mmap_obj,
104};
105
106struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
107	struct dma_buf_attachment *attach, struct sg_table *sgt)
108{
109	struct etnaviv_gem_object *etnaviv_obj;
110	size_t size = PAGE_ALIGN(attach->dmabuf->size);
111	int ret, npages;
112
113	ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC,
114				      &etnaviv_gem_prime_ops, &etnaviv_obj);
115	if (ret < 0)
116		return ERR_PTR(ret);
117
118	lockdep_set_class(&etnaviv_obj->lock, &etnaviv_prime_lock_class);
119
120	npages = size / PAGE_SIZE;
121
122	etnaviv_obj->sgt = sgt;
123	etnaviv_obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
124	if (!etnaviv_obj->pages) {
125		ret = -ENOMEM;
126		goto fail;
127	}
128
129	ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages,
130					       NULL, npages);
131	if (ret)
132		goto fail;
133
134	etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
135
136	return &etnaviv_obj->base;
137
138fail:
139	drm_gem_object_put_unlocked(&etnaviv_obj->base);
140
141	return ERR_PTR(ret);
142}
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2014-2018 Etnaviv Project
  4 */
  5
  6#include <drm/drm_prime.h>
  7#include <linux/dma-buf.h>
  8#include <linux/module.h>
  9
 10#include "etnaviv_drv.h"
 11#include "etnaviv_gem.h"
 12
 13MODULE_IMPORT_NS(DMA_BUF);
 14
 15static struct lock_class_key etnaviv_prime_lock_class;
 16
 17struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
 18{
 19	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 20	int npages = obj->size >> PAGE_SHIFT;
 21
 22	if (WARN_ON(!etnaviv_obj->pages))  /* should have already pinned! */
 23		return ERR_PTR(-EINVAL);
 24
 25	return drm_prime_pages_to_sg(obj->dev, etnaviv_obj->pages, npages);
 
 
 
 
 
 26}
 27
 28int etnaviv_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
 29{
 30	void *vaddr;
 
 31
 32	vaddr = etnaviv_gem_vmap(obj);
 33	if (!vaddr)
 34		return -ENOMEM;
 35	iosys_map_set_vaddr(map, vaddr);
 
 36
 37	return 0;
 
 
 
 
 38}
 39
 40int etnaviv_gem_prime_pin(struct drm_gem_object *obj)
 41{
 42	if (!obj->import_attach) {
 43		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 44
 45		mutex_lock(&etnaviv_obj->lock);
 46		etnaviv_gem_get_pages(etnaviv_obj);
 47		mutex_unlock(&etnaviv_obj->lock);
 48	}
 49	return 0;
 50}
 51
 52void etnaviv_gem_prime_unpin(struct drm_gem_object *obj)
 53{
 54	if (!obj->import_attach) {
 55		struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 56
 57		mutex_lock(&etnaviv_obj->lock);
 58		etnaviv_gem_put_pages(to_etnaviv_bo(obj));
 59		mutex_unlock(&etnaviv_obj->lock);
 60	}
 61}
 62
 63static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj)
 64{
 65	struct iosys_map map = IOSYS_MAP_INIT_VADDR(etnaviv_obj->vaddr);
 66
 67	if (etnaviv_obj->vaddr)
 68		dma_buf_vunmap_unlocked(etnaviv_obj->base.import_attach->dmabuf, &map);
 
 69
 70	/* Don't drop the pages for imported dmabuf, as they are not
 71	 * ours, just free the array we allocated:
 72	 */
 73	kvfree(etnaviv_obj->pages);
 
 74
 75	drm_prime_gem_destroy(&etnaviv_obj->base, etnaviv_obj->sgt);
 76}
 77
 78static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
 79{
 80	struct iosys_map map;
 81	int ret;
 82
 83	lockdep_assert_held(&etnaviv_obj->lock);
 84
 85	ret = dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf, &map);
 86	if (ret)
 87		return NULL;
 88	return map.vaddr;
 89}
 90
 91static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
 92		struct vm_area_struct *vma)
 93{
 94	return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
 95}
 96
 97static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
 98	/* .get_pages should never be called */
 99	.release = etnaviv_gem_prime_release,
100	.vmap = etnaviv_gem_prime_vmap_impl,
101	.mmap = etnaviv_gem_prime_mmap_obj,
102};
103
104struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
105	struct dma_buf_attachment *attach, struct sg_table *sgt)
106{
107	struct etnaviv_gem_object *etnaviv_obj;
108	size_t size = PAGE_ALIGN(attach->dmabuf->size);
109	int ret, npages;
110
111	ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC,
112				      &etnaviv_gem_prime_ops, &etnaviv_obj);
113	if (ret < 0)
114		return ERR_PTR(ret);
115
116	lockdep_set_class(&etnaviv_obj->lock, &etnaviv_prime_lock_class);
117
118	npages = size / PAGE_SIZE;
119
120	etnaviv_obj->sgt = sgt;
121	etnaviv_obj->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
122	if (!etnaviv_obj->pages) {
123		ret = -ENOMEM;
124		goto fail;
125	}
126
127	ret = drm_prime_sg_to_page_array(sgt, etnaviv_obj->pages, npages);
 
128	if (ret)
129		goto fail;
130
131	etnaviv_gem_obj_add(dev, &etnaviv_obj->base);
132
133	return &etnaviv_obj->base;
134
135fail:
136	drm_gem_object_put(&etnaviv_obj->base);
137
138	return ERR_PTR(ret);
139}