diff options
Diffstat (limited to 'arch/arm64/mm/init.c')
-rw-r--r-- | arch/arm64/mm/init.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 81bdd29df3a4..d0f86b74fce6 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -68,6 +68,17 @@ static int __init early_initrd(char *p) } early_param("initrd", early_initrd); +/* + * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It + * currently assumes that for memory starting above 4G, 32-bit devices will + * use a DMA offset. + */ +static phys_addr_t max_zone_dma_phys(void) +{ + phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32); + return min(offset + (1ULL << 32), memblock_end_of_DRAM()); +} + static void __init zone_sizes_init(unsigned long min, unsigned long max) { struct memblock_region *reg; @@ -78,9 +89,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) /* 4GB maximum for 32-bit only capable devices */ if (IS_ENABLED(CONFIG_ZONE_DMA)) { - unsigned long max_dma_phys = - (unsigned long)dma_to_phys(NULL, DMA_BIT_MASK(32) + 1); - max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT)); + max_dma = PFN_DOWN(max_zone_dma_phys()); zone_size[ZONE_DMA] = max_dma - min; } zone_size[ZONE_NORMAL] = max - max_dma; @@ -135,6 +144,7 @@ static void arm64_memory_present(void) void __init arm64_memblock_init(void) { u64 *reserve_map, base, size; + phys_addr_t dma_phys_limit = 0; /* * Register the kernel text, kernel data, initrd, and initial @@ -171,7 +181,11 @@ void __init arm64_memblock_init(void) } early_init_fdt_scan_reserved_mem(); - dma_contiguous_reserve(0); + + /* 4GB maximum for 32-bit only capable devices */ + if (IS_ENABLED(CONFIG_ZONE_DMA)) + dma_phys_limit = max_zone_dma_phys(); + dma_contiguous_reserve(dma_phys_limit); memblock_allow_resize(); memblock_dump_all(); |