From 0f690b56feafb9b119e070218a65af867f10bca6 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Mon, 4 Jan 2021 18:11:10 -0800 Subject: [PATCH] ANDROID: iommu/dma: Add support for DMA_ATTR_SYS_CACHE_NWA IOMMU_SYS_CACHE_NWA allows buffers for non-coherent devices to be mapped with the correct memory attributes so that the buffers can be cached in the system cache, with a no write allocate cache policy. However, this property is only usable by drivers that invoke the IOMMU API directly; it is not usable by drivers that use the DMA API. Thus, introduce DMA_ATTR_SYS_CACHE_NWA, so that drivers for non-coherent devices that use the DMA API can use it to specify if they want a buffer to be cached in the system cache. Bug: 189339242 Change-Id: Ic812a1fb144a58deb4279c2bf121fc6cc4c3b208 Signed-off-by: Isaac J. Manjarres Signed-off-by: Georgi Djakov --- drivers/iommu/dma-iommu.c | 2 ++ include/linux/dma-mapping.h | 9 +++++++++ kernel/dma/mapping.c | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 6ff8db07a274..c9bdec523454 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -615,6 +615,8 @@ static int dma_info_to_prot(enum dma_data_direction dir, bool coherent, prot |= IOMMU_PRIV; if (attrs & DMA_ATTR_SYS_CACHE) prot |= IOMMU_SYS_CACHE; + if (attrs & DMA_ATTR_SYS_CACHE_NWA) + prot |= IOMMU_SYS_CACHE_NWA; switch (dir) { case DMA_BIDIRECTIONAL: diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index fbbf2679b123..7a94663e1066 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -69,6 +69,15 @@ */ #define DMA_ATTR_SYS_CACHE (1UL << 10) +/* + * DMA_ATTR_SYS_CACHE_NWA: used to indicate that the buffer should be mapped + * with the correct memory attributes so that it can be cached in the system or + * last level cache, with a no write allocate cache policy. This is useful for + * buffers that are being mapped for devices that are non-coherent, but can use + * the system cache. + */ +#define DMA_ATTR_SYS_CACHE_NWA (1UL << 11) + /* * A dma_addr_t can hold any valid DMA or bus address for the platform. It can * be given to a device to use as a DMA source or target. It is specific to a diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c index 0897b62e2a6c..03c7211f7e43 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -420,7 +420,8 @@ pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs) if (attrs & DMA_ATTR_WRITE_COMBINE) return pgprot_writecombine(prot); #endif - if (attrs & DMA_ATTR_SYS_CACHE) + if (attrs & DMA_ATTR_SYS_CACHE || + attrs & DMA_ATTR_SYS_CACHE_NWA) return pgprot_syscached(prot); return pgprot_dmacoherent(prot); }