ARM: dma-api: fix max_pfn off-by-one error in __dma_supported()
Subsystems (2)
PATCH RESEND v2 1/1 ARM: dma-api: fix max_pfn off-by-one error in __dma_supported()
From: Chen-Yu Tsai <[email protected]>
max_pfn, as set in arch/arm/mm/init.c:
static void __init find_limits(unsigned long *min,
unsigned long *max_low,
unsigned long *max_high)
{
*max_low = PFN_DOWN(memblock_get_current_limit());
*min = PFN_UP(memblock_start_of_DRAM());
*max_high = PFN_DOWN(memblock_end_of_DRAM());
}with memblock_end_of_DRAM() pointing to the next byte after DRAM. As such, max_pfn points to the PFN after the end of DRAM.
Thus when using max_pfn to check DMA masks, we should subtract one when checking DMA ranges against it.
Commit 8bf1268f48ad ("ARM: dma-api: fix off-by-one error in __dma_supported()") fixed the same issue, but missed this spot.
This issue was found while working on the sun4i-csi v4l2 driver on the Allwinner R40 SoC. On Allwinner SoCs, DRAM is offset at 0x40000000, and we are starting to use of_dma_configure() with the "dma-ranges" property in the device tree to have the DMA API handle the offset.
In this particular instance, dma-ranges was set to the same range as the actual available (2 GiB) DRAM. The following error appeared when the driver attempted to allocate a buffer:
sun4i-csi 1c09000.csi: Coherent DMA mask 0x7fffffff (pfn 0x40000-0xc0000)
covers a smaller range of system memory than the DMA zone pfn 0x0-0xc0001
sun4i-csi 1c09000.csi: dma_alloc_coherent of size 307200 failedFixing the off-by-one error makes things work.
---
It's been close to two weeks since I sent this. I wasn't sure if I reached the right maintainers, so I'm resending this to more people.
Changes since v1:
- correct max_pfn offset in the correct place.
--- arch/arm/mm/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mm/dma-mapping.c +1 -1
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(arm_coherent_dma_ops);static int __dma_supported (struct device *dev,u64 mask,bool warn) { -unsigned long max_dma_pfn =min (max_pfn, arm_dma_pfn_limit); +unsigned long max_dma_pfn =min (max_pfn -1 , arm_dma_pfn_limit);/* * Translate the device's DMA mask to a PFN limit. This
Signature · 1 line
2.24.1
Looks good: