diff options
author | Lucas Stach <l.stach@pengutronix.de> | 2016-08-20 00:49:10 +0300 |
---|---|---|
committer | Lucas Stach <l.stach@pengutronix.de> | 2016-09-15 16:29:40 +0300 |
commit | e68f270f210776eed956884d1fc3ce1aab0912a3 (patch) | |
tree | 63e179422da3b36a55c61e4a7a4f5bc1109e99a6 /drivers/gpu/drm/etnaviv/etnaviv_mmu.c | |
parent | 90969c9aa97700663d03c51031652e131df3bd9b (diff) | |
download | 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.c | 42 |
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; |