diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h index bcd953fb1f5a..6db863c3eb93 100644 --- a/include/linux/dma-direct.h +++ b/include/linux/dma-direct.h @@ -3,8 +3,11 @@ #define _LINUX_DMA_DIRECT_H 1 #include +#include /* for min_low_pfn */ #include +static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr); + #ifdef CONFIG_ARCH_HAS_PHYS_TO_DMA #include #else @@ -24,11 +27,16 @@ static inline phys_addr_t __dma_to_phys(struct device *dev, dma_addr_t dev_addr) static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) { + dma_addr_t end = addr + size - 1; + if (!dev->dma_mask) return false; - return addr + size - 1 <= - min_not_zero(*dev->dma_mask, dev->bus_dma_mask); + if (!IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && + min(addr, end) < phys_to_dma(dev, PFN_PHYS(min_low_pfn))) + return false; + + return end <= min_not_zero(*dev->dma_mask, dev->bus_dma_mask); } #endif /* !CONFIG_ARCH_HAS_PHYS_TO_DMA */