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; }
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; }
unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) { long i, j; unsigned long base = 0; BUG_ON(0 == size); #ifdef CONFIG_PPC32 /* On 32-bit, make sure we allocate lowmem */ if (max_addr == LMB_ALLOC_ANYWHERE) max_addr = __max_low_memory; #endif for (i = lmb.memory.cnt-1; i >= 0; i--) { unsigned long lmbbase = lmb.memory.region[i].base; unsigned long lmbsize = lmb.memory.region[i].size; if (max_addr == LMB_ALLOC_ANYWHERE) base = _ALIGN_DOWN(lmbbase + lmbsize - size, align); else if (lmbbase < max_addr) { base = min(lmbbase + lmbsize, max_addr); base = _ALIGN_DOWN(base - size, align); } else continue; while ((lmbbase <= base) && ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0) ) base = _ALIGN_DOWN(lmb.reserved.region[j].base - size, align); if ((base != 0) && (lmbbase <= base)) break; } if (i < 0) return 0; lmb_add_region(&lmb.reserved, base, size); return base; }
static u64 __init lmb_alloc_nid_unreserved(u64 start, u64 end, u64 size, u64 align) { u64 base, res_base; long j; base = lmb_align_down((end - size), align); while (start <= 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) base = ~(u64)0; return base; } res_base = lmb.reserved.region[j].base; if (res_base < size) break; base = lmb_align_down(res_base - size, align); } return ~(u64)0; }
u64 lmb_alloc_base(u64 size, u64 align, u64 max_addr) { long i, j; u64 base = 0; u64 offset = reloc_offset(); struct lmb *_lmb = PTRRELOC(&lmb); struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_rsv = &(_lmb->reserved); for (i=_mem->cnt-1; i >= 0; i--) { u64 lmbbase = _mem->region[i].base; u64 lmbsize = _mem->region[i].size; if ( max_addr == LMB_ALLOC_ANYWHERE ) base = _ALIGN_DOWN(lmbbase+lmbsize-size, align); else if ( lmbbase < max_addr ) base = _ALIGN_DOWN(min(lmbbase+lmbsize,max_addr)-size, align); else continue; while ( (lmbbase <= base) && ((j = lmb_overlaps_region(_rsv,base,size)) >= 0) ) { base = _ALIGN_DOWN(_rsv->region[j].base-size, align); } if ( (base != 0) && (lmbbase <= base) ) break; } if ( i < 0 ) return 0; lmb_add_region(_rsv, base, size); return base; }