예제 #1
0
static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size,
			phys_addr_t align, phys_addr_t start, phys_addr_t end)
{
	long i;

	BUG_ON(0 == size);

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

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

		if (memblocksize < size)
			continue;
		if ((memblockbase + memblocksize) <= start)
			break;
		bottom = max(memblockbase, start);
		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;
}
예제 #2
0
static phys_addr_t __init memblock_alloc_nid_region(struct memblock_region *mp,
					       phys_addr_t size,
					       phys_addr_t align, int nid)
{
	phys_addr_t start, end;

	start = mp->base;
	end = start + mp->size;

	start = memblock_align_up(start, align);
	while (start < end) {
		phys_addr_t this_end;
		int this_nid;

		this_end = memblock_nid_range(start, end, &this_nid);
		if (this_nid == nid) {
			phys_addr_t ret = memblock_find_region(start, this_end, size, align);
			if (ret != MEMBLOCK_ERROR &&
			    !memblock_add_region(&memblock.reserved, ret, size))
				return ret;
		}
		start = this_end;
	}

	return MEMBLOCK_ERROR;
}
예제 #3
0
phys_addr_t __init memblock_find_in_range_node(phys_addr_t start,
					       phys_addr_t end,
					       phys_addr_t size,
					       phys_addr_t align, int nid)
{
	struct memblock_type *mem = &memblock.memory;
	int i;

	BUG_ON(0 == size);

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

	for (i = mem->cnt - 1; i >= 0; i--) {
		struct memblock_region *r = &mem->regions[i];
		phys_addr_t base = max(start, r->base);
		phys_addr_t top = min(end, r->base + r->size);

		while (base < top) {
			phys_addr_t tbase, ret;
			int tnid;

			tbase = memblock_nid_range_rev(base, top, &tnid);
			if (nid == MAX_NUMNODES || tnid == nid) {
				ret = memblock_find_region(tbase, top, size, align);
				if (ret)
					return ret;
			}
			top = tbase;
		}
	}

	return 0;
}