diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 7f71b6663e99..3c58602e1229 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -432,6 +432,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 956151052d45..599228bd9bb9 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 51bb8fa8eb89..dd2762027d5f 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -348,6 +348,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 */