diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 3014f16c1aaf..c0c941a04ca2 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -418,6 +418,8 @@ static int dma_info_to_prot(enum dma_data_direction dir, bool coherent, if (attrs & DMA_ATTR_PRIVILEGED) prot |= IOMMU_PRIV; + if (attrs & DMA_ATTR_SYS_CACHE_ONLY) + prot |= IOMMU_SYS_CACHE_ONLY; switch (dir) { case DMA_BIDIRECTIONAL: diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index dca2b1355bb1..562ee1670703 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -61,6 +61,14 @@ */ #define DMA_ATTR_PRIVILEGED (1UL << 9) +/* + * DMA_ATTR_SYS_CACHE_ONLY: 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. 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 (1UL << 10) + /* * 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 8349a9f2c345..d77f6afd4725 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -419,6 +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) + return pgprot_syscached(prot); return pgprot_dmacoherent(prot); } #endif /* CONFIG_MMU */