aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2016-08-19 17:49:10 -0400
committerLucas Stach <l.stach@pengutronix.de>2016-09-15 09:29:40 -0400
commite68f270f210776eed956884d1fc3ce1aab0912a3 (patch)
tree63e179422da3b36a55c61e4a7a4f5bc1109e99a6 /drivers/gpu
parent90969c9aa97700663d03c51031652e131df3bd9b (diff)
drm/etnaviv: map cmdbuf through MMU on version 2
With MMUv2 all buffers need to be mapped through the MMU once it is enabled. Align the buffer size to 4K, as the MMU is only able to map page aligned buffers. Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c4
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.c42
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.h2
4 files changed, 49 insertions, 1 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index fcf4b927dc83..9b61be847d45 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1112,6 +1112,9 @@ struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, u32 size,
1112 if (!cmdbuf) 1112 if (!cmdbuf)
1113 return NULL; 1113 return NULL;
1114 1114
1115 if (gpu->mmu->version == ETNAVIV_IOMMU_V2)
1116 size = ALIGN(size, SZ_4K);
1117
1115 cmdbuf->vaddr = dma_alloc_wc(gpu->dev, size, &cmdbuf->paddr, 1118 cmdbuf->vaddr = dma_alloc_wc(gpu->dev, size, &cmdbuf->paddr,
1116 GFP_KERNEL); 1119 GFP_KERNEL);
1117 if (!cmdbuf->vaddr) { 1120 if (!cmdbuf->vaddr) {
@@ -1127,6 +1130,7 @@ struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, u32 size,
1127 1130
1128void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf) 1131void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
1129{ 1132{
1133 etnaviv_iommu_put_cmdbuf_va(cmdbuf->gpu, cmdbuf);
1130 dma_free_wc(cmdbuf->gpu->dev, cmdbuf->size, cmdbuf->vaddr, 1134 dma_free_wc(cmdbuf->gpu->dev, cmdbuf->size, cmdbuf->vaddr,
1131 cmdbuf->paddr); 1135 cmdbuf->paddr);
1132 kfree(cmdbuf); 1136 kfree(cmdbuf);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 7a10a9c32a70..73c278dc3706 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -160,6 +160,8 @@ struct etnaviv_cmdbuf {
160 dma_addr_t paddr; 160 dma_addr_t paddr;
161 u32 size; 161 u32 size;
162 u32 user_size; 162 u32 user_size;
163 /* vram node used if the cmdbuf is mapped through the MMUv2 */
164 struct drm_mm_node vram_node;
163 /* fence after which this buffer is to be disposed */ 165 /* fence after which this buffer is to be disposed */
164 struct fence *fence; 166 struct fence *fence;
165 /* target exec state */ 167 /* target exec state */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index 69ea0a0a70c2..98c84ef862c7 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -319,9 +319,49 @@ void etnaviv_iommu_restore(struct etnaviv_gpu *gpu)
319u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu, 319u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu,
320 struct etnaviv_cmdbuf *buf) 320 struct etnaviv_cmdbuf *buf)
321{ 321{
322 return buf->paddr - gpu->memory_base; 322 struct etnaviv_iommu *mmu = gpu->mmu;
323
324 if (mmu->version == ETNAVIV_IOMMU_V1) {
325 return buf->paddr - gpu->memory_base;
326 } else {
327 int ret;
328
329 if (buf->vram_node.allocated)
330 return (u32)buf->vram_node.start;
331
332 mutex_lock(&mmu->lock);
333 ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, buf->size);
334 if (ret < 0) {
335 mutex_unlock(&mmu->lock);
336 return 0;
337 }
338 ret = iommu_map(mmu->domain, buf->vram_node.start, buf->paddr,
339 buf->size, IOMMU_READ);
340 if (ret < 0) {
341 drm_mm_remove_node(&buf->vram_node);
342 mutex_unlock(&mmu->lock);
343 return 0;
344 }
345 mmu->last_iova = buf->vram_node.start + buf->size;
346 gpu->mmu->need_flush = true;
347 mutex_unlock(&mmu->lock);
348
349 return (u32)buf->vram_node.start;
350 }
323} 351}
324 352
353void etnaviv_iommu_put_cmdbuf_va(struct etnaviv_gpu *gpu,
354 struct etnaviv_cmdbuf *buf)
355{
356 struct etnaviv_iommu *mmu = gpu->mmu;
357
358 if (mmu->version == ETNAVIV_IOMMU_V2 && buf->vram_node.allocated) {
359 mutex_lock(&mmu->lock);
360 iommu_unmap(mmu->domain, buf->vram_node.start, buf->size);
361 drm_mm_remove_node(&buf->vram_node);
362 mutex_unlock(&mmu->lock);
363 }
364}
325size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu) 365size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu)
326{ 366{
327 struct etnaviv_iommu_ops *ops; 367 struct etnaviv_iommu_ops *ops;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
index 0d34325a318a..e787e49c9693 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
@@ -64,6 +64,8 @@ void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu);
64 64
65u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu, 65u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu,
66 struct etnaviv_cmdbuf *buf); 66 struct etnaviv_cmdbuf *buf);
67void etnaviv_iommu_put_cmdbuf_va(struct etnaviv_gpu *gpu,
68 struct etnaviv_cmdbuf *buf);
67 69
68size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu); 70size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu);
69void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf); 71void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf);