From ec1e52f1ca2ddbd1af1ceed2161a1b816aeaed1f 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_ONLY_NWA IOMMU_SYS_CACHE_ONLY_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_ONLY_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 c0c941a04ca2..9b7e427fc5bb 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -420,6 +420,8 @@ static int dma_info_to_prot(enum dma_data_direction dir, bool coherent, prot |= IOMMU_PRIV; if (attrs & DMA_ATTR_SYS_CACHE_ONLY) prot |= IOMMU_SYS_CACHE_ONLY; + if (attrs & DMA_ATTR_SYS_CACHE_ONLY_NWA) + prot |= IOMMU_SYS_CACHE_ONLY_NWA; switch (dir) { case DMA_BIDIRECTIONAL: diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 562ee1670703..b6106938a94b 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -69,6 +69,15 @@ */ #define DMA_ATTR_SYS_CACHE_ONLY (1UL << 10) +/* + * DMA_ATTR_SYS_CACHE_ONLY_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_ONLY_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 d77f6afd4725..af338251e13e 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -419,7 +419,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_ONLY) + if (attrs & DMA_ATTR_SYS_CACHE_ONLY || + attrs & DMA_ATTR_SYS_CACHE_ONLY_NWA) return pgprot_syscached(prot); return pgprot_dmacoherent(prot); }