diff options
author | Christoph Hellwig <hch@lst.de> | 2019-04-29 16:16:42 +0200 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2019-06-25 07:54:06 +0200 |
commit | 4a54d16f615f41489b2ecbc940f6eb2618ddafd6 (patch) | |
tree | e12a8aa22cac1d57f7135ada2284801a5f1db8b9 /kernel/dma/mapping.c | |
parent | iommu/dma: Apply dma_{alloc,free}_contiguous functions (diff) | |
download | linux-4a54d16f615f41489b2ecbc940f6eb2618ddafd6.tar.xz linux-4a54d16f615f41489b2ecbc940f6eb2618ddafd6.zip |
dma-mapping: truncate dma masks to what dma_addr_t can hold
The dma masks in struct device are always 64-bits wide. But for builds
using a 32-bit dma_addr_t we need to ensure we don't store an
unsupportable value. Before Linux 5.0 this was handled at least by
the ARM dma mapping code by never allowing to set a larger dma_mask,
but these days we allow the driver to just set the largest supported
value and never fall back to a smaller one. Ensure this always works
by truncating the value.
Fixes: 9eb9e96e97b3 ("Documentation/DMA-API-HOWTO: update dma_mask sections")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'kernel/dma/mapping.c')
-rw-r--r-- | kernel/dma/mapping.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c index f7afdadb6770..1f628e7ac709 100644 --- a/kernel/dma/mapping.c +++ b/kernel/dma/mapping.c @@ -317,6 +317,12 @@ void arch_dma_set_mask(struct device *dev, u64 mask); int dma_set_mask(struct device *dev, u64 mask) { + /* + * Truncate the mask to the actually supported dma_addr_t width to + * avoid generating unsupportable addresses. + */ + mask = (dma_addr_t)mask; + if (!dev->dma_mask || !dma_supported(dev, mask)) return -EIO; @@ -330,6 +336,12 @@ EXPORT_SYMBOL(dma_set_mask); #ifndef CONFIG_ARCH_HAS_DMA_SET_COHERENT_MASK int dma_set_coherent_mask(struct device *dev, u64 mask) { + /* + * Truncate the mask to the actually supported dma_addr_t width to + * avoid generating unsupportable addresses. + */ + mask = (dma_addr_t)mask; + if (!dma_supported(dev, mask)) return -EIO; |