diff options
Diffstat (limited to 'mm/bootmem.c')
| -rw-r--r-- | mm/bootmem.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 4af15d0340ad..ad8eec6e44a8 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
| @@ -405,6 +405,29 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size, | |||
| 405 | } | 405 | } |
| 406 | #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ | 406 | #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ |
| 407 | 407 | ||
| 408 | static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, | ||
| 409 | unsigned long step) | ||
| 410 | { | ||
| 411 | unsigned long base = bdata->node_min_pfn; | ||
| 412 | |||
| 413 | /* | ||
| 414 | * Align the index with respect to the node start so that the | ||
| 415 | * combination of both satisfies the requested alignment. | ||
| 416 | */ | ||
| 417 | |||
| 418 | return ALIGN(base + idx, step) - base; | ||
| 419 | } | ||
| 420 | |||
| 421 | static unsigned long align_off(struct bootmem_data *bdata, unsigned long off, | ||
| 422 | unsigned long align) | ||
| 423 | { | ||
| 424 | unsigned long base = PFN_PHYS(bdata->node_min_pfn); | ||
| 425 | |||
| 426 | /* Same as align_idx for byte offsets */ | ||
| 427 | |||
| 428 | return ALIGN(base + off, align) - base; | ||
| 429 | } | ||
| 430 | |||
| 408 | static void * __init alloc_bootmem_core(struct bootmem_data *bdata, | 431 | static void * __init alloc_bootmem_core(struct bootmem_data *bdata, |
| 409 | unsigned long size, unsigned long align, | 432 | unsigned long size, unsigned long align, |
| 410 | unsigned long goal, unsigned long limit) | 433 | unsigned long goal, unsigned long limit) |
| @@ -441,7 +464,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata, | |||
| 441 | else | 464 | else |
| 442 | start = ALIGN(min, step); | 465 | start = ALIGN(min, step); |
| 443 | 466 | ||
| 444 | sidx = start - bdata->node_min_pfn;; | 467 | sidx = start - bdata->node_min_pfn; |
| 445 | midx = max - bdata->node_min_pfn; | 468 | midx = max - bdata->node_min_pfn; |
| 446 | 469 | ||
| 447 | if (bdata->hint_idx > sidx) { | 470 | if (bdata->hint_idx > sidx) { |
| @@ -450,7 +473,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata, | |||
| 450 | * catch the fallback below. | 473 | * catch the fallback below. |
| 451 | */ | 474 | */ |
| 452 | fallback = sidx + 1; | 475 | fallback = sidx + 1; |
| 453 | sidx = ALIGN(bdata->hint_idx, step); | 476 | sidx = align_idx(bdata, bdata->hint_idx, step); |
| 454 | } | 477 | } |
| 455 | 478 | ||
| 456 | while (1) { | 479 | while (1) { |
| @@ -459,7 +482,7 @@ static void * __init alloc_bootmem_core(struct bootmem_data *bdata, | |||
| 459 | unsigned long eidx, i, start_off, end_off; | 482 | unsigned long eidx, i, start_off, end_off; |
| 460 | find_block: | 483 | find_block: |
| 461 | sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx); | 484 | sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx); |
| 462 | sidx = ALIGN(sidx, step); | 485 | sidx = align_idx(bdata, sidx, step); |
| 463 | eidx = sidx + PFN_UP(size); | 486 | eidx = sidx + PFN_UP(size); |
| 464 | 487 | ||
| 465 | if (sidx >= midx || eidx > midx) | 488 | if (sidx >= midx || eidx > midx) |
| @@ -467,15 +490,15 @@ find_block: | |||
| 467 | 490 | ||
| 468 | for (i = sidx; i < eidx; i++) | 491 | for (i = sidx; i < eidx; i++) |
| 469 | if (test_bit(i, bdata->node_bootmem_map)) { | 492 | if (test_bit(i, bdata->node_bootmem_map)) { |
| 470 | sidx = ALIGN(i, step); | 493 | sidx = align_idx(bdata, i, step); |
| 471 | if (sidx == i) | 494 | if (sidx == i) |
| 472 | sidx += step; | 495 | sidx += step; |
| 473 | goto find_block; | 496 | goto find_block; |
| 474 | } | 497 | } |
| 475 | 498 | ||
| 476 | if (bdata->last_end_off && | 499 | if (bdata->last_end_off & (PAGE_SIZE - 1) && |
| 477 | PFN_DOWN(bdata->last_end_off) + 1 == sidx) | 500 | PFN_DOWN(bdata->last_end_off) + 1 == sidx) |
| 478 | start_off = ALIGN(bdata->last_end_off, align); | 501 | start_off = align_off(bdata, bdata->last_end_off, align); |
| 479 | else | 502 | else |
| 480 | start_off = PFN_PHYS(sidx); | 503 | start_off = PFN_PHYS(sidx); |
| 481 | 504 | ||
| @@ -499,7 +522,7 @@ find_block: | |||
| 499 | } | 522 | } |
| 500 | 523 | ||
| 501 | if (fallback) { | 524 | if (fallback) { |
| 502 | sidx = ALIGN(fallback - 1, step); | 525 | sidx = align_idx(bdata, fallback - 1, step); |
| 503 | fallback = 0; | 526 | fallback = 0; |
| 504 | goto find_block; | 527 | goto find_block; |
| 505 | } | 528 | } |
