dabc7a
From 369971aa0101c4cfb84dacaaaa1b5cc5790c14ff Mon Sep 17 00:00:00 2001
dabc7a
From: Thierry Reding <treding@nvidia.com>
dabc7a
Date: Wed, 11 Apr 2018 10:34:17 +0200
dabc7a
Subject: [PATCH] drm/nouveau: tegra: Detach from ARM DMA/IOMMU mapping
dabc7a
dabc7a
Depending on the kernel configuration, early ARM architecture setup code
dabc7a
may have attached the GPU to a DMA/IOMMU mapping that transparently uses
dabc7a
the IOMMU to back the DMA API. Tegra requires special handling for IOMMU
dabc7a
backed buffers (a special bit in the GPU's MMU page tables indicates the
dabc7a
memory path to take: via the SMMU or directly to the memory controller).
dabc7a
Transparently backing DMA memory with an IOMMU prevents Nouveau from
dabc7a
properly handling such memory accesses and causes memory access faults.
dabc7a
dabc7a
As a side-note: buffers other than those allocated in instance memory
dabc7a
don't need to be physically contiguous from the GPU's perspective since
dabc7a
the GPU can map them into contiguous buffers using its own MMU. Mapping
dabc7a
these buffers through the IOMMU is unnecessary and will even lead to
dabc7a
performance degradation because of the additional translation.
dabc7a
dabc7a
Signed-off-by: Thierry Reding <treding@nvidia.com>
dabc7a
---
dabc7a
 drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | 19 +++++++++++++++++++
dabc7a
 1 file changed, 19 insertions(+)
dabc7a
dabc7a
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
dabc7a
index 1f07999aea1d..ac7706f56f6f 100644
dabc7a
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
dabc7a
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
dabc7a
@@ -19,6 +19,11 @@
dabc7a
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
dabc7a
  * DEALINGS IN THE SOFTWARE.
dabc7a
  */
dabc7a
+
dabc7a
+#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
dabc7a
+#include <asm/dma-iommu.h>
dabc7a
+#endif
dabc7a
+
dabc7a
 #include <core/tegra.h>
dabc7a
 #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
dabc7a
 #include "priv.h"
dabc7a
@@ -105,6 +110,20 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
dabc7a
 	unsigned long pgsize_bitmap;
dabc7a
 	int ret;
dabc7a
 
dabc7a
+#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
dabc7a
+	if (dev->archdata.mapping) {
dabc7a
+		struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
dabc7a
+
dabc7a
+		arm_iommu_release_mapping(mapping);
dabc7a
+		arm_iommu_detach_device(dev);
dabc7a
+
dabc7a
+		if (dev->archdata.dma_coherent)
dabc7a
+			set_dma_ops(dev, &arm_coherent_dma_ops);
dabc7a
+		else
dabc7a
+			set_dma_ops(dev, &arm_dma_ops);
dabc7a
+	}
dabc7a
+#endif
dabc7a
+
dabc7a
 	if (!tdev->func->iommu_bit)
dabc7a
 		return;
dabc7a
 
dabc7a
-- 
dabc7a
2.16.3
dabc7a