[PATCH] arm64: dma: Override DMA ops for legacy virtio devices

From: Will Deacon
Date: Fri Jul 27 2018 - 05:49:25 EST


Virtio devices are always cache-coherent, so force use of the coherent
DMA ops for legacy virtio devices where the dma-coherent is known to
be omitted by QEMU for the MMIO transport.

Signed-off-by: Will Deacon <will.deacon@xxxxxxx>
---
arch/arm64/include/asm/dma-mapping.h | 6 ++++++
arch/arm64/mm/dma-mapping.c | 19 +++++++++++++++++++
2 files changed, 25 insertions(+)

diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
index b7847eb8a7bb..30aa8fb62dc3 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -44,6 +44,12 @@ void arch_teardown_dma_ops(struct device *dev);
#define arch_teardown_dma_ops arch_teardown_dma_ops
#endif

+#ifdef CONFIG_VIRTIO
+struct virtio_device;
+void platform_override_dma_ops(struct virtio_device *vdev);
+#define platform_override_dma_ops platform_override_dma_ops
+#endif
+
/* do not use this function in a driver */
static inline bool is_device_dma_coherent(struct device *dev)
{
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 61e93f0b5482..f9ca61b1b34d 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -891,3 +891,22 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
}
#endif
}
+
+#ifdef CONFIG_VIRTIO
+#include <linux/virtio_config.h>
+
+void platform_override_dma_ops(struct virtio_device *vdev)
+{
+ struct device *dev = vdev->dev.parent;
+ const struct dma_map_ops *dma_ops = &arm64_swiotlb_dma_ops;
+
+ if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
+ return;
+
+ dev->archdata.dma_coherent = true;
+ if (iommu_get_domain_for_dev(dev))
+ dma_ops = &iommu_dma_ops;
+
+ set_dma_ops(dev, dma_ops);
+}
+#endif /* CONFIG_VIRTIO */
--
2.1.4