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