diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 1ab66303b016..bddebe0fdc73 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -377,10 +377,9 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) mdesc->reserve(); /* - * reserve memory for DMA contigouos allocations, - * must come from DMA area inside low memory + * reserve memory for DMA contigouos allocations */ - dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit)); + dma_contiguous_reserve(arm_dma_limit); arm_memblock_steal_permitted = false; memblock_allow_resize(); diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 74f26c910506..3b3a22443023 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -296,6 +296,8 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base, { phys_addr_t base = *res_base; phys_addr_t alignment; + phys_addr_t memblock_end = memblock_end_of_DRAM(); + phys_addr_t highmem_start = __pa(high_memory); int ret = 0; pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__, @@ -311,6 +313,13 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base, if (!size) return -EINVAL; + if (((limit == 0 || limit > memblock_end) && + (memblock_end - size < highmem_start && + memblock_end > highmem_start)) || + (limit > highmem_start && limit - size < highmem_start)) { + limit = highmem_start; + } + /* Sanitise input arguments */ alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); base = ALIGN(base, alignment);