static u64 __init lmb_alloc_nid_region(struct lmb_property *mp, u64 (*nid_range)(u64, u64, int *), u64 size, u64 align, int nid) { u64 start, end; start = mp->base; end = start + mp->size; start = lmb_align_up(start, align); while (start < end) { u64 this_end; int this_nid; this_end = nid_range(start, end, &this_nid); if (this_nid == nid) { u64 ret = lmb_alloc_nid_unreserved(start, this_end, size, align); if (ret != ~(u64)0) return ret; } start = this_end; } return ~(u64)0; }
u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr) { long i, j; u64 base = 0; u64 res_base; BUG_ON(0 == size); size = lmb_align_up(size, align); /* On some platforms, make sure we allocate lowmem */ /* Note that LMB_REAL_LIMIT may be LMB_ALLOC_ANYWHERE */ if (max_addr == LMB_ALLOC_ANYWHERE) max_addr = LMB_REAL_LIMIT; for (i = lmb.memory.cnt - 1; i >= 0; i--) { u64 lmbbase = lmb.memory.region[i].base; u64 lmbsize = lmb.memory.region[i].size; if (lmbsize < size) continue; if (max_addr == LMB_ALLOC_ANYWHERE) base = lmb_align_down(lmbbase + lmbsize - size, align); else if (lmbbase < max_addr) { base = min(lmbbase + lmbsize, max_addr); base = lmb_align_down(base - size, align); } else continue; while (base && lmbbase <= base) { j = lmb_overlaps_region(&lmb.reserved, base, size); if (j < 0) { /* this area isn't reserved, take it */ if (lmb_add_region(&lmb.reserved, base, size) < 0) return 0; return base; } res_base = lmb.reserved.region[j].base; if (res_base < size) break; base = lmb_align_down(res_base - size, align); } } return 0; }
u64 __init lmb_alloc_nid(u64 size, u64 align, int nid, u64 (*nid_range)(u64 start, u64 end, int *nid)) { struct lmb_region *mem = &lmb.memory; int i; BUG_ON(0 == size); size = lmb_align_up(size, align); for (i = 0; i < mem->cnt; i++) { u64 ret = lmb_alloc_nid_region(&mem->region[i], nid_range, size, align, nid); if (ret != ~(u64)0) return ret; } return lmb_alloc(size, align); }
phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr) { long i, j; phys_addr_t base = 0; phys_addr_t res_base; for (i = lmb->memory.cnt-1; i >= 0; i--) { phys_addr_t lmbbase = lmb->memory.region[i].base; phys_size_t lmbsize = lmb->memory.region[i].size; if (lmbsize < size) continue; if (max_addr == LMB_ALLOC_ANYWHERE) base = lmb_align_down(lmbbase + lmbsize - size, align); else if (lmbbase < max_addr) { base = lmbbase + lmbsize; if (base < lmbbase) base = -1; base = min(base, max_addr); base = lmb_align_down(base - size, align); } else continue; while (base && lmbbase <= base) { j = lmb_overlaps_region(&lmb->reserved, base, size); if (j < 0) { /* This area isn't reserved, take it */ if (lmb_add_region(&lmb->reserved, base, lmb_align_up(size, align)) < 0) return 0; return base; } res_base = lmb->reserved.region[j].base; if (res_base < size) break; base = lmb_align_down(res_base - size, align); } } return 0; }