aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lmb.c')
-rw-r--r--lib/lmb.c86
1 files changed, 76 insertions, 10 deletions
diff --git a/lib/lmb.c b/lib/lmb.c
index 3c43b95fef4a..549fbb3d70cf 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -232,6 +232,82 @@ long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base,
232 return (i < rgn->cnt) ? i : -1; 232 return (i < rgn->cnt) ? i : -1;
233} 233}
234 234
235static u64 lmb_align_down(u64 addr, u64 size)
236{
237 return addr & ~(size - 1);
238}
239
240static u64 lmb_align_up(u64 addr, u64 size)
241{
242 return (addr + (size - 1)) & ~(size - 1);
243}
244
245static u64 __init lmb_alloc_nid_unreserved(u64 start, u64 end,
246 u64 size, u64 align)
247{
248 u64 base;
249 long j;
250
251 base = lmb_align_down((end - size), align);
252 while (start <= base &&
253 ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0))
254 base = lmb_align_down(lmb.reserved.region[j].base - size,
255 align);
256
257 if (base != 0 && start <= base) {
258 if (lmb_add_region(&lmb.reserved, base,
259 lmb_align_up(size, align)) < 0)
260 base = ~(u64)0;
261 return base;
262 }
263
264 return ~(u64)0;
265}
266
267static u64 __init lmb_alloc_nid_region(struct lmb_property *mp,
268 u64 (*nid_range)(u64, u64, int *),
269 u64 size, u64 align, int nid)
270{
271 u64 start, end;
272
273 start = mp->base;
274 end = start + mp->size;
275
276 start = lmb_align_up(start, align);
277 while (start < end) {
278 u64 this_end;
279 int this_nid;
280
281 this_end = nid_range(start, end, &this_nid);
282 if (this_nid == nid) {
283 u64 ret = lmb_alloc_nid_unreserved(start, this_end,
284 size, align);
285 if (ret != ~(u64)0)
286 return ret;
287 }
288 start = this_end;
289 }
290
291 return ~(u64)0;
292}
293
294u64 __init lmb_alloc_nid(u64 size, u64 align, int nid,
295 u64 (*nid_range)(u64 start, u64 end, int *nid))
296{
297 struct lmb_region *mem = &lmb.memory;
298 int i;
299
300 for (i = 0; i < mem->cnt; i++) {
301 u64 ret = lmb_alloc_nid_region(&mem->region[i],
302 nid_range,
303 size, align, nid);
304 if (ret != ~(u64)0)
305 return ret;
306 }
307
308 return lmb_alloc(size, align);
309}
310
235u64 __init lmb_alloc(u64 size, u64 align) 311u64 __init lmb_alloc(u64 size, u64 align)
236{ 312{
237 return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE); 313 return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
@@ -250,16 +326,6 @@ u64 __init lmb_alloc_base(u64 size, u64 align, u64 max_addr)
250 return alloc; 326 return alloc;
251} 327}
252 328
253static u64 lmb_align_down(u64 addr, u64 size)
254{
255 return addr & ~(size - 1);
256}
257
258static u64 lmb_align_up(u64 addr, u64 size)
259{
260 return (addr + (size - 1)) & ~(size - 1);
261}
262
263u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr) 329u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr)
264{ 330{
265 long i, j; 331 long i, j;