aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/etnaviv/Makefile1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_buffer.c14
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c153
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h58
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c5
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_dump.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c8
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c95
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h28
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_iommu.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.c60
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.h10
14 files changed, 329 insertions, 123 deletions
diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile
index 1086e9876f91..4f76c992043f 100644
--- a/drivers/gpu/drm/etnaviv/Makefile
+++ b/drivers/gpu/drm/etnaviv/Makefile
@@ -1,6 +1,7 @@
1etnaviv-y := \ 1etnaviv-y := \
2 etnaviv_buffer.o \ 2 etnaviv_buffer.o \
3 etnaviv_cmd_parser.o \ 3 etnaviv_cmd_parser.o \
4 etnaviv_cmdbuf.o \
4 etnaviv_drv.o \ 5 etnaviv_drv.o \
5 etnaviv_dump.o \ 6 etnaviv_dump.o \
6 etnaviv_gem_prime.o \ 7 etnaviv_gem_prime.o \
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
index d9230132dfbc..ed9588f36bc9 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -15,6 +15,7 @@
15 * this program. If not, see <http://www.gnu.org/licenses/>. 15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18#include "etnaviv_cmdbuf.h"
18#include "etnaviv_gpu.h" 19#include "etnaviv_gpu.h"
19#include "etnaviv_gem.h" 20#include "etnaviv_gem.h"
20#include "etnaviv_mmu.h" 21#include "etnaviv_mmu.h"
@@ -125,7 +126,7 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
125 u32 *ptr = buf->vaddr + off; 126 u32 *ptr = buf->vaddr + off;
126 127
127 dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n", 128 dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n",
128 ptr, etnaviv_iommu_get_cmdbuf_va(gpu, buf) + off, size - len * 4 - off); 129 ptr, etnaviv_cmdbuf_get_va(buf) + off, size - len * 4 - off);
129 130
130 print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, 131 print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
131 ptr, len * 4, 0); 132 ptr, len * 4, 0);
@@ -158,7 +159,7 @@ static u32 etnaviv_buffer_reserve(struct etnaviv_gpu *gpu,
158 if (buffer->user_size + cmd_dwords * sizeof(u64) > buffer->size) 159 if (buffer->user_size + cmd_dwords * sizeof(u64) > buffer->size)
159 buffer->user_size = 0; 160 buffer->user_size = 0;
160 161
161 return etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + buffer->user_size; 162 return etnaviv_cmdbuf_get_va(buffer) + buffer->user_size;
162} 163}
163 164
164u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu) 165u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
@@ -169,7 +170,7 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
169 buffer->user_size = 0; 170 buffer->user_size = 0;
170 171
171 CMD_WAIT(buffer); 172 CMD_WAIT(buffer);
172 CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + 173 CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
173 buffer->user_size - 4); 174 buffer->user_size - 4);
174 175
175 return buffer->user_size / 8; 176 return buffer->user_size / 8;
@@ -261,7 +262,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
261 if (drm_debug & DRM_UT_DRIVER) 262 if (drm_debug & DRM_UT_DRIVER)
262 etnaviv_buffer_dump(gpu, buffer, 0, 0x50); 263 etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
263 264
264 link_target = etnaviv_iommu_get_cmdbuf_va(gpu, cmdbuf); 265 link_target = etnaviv_cmdbuf_get_va(cmdbuf);
265 link_dwords = cmdbuf->size / 8; 266 link_dwords = cmdbuf->size / 8;
266 267
267 /* 268 /*
@@ -355,12 +356,13 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
355 CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | 356 CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
356 VIVS_GL_EVENT_FROM_PE); 357 VIVS_GL_EVENT_FROM_PE);
357 CMD_WAIT(buffer); 358 CMD_WAIT(buffer);
358 CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + 359 CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
359 buffer->user_size - 4); 360 buffer->user_size - 4);
360 361
361 if (drm_debug & DRM_UT_DRIVER) 362 if (drm_debug & DRM_UT_DRIVER)
362 pr_info("stream link to 0x%08x @ 0x%08x %p\n", 363 pr_info("stream link to 0x%08x @ 0x%08x %p\n",
363 return_target, etnaviv_iommu_get_cmdbuf_va(gpu, cmdbuf), cmdbuf->vaddr); 364 return_target, etnaviv_cmdbuf_get_va(cmdbuf),
365 cmdbuf->vaddr);
364 366
365 if (drm_debug & DRM_UT_DRIVER) { 367 if (drm_debug & DRM_UT_DRIVER) {
366 print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, 368 print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
index 2a2e5e366ab7..6e3bbcf24160 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
@@ -56,6 +56,8 @@ static const struct {
56 ST(0x0644, 1), 56 ST(0x0644, 1),
57 ST(0x064c, 1), 57 ST(0x064c, 1),
58 ST(0x0680, 8), 58 ST(0x0680, 8),
59 ST(0x086c, 1),
60 ST(0x1028, 1),
59 ST(0x1410, 1), 61 ST(0x1410, 1),
60 ST(0x1430, 1), 62 ST(0x1430, 1),
61 ST(0x1458, 1), 63 ST(0x1458, 1),
@@ -73,8 +75,12 @@ static const struct {
73 ST(0x16c0, 8), 75 ST(0x16c0, 8),
74 ST(0x16e0, 8), 76 ST(0x16e0, 8),
75 ST(0x1740, 8), 77 ST(0x1740, 8),
78 ST(0x17c0, 8),
79 ST(0x17e0, 8),
76 ST(0x2400, 14 * 16), 80 ST(0x2400, 14 * 16),
77 ST(0x10800, 32 * 16), 81 ST(0x10800, 32 * 16),
82 ST(0x14600, 16),
83 ST(0x14800, 8 * 8),
78#undef ST 84#undef ST
79}; 85};
80 86
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
new file mode 100644
index 000000000000..633e0f07cbac
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
@@ -0,0 +1,153 @@
1/*
2 * Copyright (C) 2017 Etnaviv Project
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <drm/drm_mm.h>
18
19#include "etnaviv_cmdbuf.h"
20#include "etnaviv_gpu.h"
21#include "etnaviv_mmu.h"
22
23#define SUBALLOC_SIZE SZ_256K
24#define SUBALLOC_GRANULE SZ_4K
25#define SUBALLOC_GRANULES (SUBALLOC_SIZE / SUBALLOC_GRANULE)
26
27struct etnaviv_cmdbuf_suballoc {
28 /* suballocated dma buffer properties */
29 struct etnaviv_gpu *gpu;
30 void *vaddr;
31 dma_addr_t paddr;
32
33 /* GPU mapping */
34 u32 iova;
35 struct drm_mm_node vram_node; /* only used on MMUv2 */
36
37 /* allocation management */
38 struct mutex lock;
39 DECLARE_BITMAP(granule_map, SUBALLOC_GRANULES);
40 int free_space;
41 wait_queue_head_t free_event;
42};
43
44struct etnaviv_cmdbuf_suballoc *
45etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu)
46{
47 struct etnaviv_cmdbuf_suballoc *suballoc;
48 int ret;
49
50 suballoc = kzalloc(sizeof(*suballoc), GFP_KERNEL);
51 if (!suballoc)
52 return ERR_PTR(-ENOMEM);
53
54 suballoc->gpu = gpu;
55 mutex_init(&suballoc->lock);
56 init_waitqueue_head(&suballoc->free_event);
57
58 suballoc->vaddr = dma_alloc_wc(gpu->dev, SUBALLOC_SIZE,
59 &suballoc->paddr, GFP_KERNEL);
60 if (!suballoc->vaddr)
61 goto free_suballoc;
62
63 ret = etnaviv_iommu_get_suballoc_va(gpu, suballoc->paddr,
64 &suballoc->vram_node, SUBALLOC_SIZE,
65 &suballoc->iova);
66 if (ret)
67 goto free_dma;
68
69 return suballoc;
70
71free_dma:
72 dma_free_wc(gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, suballoc->paddr);
73free_suballoc:
74 kfree(suballoc);
75
76 return NULL;
77}
78
79void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)
80{
81 etnaviv_iommu_put_suballoc_va(suballoc->gpu, &suballoc->vram_node,
82 SUBALLOC_SIZE, suballoc->iova);
83 dma_free_wc(suballoc->gpu->dev, SUBALLOC_SIZE, suballoc->vaddr,
84 suballoc->paddr);
85 kfree(suballoc);
86}
87
88struct etnaviv_cmdbuf *
89etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
90 size_t nr_bos)
91{
92 struct etnaviv_cmdbuf *cmdbuf;
93 size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]),
94 sizeof(*cmdbuf));
95 int granule_offs, order, ret;
96
97 cmdbuf = kzalloc(sz, GFP_KERNEL);
98 if (!cmdbuf)
99 return NULL;
100
101 cmdbuf->suballoc = suballoc;
102 cmdbuf->size = size;
103
104 order = order_base_2(ALIGN(size, SUBALLOC_GRANULE) / SUBALLOC_GRANULE);
105retry:
106 mutex_lock(&suballoc->lock);
107 granule_offs = bitmap_find_free_region(suballoc->granule_map,
108 SUBALLOC_GRANULES, order);
109 if (granule_offs < 0) {
110 suballoc->free_space = 0;
111 mutex_unlock(&suballoc->lock);
112 ret = wait_event_interruptible_timeout(suballoc->free_event,
113 suballoc->free_space,
114 msecs_to_jiffies(10 * 1000));
115 if (!ret) {
116 dev_err(suballoc->gpu->dev,
117 "Timeout waiting for cmdbuf space\n");
118 return NULL;
119 }
120 goto retry;
121 }
122 mutex_unlock(&suballoc->lock);
123 cmdbuf->suballoc_offset = granule_offs * SUBALLOC_GRANULE;
124 cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset;
125
126 return cmdbuf;
127}
128
129void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
130{
131 struct etnaviv_cmdbuf_suballoc *suballoc = cmdbuf->suballoc;
132 int order = order_base_2(ALIGN(cmdbuf->size, SUBALLOC_GRANULE) /
133 SUBALLOC_GRANULE);
134
135 mutex_lock(&suballoc->lock);
136 bitmap_release_region(suballoc->granule_map,
137 cmdbuf->suballoc_offset / SUBALLOC_GRANULE,
138 order);
139 suballoc->free_space = 1;
140 mutex_unlock(&suballoc->lock);
141 wake_up_all(&suballoc->free_event);
142 kfree(cmdbuf);
143}
144
145u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf)
146{
147 return buf->suballoc->iova + buf->suballoc_offset;
148}
149
150dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf)
151{
152 return buf->suballoc->paddr + buf->suballoc_offset;
153}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h
new file mode 100644
index 000000000000..80d78076c679
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h
@@ -0,0 +1,58 @@
1/*
2 * Copyright (C) 2017 Etnaviv Project
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef __ETNAVIV_CMDBUF_H__
18#define __ETNAVIV_CMDBUF_H__
19
20#include <linux/types.h>
21
22struct etnaviv_gpu;
23struct etnaviv_cmdbuf_suballoc;
24
25struct etnaviv_cmdbuf {
26 /* suballocator this cmdbuf is allocated from */
27 struct etnaviv_cmdbuf_suballoc *suballoc;
28 /* user context key, must be unique between all active users */
29 struct etnaviv_file_private *ctx;
30 /* cmdbuf properties */
31 int suballoc_offset;
32 void *vaddr;
33 u32 size;
34 u32 user_size;
35 /* fence after which this buffer is to be disposed */
36 struct dma_fence *fence;
37 /* target exec state */
38 u32 exec_state;
39 /* per GPU in-flight list */
40 struct list_head node;
41 /* BOs attached to this command buffer */
42 unsigned int nr_bos;
43 struct etnaviv_vram_mapping *bo_map[0];
44};
45
46struct etnaviv_cmdbuf_suballoc *
47etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu);
48void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc);
49
50struct etnaviv_cmdbuf *
51etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
52 size_t nr_bos);
53void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);
54
55u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf);
56dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf);
57
58#endif /* __ETNAVIV_CMDBUF_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 590be0d1dd95..587e45043542 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -18,11 +18,11 @@
18#include <linux/of_platform.h> 18#include <linux/of_platform.h>
19#include <drm/drm_of.h> 19#include <drm/drm_of.h>
20 20
21#include "etnaviv_cmdbuf.h"
21#include "etnaviv_drv.h" 22#include "etnaviv_drv.h"
22#include "etnaviv_gpu.h" 23#include "etnaviv_gpu.h"
23#include "etnaviv_gem.h" 24#include "etnaviv_gem.h"
24#include "etnaviv_mmu.h" 25#include "etnaviv_mmu.h"
25#include "etnaviv_gem.h"
26 26
27#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING 27#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
28static bool reglog; 28static bool reglog;
@@ -177,7 +177,8 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m)
177 u32 i; 177 u32 i;
178 178
179 seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n", 179 seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n",
180 buf->vaddr, (u64)buf->paddr, size - buf->user_size); 180 buf->vaddr, (u64)etnaviv_cmdbuf_get_pa(buf),
181 size - buf->user_size);
181 182
182 for (i = 0; i < size / 4; i++) { 183 for (i = 0; i < size / 4; i++) {
183 if (i && !(i % 4)) 184 if (i && !(i % 4))
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
index af65491a78e2..d019b5e311cc 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include <linux/devcoredump.h> 17#include <linux/devcoredump.h>
18#include "etnaviv_cmdbuf.h"
18#include "etnaviv_dump.h" 19#include "etnaviv_dump.h"
19#include "etnaviv_gem.h" 20#include "etnaviv_gem.h"
20#include "etnaviv_gpu.h" 21#include "etnaviv_gpu.h"
@@ -177,12 +178,11 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu)
177 etnaviv_core_dump_mmu(&iter, gpu, mmu_size); 178 etnaviv_core_dump_mmu(&iter, gpu, mmu_size);
178 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer->vaddr, 179 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer->vaddr,
179 gpu->buffer->size, 180 gpu->buffer->size,
180 etnaviv_iommu_get_cmdbuf_va(gpu, gpu->buffer)); 181 etnaviv_cmdbuf_get_va(gpu->buffer));
181 182
182 list_for_each_entry(cmd, &gpu->active_cmd_list, node) 183 list_for_each_entry(cmd, &gpu->active_cmd_list, node)
183 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, cmd->vaddr, 184 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, cmd->vaddr,
184 cmd->size, 185 cmd->size, etnaviv_cmdbuf_get_va(cmd));
185 etnaviv_iommu_get_cmdbuf_va(gpu, cmd));
186 186
187 /* Reserve space for the bomap */ 187 /* Reserve space for the bomap */
188 if (n_bomap_pages) { 188 if (n_bomap_pages) {
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index afdd55ddf821..726090d7a6ac 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include <linux/reservation.h> 17#include <linux/reservation.h>
18#include "etnaviv_cmdbuf.h"
18#include "etnaviv_drv.h" 19#include "etnaviv_drv.h"
19#include "etnaviv_gpu.h" 20#include "etnaviv_gpu.h"
20#include "etnaviv_gem.h" 21#include "etnaviv_gem.h"
@@ -332,8 +333,9 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
332 bos = drm_malloc_ab(args->nr_bos, sizeof(*bos)); 333 bos = drm_malloc_ab(args->nr_bos, sizeof(*bos));
333 relocs = drm_malloc_ab(args->nr_relocs, sizeof(*relocs)); 334 relocs = drm_malloc_ab(args->nr_relocs, sizeof(*relocs));
334 stream = drm_malloc_ab(1, args->stream_size); 335 stream = drm_malloc_ab(1, args->stream_size);
335 cmdbuf = etnaviv_gpu_cmdbuf_new(gpu, ALIGN(args->stream_size, 8) + 8, 336 cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc,
336 args->nr_bos); 337 ALIGN(args->stream_size, 8) + 8,
338 args->nr_bos);
337 if (!bos || !relocs || !stream || !cmdbuf) { 339 if (!bos || !relocs || !stream || !cmdbuf) {
338 ret = -ENOMEM; 340 ret = -ENOMEM;
339 goto err_submit_cmds; 341 goto err_submit_cmds;
@@ -422,7 +424,7 @@ err_submit_objects:
422err_submit_cmds: 424err_submit_cmds:
423 /* if we still own the cmdbuf */ 425 /* if we still own the cmdbuf */
424 if (cmdbuf) 426 if (cmdbuf)
425 etnaviv_gpu_cmdbuf_free(cmdbuf); 427 etnaviv_cmdbuf_free(cmdbuf);
426 if (stream) 428 if (stream)
427 drm_free_large(stream); 429 drm_free_large(stream);
428 if (bos) 430 if (bos)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 0a67124bb2a4..130d7d517a19 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -18,6 +18,8 @@
18#include <linux/dma-fence.h> 18#include <linux/dma-fence.h>
19#include <linux/moduleparam.h> 19#include <linux/moduleparam.h>
20#include <linux/of_device.h> 20#include <linux/of_device.h>
21
22#include "etnaviv_cmdbuf.h"
21#include "etnaviv_dump.h" 23#include "etnaviv_dump.h"
22#include "etnaviv_gpu.h" 24#include "etnaviv_gpu.h"
23#include "etnaviv_gem.h" 25#include "etnaviv_gem.h"
@@ -546,6 +548,37 @@ void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch)
546 VIVS_FE_COMMAND_CONTROL_PREFETCH(prefetch)); 548 VIVS_FE_COMMAND_CONTROL_PREFETCH(prefetch));
547} 549}
548 550
551static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
552{
553 /*
554 * Base value for VIVS_PM_PULSE_EATER register on models where it
555 * cannot be read, extracted from vivante kernel driver.
556 */
557 u32 pulse_eater = 0x01590880;
558
559 if (etnaviv_is_model_rev(gpu, GC4000, 0x5208) ||
560 etnaviv_is_model_rev(gpu, GC4000, 0x5222)) {
561 pulse_eater |= BIT(23);
562
563 }
564
565 if (etnaviv_is_model_rev(gpu, GC1000, 0x5039) ||
566 etnaviv_is_model_rev(gpu, GC1000, 0x5040)) {
567 pulse_eater &= ~BIT(16);
568 pulse_eater |= BIT(17);
569 }
570
571 if ((gpu->identity.revision > 0x5420) &&
572 (gpu->identity.features & chipFeatures_PIPE_3D))
573 {
574 /* Performance fix: disable internal DFS */
575 pulse_eater = gpu_read(gpu, VIVS_PM_PULSE_EATER);
576 pulse_eater |= BIT(18);
577 }
578
579 gpu_write(gpu, VIVS_PM_PULSE_EATER, pulse_eater);
580}
581
549static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) 582static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
550{ 583{
551 u16 prefetch; 584 u16 prefetch;
@@ -586,6 +619,9 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
586 gpu_write(gpu, VIVS_MC_BUS_CONFIG, bus_config); 619 gpu_write(gpu, VIVS_MC_BUS_CONFIG, bus_config);
587 } 620 }
588 621
622 /* setup the pulse eater */
623 etnaviv_gpu_setup_pulse_eater(gpu);
624
589 /* setup the MMU */ 625 /* setup the MMU */
590 etnaviv_iommu_restore(gpu); 626 etnaviv_iommu_restore(gpu);
591 627
@@ -593,7 +629,7 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
593 prefetch = etnaviv_buffer_init(gpu); 629 prefetch = etnaviv_buffer_init(gpu);
594 630
595 gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U); 631 gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U);
596 etnaviv_gpu_start_fe(gpu, etnaviv_iommu_get_cmdbuf_va(gpu, gpu->buffer), 632 etnaviv_gpu_start_fe(gpu, etnaviv_cmdbuf_get_va(gpu->buffer),
597 prefetch); 633 prefetch);
598} 634}
599 635
@@ -658,8 +694,15 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
658 goto fail; 694 goto fail;
659 } 695 }
660 696
697 gpu->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(gpu);
698 if (IS_ERR(gpu->cmdbuf_suballoc)) {
699 dev_err(gpu->dev, "Failed to create cmdbuf suballocator\n");
700 ret = PTR_ERR(gpu->cmdbuf_suballoc);
701 goto fail;
702 }
703
661 /* Create buffer: */ 704 /* Create buffer: */
662 gpu->buffer = etnaviv_gpu_cmdbuf_new(gpu, PAGE_SIZE, 0); 705 gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0);
663 if (!gpu->buffer) { 706 if (!gpu->buffer) {
664 ret = -ENOMEM; 707 ret = -ENOMEM;
665 dev_err(gpu->dev, "could not create command buffer\n"); 708 dev_err(gpu->dev, "could not create command buffer\n");
@@ -667,7 +710,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
667 } 710 }
668 711
669 if (gpu->mmu->version == ETNAVIV_IOMMU_V1 && 712 if (gpu->mmu->version == ETNAVIV_IOMMU_V1 &&
670 gpu->buffer->paddr - gpu->memory_base > 0x80000000) { 713 etnaviv_cmdbuf_get_va(gpu->buffer) > 0x80000000) {
671 ret = -EINVAL; 714 ret = -EINVAL;
672 dev_err(gpu->dev, 715 dev_err(gpu->dev,
673 "command buffer outside valid memory window\n"); 716 "command buffer outside valid memory window\n");
@@ -694,7 +737,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
694 return 0; 737 return 0;
695 738
696free_buffer: 739free_buffer:
697 etnaviv_gpu_cmdbuf_free(gpu->buffer); 740 etnaviv_cmdbuf_free(gpu->buffer);
698 gpu->buffer = NULL; 741 gpu->buffer = NULL;
699destroy_iommu: 742destroy_iommu:
700 etnaviv_iommu_destroy(gpu->mmu); 743 etnaviv_iommu_destroy(gpu->mmu);
@@ -1117,41 +1160,6 @@ static void event_free(struct etnaviv_gpu *gpu, unsigned int event)
1117 * Cmdstream submission/retirement: 1160 * Cmdstream submission/retirement:
1118 */ 1161 */
1119 1162
1120struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, u32 size,
1121 size_t nr_bos)
1122{
1123 struct etnaviv_cmdbuf *cmdbuf;
1124 size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]),
1125 sizeof(*cmdbuf));
1126
1127 cmdbuf = kzalloc(sz, GFP_KERNEL);
1128 if (!cmdbuf)
1129 return NULL;
1130
1131 if (gpu->mmu->version == ETNAVIV_IOMMU_V2)
1132 size = ALIGN(size, SZ_4K);
1133
1134 cmdbuf->vaddr = dma_alloc_wc(gpu->dev, size, &cmdbuf->paddr,
1135 GFP_KERNEL);
1136 if (!cmdbuf->vaddr) {
1137 kfree(cmdbuf);
1138 return NULL;
1139 }
1140
1141 cmdbuf->gpu = gpu;
1142 cmdbuf->size = size;
1143
1144 return cmdbuf;
1145}
1146
1147void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
1148{
1149 etnaviv_iommu_put_cmdbuf_va(cmdbuf->gpu, cmdbuf);
1150 dma_free_wc(cmdbuf->gpu->dev, cmdbuf->size, cmdbuf->vaddr,
1151 cmdbuf->paddr);
1152 kfree(cmdbuf);
1153}
1154
1155static void retire_worker(struct work_struct *work) 1163static void retire_worker(struct work_struct *work)
1156{ 1164{
1157 struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu, 1165 struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu,
@@ -1177,7 +1185,7 @@ static void retire_worker(struct work_struct *work)
1177 etnaviv_gem_mapping_unreference(mapping); 1185 etnaviv_gem_mapping_unreference(mapping);
1178 } 1186 }
1179 1187
1180 etnaviv_gpu_cmdbuf_free(cmdbuf); 1188 etnaviv_cmdbuf_free(cmdbuf);
1181 /* 1189 /*
1182 * We need to balance the runtime PM count caused by 1190 * We need to balance the runtime PM count caused by
1183 * each submission. Upon submission, we increment 1191 * each submission. Upon submission, we increment
@@ -1593,10 +1601,15 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
1593#endif 1601#endif
1594 1602
1595 if (gpu->buffer) { 1603 if (gpu->buffer) {
1596 etnaviv_gpu_cmdbuf_free(gpu->buffer); 1604 etnaviv_cmdbuf_free(gpu->buffer);
1597 gpu->buffer = NULL; 1605 gpu->buffer = NULL;
1598 } 1606 }
1599 1607
1608 if (gpu->cmdbuf_suballoc) {
1609 etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc);
1610 gpu->cmdbuf_suballoc = NULL;
1611 }
1612
1600 if (gpu->mmu) { 1613 if (gpu->mmu) {
1601 etnaviv_iommu_destroy(gpu->mmu); 1614 etnaviv_iommu_destroy(gpu->mmu);
1602 gpu->mmu = NULL; 1615 gpu->mmu = NULL;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 8c6b824e9d0a..1c0606ea7d5e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -92,6 +92,7 @@ struct etnaviv_event {
92 struct dma_fence *fence; 92 struct dma_fence *fence;
93}; 93};
94 94
95struct etnaviv_cmdbuf_suballoc;
95struct etnaviv_cmdbuf; 96struct etnaviv_cmdbuf;
96 97
97struct etnaviv_gpu { 98struct etnaviv_gpu {
@@ -135,6 +136,7 @@ struct etnaviv_gpu {
135 int irq; 136 int irq;
136 137
137 struct etnaviv_iommu *mmu; 138 struct etnaviv_iommu *mmu;
139 struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
138 140
139 /* Power Control: */ 141 /* Power Control: */
140 struct clk *clk_bus; 142 struct clk *clk_bus;
@@ -150,29 +152,6 @@ struct etnaviv_gpu {
150 struct work_struct recover_work; 152 struct work_struct recover_work;
151}; 153};
152 154
153struct etnaviv_cmdbuf {
154 /* device this cmdbuf is allocated for */
155 struct etnaviv_gpu *gpu;
156 /* user context key, must be unique between all active users */
157 struct etnaviv_file_private *ctx;
158 /* cmdbuf properties */
159 void *vaddr;
160 dma_addr_t paddr;
161 u32 size;
162 u32 user_size;
163 /* vram node used if the cmdbuf is mapped through the MMUv2 */
164 struct drm_mm_node vram_node;
165 /* fence after which this buffer is to be disposed */
166 struct dma_fence *fence;
167 /* target exec state */
168 u32 exec_state;
169 /* per GPU in-flight list */
170 struct list_head node;
171 /* BOs attached to this command buffer */
172 unsigned int nr_bos;
173 struct etnaviv_vram_mapping *bo_map[0];
174};
175
176static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data) 155static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data)
177{ 156{
178 etnaviv_writel(data, gpu->mmio + reg); 157 etnaviv_writel(data, gpu->mmio + reg);
@@ -211,9 +190,6 @@ int etnaviv_gpu_wait_obj_inactive(struct etnaviv_gpu *gpu,
211 struct etnaviv_gem_object *etnaviv_obj, struct timespec *timeout); 190 struct etnaviv_gem_object *etnaviv_obj, struct timespec *timeout);
212int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, 191int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
213 struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf); 192 struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf);
214struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu,
215 u32 size, size_t nr_bos);
216void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);
217int etnaviv_gpu_pm_get_sync(struct etnaviv_gpu *gpu); 193int etnaviv_gpu_pm_get_sync(struct etnaviv_gpu *gpu);
218void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu); 194void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu);
219int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms); 195int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
index 81f1583a7946..7a7c97f599d7 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
@@ -184,7 +184,7 @@ static void etnaviv_iommuv1_dump(struct iommu_domain *domain, void *buf)
184 memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE); 184 memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE);
185} 185}
186 186
187static struct etnaviv_iommu_ops etnaviv_iommu_ops = { 187static const struct etnaviv_iommu_ops etnaviv_iommu_ops = {
188 .ops = { 188 .ops = {
189 .domain_free = etnaviv_domain_free, 189 .domain_free = etnaviv_domain_free,
190 .map = etnaviv_iommuv1_map, 190 .map = etnaviv_iommuv1_map,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
index 7e9c4d210a84..cbe447ac5974 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
@@ -21,6 +21,7 @@
21#include <linux/dma-mapping.h> 21#include <linux/dma-mapping.h>
22#include <linux/bitops.h> 22#include <linux/bitops.h>
23 23
24#include "etnaviv_cmdbuf.h"
24#include "etnaviv_gpu.h" 25#include "etnaviv_gpu.h"
25#include "etnaviv_mmu.h" 26#include "etnaviv_mmu.h"
26#include "etnaviv_iommu.h" 27#include "etnaviv_iommu.h"
@@ -229,7 +230,7 @@ static void etnaviv_iommuv2_dump(struct iommu_domain *domain, void *buf)
229 memcpy(buf, etnaviv_domain->stlb_cpu[i], SZ_4K); 230 memcpy(buf, etnaviv_domain->stlb_cpu[i], SZ_4K);
230} 231}
231 232
232static struct etnaviv_iommu_ops etnaviv_iommu_ops = { 233static const struct etnaviv_iommu_ops etnaviv_iommu_ops = {
233 .ops = { 234 .ops = {
234 .domain_free = etnaviv_iommuv2_domain_free, 235 .domain_free = etnaviv_iommuv2_domain_free,
235 .map = etnaviv_iommuv2_map, 236 .map = etnaviv_iommuv2_map,
@@ -254,7 +255,8 @@ void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu)
254 prefetch = etnaviv_buffer_config_mmuv2(gpu, 255 prefetch = etnaviv_buffer_config_mmuv2(gpu,
255 (u32)etnaviv_domain->mtlb_dma, 256 (u32)etnaviv_domain->mtlb_dma,
256 (u32)etnaviv_domain->bad_page_dma); 257 (u32)etnaviv_domain->bad_page_dma);
257 etnaviv_gpu_start_fe(gpu, gpu->buffer->paddr, prefetch); 258 etnaviv_gpu_start_fe(gpu, (u32)etnaviv_cmdbuf_get_pa(gpu->buffer),
259 prefetch);
258 etnaviv_gpu_wait_idle(gpu, 100); 260 etnaviv_gpu_wait_idle(gpu, 100);
259 261
260 gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE); 262 gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index f503af462dad..ff826c16fb89 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include "common.xml.h" 17#include "common.xml.h"
18#include "etnaviv_cmdbuf.h"
18#include "etnaviv_drv.h" 19#include "etnaviv_drv.h"
19#include "etnaviv_gem.h" 20#include "etnaviv_gem.h"
20#include "etnaviv_gpu.h" 21#include "etnaviv_gpu.h"
@@ -117,14 +118,9 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu *mmu,
117 struct list_head list; 118 struct list_head list;
118 bool found; 119 bool found;
119 120
120 /*
121 * XXX: The DRM_MM_SEARCH_BELOW is really a hack to trick
122 * drm_mm into giving out a low IOVA after address space
123 * rollover. This needs a proper fix.
124 */
125 ret = drm_mm_insert_node_in_range(&mmu->mm, node, 121 ret = drm_mm_insert_node_in_range(&mmu->mm, node,
126 size, 0, mmu->last_iova, ~0UL, 122 size, 0, mmu->last_iova, ~0UL,
127 mmu->last_iova ? DRM_MM_SEARCH_DEFAULT : DRM_MM_SEARCH_BELOW); 123 DRM_MM_SEARCH_DEFAULT);
128 124
129 if (ret != -ENOSPC) 125 if (ret != -ENOSPC)
130 break; 126 break;
@@ -194,11 +190,8 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu *mmu,
194 190
195 /* 191 /*
196 * We removed enough mappings so that the new allocation will 192 * We removed enough mappings so that the new allocation will
197 * succeed. Ensure that the MMU will be flushed before the 193 * succeed, retry the allocation one more time.
198 * associated commit requesting this mapping, and retry the
199 * allocation one more time.
200 */ 194 */
201 mmu->need_flush = true;
202 } 195 }
203 196
204 return ret; 197 return ret;
@@ -250,6 +243,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
250 } 243 }
251 244
252 list_add_tail(&mapping->mmu_node, &mmu->mappings); 245 list_add_tail(&mapping->mmu_node, &mmu->mappings);
246 mmu->need_flush = true;
253 mutex_unlock(&mmu->lock); 247 mutex_unlock(&mmu->lock);
254 248
255 return ret; 249 return ret;
@@ -267,6 +261,7 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
267 etnaviv_iommu_remove_mapping(mmu, mapping); 261 etnaviv_iommu_remove_mapping(mmu, mapping);
268 262
269 list_del(&mapping->mmu_node); 263 list_del(&mapping->mmu_node);
264 mmu->need_flush = true;
270 mutex_unlock(&mmu->lock); 265 mutex_unlock(&mmu->lock);
271} 266}
272 267
@@ -322,55 +317,50 @@ void etnaviv_iommu_restore(struct etnaviv_gpu *gpu)
322 etnaviv_iommuv2_restore(gpu); 317 etnaviv_iommuv2_restore(gpu);
323} 318}
324 319
325u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu, 320int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr,
326 struct etnaviv_cmdbuf *buf) 321 struct drm_mm_node *vram_node, size_t size,
322 u32 *iova)
327{ 323{
328 struct etnaviv_iommu *mmu = gpu->mmu; 324 struct etnaviv_iommu *mmu = gpu->mmu;
329 325
330 if (mmu->version == ETNAVIV_IOMMU_V1) { 326 if (mmu->version == ETNAVIV_IOMMU_V1) {
331 return buf->paddr - gpu->memory_base; 327 *iova = paddr - gpu->memory_base;
328 return 0;
332 } else { 329 } else {
333 int ret; 330 int ret;
334 331
335 if (buf->vram_node.allocated)
336 return (u32)buf->vram_node.start;
337
338 mutex_lock(&mmu->lock); 332 mutex_lock(&mmu->lock);
339 ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, 333 ret = etnaviv_iommu_find_iova(mmu, vram_node, size);
340 buf->size + SZ_64K);
341 if (ret < 0) { 334 if (ret < 0) {
342 mutex_unlock(&mmu->lock); 335 mutex_unlock(&mmu->lock);
343 return 0; 336 return ret;
344 } 337 }
345 ret = iommu_map(mmu->domain, buf->vram_node.start, buf->paddr, 338 ret = iommu_map(mmu->domain, vram_node->start, paddr, size,
346 buf->size, IOMMU_READ); 339 IOMMU_READ);
347 if (ret < 0) { 340 if (ret < 0) {
348 drm_mm_remove_node(&buf->vram_node); 341 drm_mm_remove_node(vram_node);
349 mutex_unlock(&mmu->lock); 342 mutex_unlock(&mmu->lock);
350 return 0; 343 return ret;
351 } 344 }
352 /* 345 mmu->last_iova = vram_node->start + size;
353 * At least on GC3000 the FE MMU doesn't properly flush old TLB
354 * entries. Make sure to space the command buffers out in a way
355 * that the FE MMU prefetch won't load invalid entries.
356 */
357 mmu->last_iova = buf->vram_node.start + buf->size + SZ_64K;
358 gpu->mmu->need_flush = true; 346 gpu->mmu->need_flush = true;
359 mutex_unlock(&mmu->lock); 347 mutex_unlock(&mmu->lock);
360 348
361 return (u32)buf->vram_node.start; 349 *iova = (u32)vram_node->start;
350 return 0;
362 } 351 }
363} 352}
364 353
365void etnaviv_iommu_put_cmdbuf_va(struct etnaviv_gpu *gpu, 354void etnaviv_iommu_put_suballoc_va(struct etnaviv_gpu *gpu,
366 struct etnaviv_cmdbuf *buf) 355 struct drm_mm_node *vram_node, size_t size,
356 u32 iova)
367{ 357{
368 struct etnaviv_iommu *mmu = gpu->mmu; 358 struct etnaviv_iommu *mmu = gpu->mmu;
369 359
370 if (mmu->version == ETNAVIV_IOMMU_V2 && buf->vram_node.allocated) { 360 if (mmu->version == ETNAVIV_IOMMU_V2) {
371 mutex_lock(&mmu->lock); 361 mutex_lock(&mmu->lock);
372 iommu_unmap(mmu->domain, buf->vram_node.start, buf->size); 362 iommu_unmap(mmu->domain,iova, size);
373 drm_mm_remove_node(&buf->vram_node); 363 drm_mm_remove_node(vram_node);
374 mutex_unlock(&mmu->lock); 364 mutex_unlock(&mmu->lock);
375 } 365 }
376} 366}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
index e787e49c9693..54be289e5981 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
@@ -62,10 +62,12 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
62 struct etnaviv_vram_mapping *mapping); 62 struct etnaviv_vram_mapping *mapping);
63void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu); 63void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu);
64 64
65u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu, 65int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr,
66 struct etnaviv_cmdbuf *buf); 66 struct drm_mm_node *vram_node, size_t size,
67void etnaviv_iommu_put_cmdbuf_va(struct etnaviv_gpu *gpu, 67 u32 *iova);
68 struct etnaviv_cmdbuf *buf); 68void etnaviv_iommu_put_suballoc_va(struct etnaviv_gpu *gpu,
69 struct drm_mm_node *vram_node, size_t size,
70 u32 iova);
69 71
70size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu); 72size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu);
71void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf); 73void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf);