summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2016-08-19 23:49:10 +0200
committerLucas Stach <l.stach@pengutronix.de>2016-09-15 15:29:40 +0200
commite68f270f210776eed956884d1fc3ce1aab0912a3 (patch)
tree63e179422da3b36a55c61e4a7a4f5bc1109e99a6 /drivers/gpu/drm/etnaviv/etnaviv_mmu.c
parent90969c9aa97700663d03c51031652e131df3bd9b (diff)
downloadlinux-e68f270f210776eed956884d1fc3ce1aab0912a3.tar.gz
linux-e68f270f210776eed956884d1fc3ce1aab0912a3.tar.xz
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/drm/etnaviv/etnaviv_mmu.c')
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.c42
1 files changed, 41 insertions, 1 deletions
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)
u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu,
struct etnaviv_cmdbuf *buf)
{
- return buf->paddr - gpu->memory_base;
+ struct etnaviv_iommu *mmu = gpu->mmu;
+
+ if (mmu->version == ETNAVIV_IOMMU_V1) {
+ return buf->paddr - gpu->memory_base;
+ } else {
+ int ret;
+
+ if (buf->vram_node.allocated)
+ return (u32)buf->vram_node.start;
+
+ mutex_lock(&mmu->lock);
+ ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, buf->size);
+ if (ret < 0) {
+ mutex_unlock(&mmu->lock);
+ return 0;
+ }
+ ret = iommu_map(mmu->domain, buf->vram_node.start, buf->paddr,
+ buf->size, IOMMU_READ);
+ if (ret < 0) {
+ drm_mm_remove_node(&buf->vram_node);
+ mutex_unlock(&mmu->lock);
+ return 0;
+ }
+ mmu->last_iova = buf->vram_node.start + buf->size;
+ gpu->mmu->need_flush = true;
+ mutex_unlock(&mmu->lock);
+
+ return (u32)buf->vram_node.start;
+ }
}
+void etnaviv_iommu_put_cmdbuf_va(struct etnaviv_gpu *gpu,
+ struct etnaviv_cmdbuf *buf)
+{
+ struct etnaviv_iommu *mmu = gpu->mmu;
+
+ if (mmu->version == ETNAVIV_IOMMU_V2 && buf->vram_node.allocated) {
+ mutex_lock(&mmu->lock);
+ iommu_unmap(mmu->domain, buf->vram_node.start, buf->size);
+ drm_mm_remove_node(&buf->vram_node);
+ mutex_unlock(&mmu->lock);
+ }
+}
size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu)
{
struct etnaviv_iommu_ops *ops;