Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fef501d4 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

memblock: Add "start" argument to memblock_find_base()



To constraint the search of a region between two boundaries,
which will be used by the new NUMA aware allocator among others.

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent d2cd563b
Loading
Loading
Loading
Loading
+16 −11
Original line number Original line Diff line number Diff line
@@ -117,19 +117,18 @@ static phys_addr_t __init memblock_find_region(phys_addr_t start, phys_addr_t en
	return MEMBLOCK_ERROR;
	return MEMBLOCK_ERROR;
}
}


static phys_addr_t __init memblock_find_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
static phys_addr_t __init memblock_find_base(phys_addr_t size, phys_addr_t align,
					phys_addr_t start, phys_addr_t end)
{
{
	long i;
	long i;
	phys_addr_t base = 0;
	phys_addr_t res_base;


	BUG_ON(0 == size);
	BUG_ON(0 == size);


	size = memblock_align_up(size, align);
	size = memblock_align_up(size, align);


	/* Pump up max_addr */
	/* Pump up max_addr */
	if (max_addr == MEMBLOCK_ALLOC_ACCESSIBLE)
	if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
		max_addr = memblock.current_limit;
		end = memblock.current_limit;


	/* We do a top-down search, this tends to limit memory
	/* We do a top-down search, this tends to limit memory
	 * fragmentation by keeping early boot allocs near the
	 * fragmentation by keeping early boot allocs near the
@@ -138,13 +137,19 @@ static phys_addr_t __init memblock_find_base(phys_addr_t size, phys_addr_t align
	for (i = memblock.memory.cnt - 1; i >= 0; i--) {
	for (i = memblock.memory.cnt - 1; i >= 0; i--) {
		phys_addr_t memblockbase = memblock.memory.regions[i].base;
		phys_addr_t memblockbase = memblock.memory.regions[i].base;
		phys_addr_t memblocksize = memblock.memory.regions[i].size;
		phys_addr_t memblocksize = memblock.memory.regions[i].size;
		phys_addr_t bottom, top, found;


		if (memblocksize < size)
		if (memblocksize < size)
			continue;
			continue;
		base = min(memblockbase + memblocksize, max_addr);
		if ((memblockbase + memblocksize) <= start)
		res_base = memblock_find_region(memblockbase, base, size, align);
			break;
		if (res_base != MEMBLOCK_ERROR)
		bottom = max(memblockbase, start);
			return res_base;
		top = min(memblockbase + memblocksize, end);
		if (bottom >= top)
			continue;
		found = memblock_find_region(bottom, top, size, align);
		if (found != MEMBLOCK_ERROR)
			return found;
	}
	}
	return MEMBLOCK_ERROR;
	return MEMBLOCK_ERROR;
}
}
@@ -204,7 +209,7 @@ static int memblock_double_array(struct memblock_type *type)
		new_array = kmalloc(new_size, GFP_KERNEL);
		new_array = kmalloc(new_size, GFP_KERNEL);
		addr = new_array == NULL ? MEMBLOCK_ERROR : __pa(new_array);
		addr = new_array == NULL ? MEMBLOCK_ERROR : __pa(new_array);
	} else
	} else
		addr = memblock_find_base(new_size, sizeof(phys_addr_t), MEMBLOCK_ALLOC_ACCESSIBLE);
		addr = memblock_find_base(new_size, sizeof(phys_addr_t), 0, MEMBLOCK_ALLOC_ACCESSIBLE);
	if (addr == MEMBLOCK_ERROR) {
	if (addr == MEMBLOCK_ERROR) {
		pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n",
		pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n",
		       memblock_type_name(type), type->max, type->max * 2);
		       memblock_type_name(type), type->max, type->max * 2);
@@ -416,7 +421,7 @@ phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, ph
	 */
	 */
	size = memblock_align_up(size, align);
	size = memblock_align_up(size, align);


	found = memblock_find_base(size, align, max_addr);
	found = memblock_find_base(size, align, 0, max_addr);
	if (found != MEMBLOCK_ERROR &&
	if (found != MEMBLOCK_ERROR &&
	    memblock_add_region(&memblock.reserved, found, size) >= 0)
	    memblock_add_region(&memblock.reserved, found, size) >= 0)
		return found;
		return found;