diff options
-rw-r--r-- | include/linux/memblock.h | 1 | ||||
-rw-r--r-- | mm/memblock.c | 53 |
2 files changed, 39 insertions, 15 deletions
diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 77c60e52939d..9a805ec6e794 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h | |||
@@ -22,6 +22,7 @@ | |||
22 | struct memblock_region { | 22 | struct memblock_region { |
23 | phys_addr_t base; | 23 | phys_addr_t base; |
24 | phys_addr_t size; | 24 | phys_addr_t size; |
25 | unsigned long flags; | ||
25 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 26 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
26 | int nid; | 27 | int nid; |
27 | #endif | 28 | #endif |
diff --git a/mm/memblock.c b/mm/memblock.c index aab566998b61..270b005ca964 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
@@ -255,6 +255,7 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u | |||
255 | type->cnt = 1; | 255 | type->cnt = 1; |
256 | type->regions[0].base = 0; | 256 | type->regions[0].base = 0; |
257 | type->regions[0].size = 0; | 257 | type->regions[0].size = 0; |
258 | type->regions[0].flags = 0; | ||
258 | memblock_set_region_node(&type->regions[0], MAX_NUMNODES); | 259 | memblock_set_region_node(&type->regions[0], MAX_NUMNODES); |
259 | } | 260 | } |
260 | } | 261 | } |
@@ -405,7 +406,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type) | |||
405 | 406 | ||
406 | if (this->base + this->size != next->base || | 407 | if (this->base + this->size != next->base || |
407 | memblock_get_region_node(this) != | 408 | memblock_get_region_node(this) != |
408 | memblock_get_region_node(next)) { | 409 | memblock_get_region_node(next) || |
410 | this->flags != next->flags) { | ||
409 | BUG_ON(this->base + this->size > next->base); | 411 | BUG_ON(this->base + this->size > next->base); |
410 | i++; | 412 | i++; |
411 | continue; | 413 | continue; |
@@ -425,13 +427,15 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type) | |||
425 | * @base: base address of the new region | 427 | * @base: base address of the new region |
426 | * @size: size of the new region | 428 | * @size: size of the new region |
427 | * @nid: node id of the new region | 429 | * @nid: node id of the new region |
430 | * @flags: flags of the new region | ||
428 | * | 431 | * |
429 | * Insert new memblock region [@base,@base+@size) into @type at @idx. | 432 | * Insert new memblock region [@base,@base+@size) into @type at @idx. |
430 | * @type must already have extra room to accomodate the new region. | 433 | * @type must already have extra room to accomodate the new region. |
431 | */ | 434 | */ |
432 | static void __init_memblock memblock_insert_region(struct memblock_type *type, | 435 | static void __init_memblock memblock_insert_region(struct memblock_type *type, |
433 | int idx, phys_addr_t base, | 436 | int idx, phys_addr_t base, |
434 | phys_addr_t size, int nid) | 437 | phys_addr_t size, |
438 | int nid, unsigned long flags) | ||
435 | { | 439 | { |
436 | struct memblock_region *rgn = &type->regions[idx]; | 440 | struct memblock_region *rgn = &type->regions[idx]; |
437 | 441 | ||
@@ -439,6 +443,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type, | |||
439 | memmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn)); | 443 | memmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn)); |
440 | rgn->base = base; | 444 | rgn->base = base; |
441 | rgn->size = size; | 445 | rgn->size = size; |
446 | rgn->flags = flags; | ||
442 | memblock_set_region_node(rgn, nid); | 447 | memblock_set_region_node(rgn, nid); |
443 | type->cnt++; | 448 | type->cnt++; |
444 | type->total_size += size; | 449 | type->total_size += size; |
@@ -450,6 +455,7 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type, | |||
450 | * @base: base address of the new region | 455 | * @base: base address of the new region |
451 | * @size: size of the new region | 456 | * @size: size of the new region |
452 | * @nid: nid of the new region | 457 | * @nid: nid of the new region |
458 | * @flags: flags of the new region | ||
453 | * | 459 | * |
454 | * Add new memblock region [@base,@base+@size) into @type. The new region | 460 | * Add new memblock region [@base,@base+@size) into @type. The new region |
455 | * is allowed to overlap with existing ones - overlaps don't affect already | 461 | * is allowed to overlap with existing ones - overlaps don't affect already |
@@ -460,7 +466,8 @@ static void __init_memblock memblock_insert_region(struct memblock_type *type, | |||
460 | * 0 on success, -errno on failure. | 466 | * 0 on success, -errno on failure. |
461 | */ | 467 | */ |
462 | static int __init_memblock memblock_add_region(struct memblock_type *type, | 468 | static int __init_memblock memblock_add_region(struct memblock_type *type, |
463 | phys_addr_t base, phys_addr_t size, int nid) | 469 | phys_addr_t base, phys_addr_t size, |
470 | int nid, unsigned long flags) | ||
464 | { | 471 | { |
465 | bool insert = false; | 472 | bool insert = false; |
466 | phys_addr_t obase = base; | 473 | phys_addr_t obase = base; |
@@ -475,6 +482,7 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, | |||
475 | WARN_ON(type->cnt != 1 || type->total_size); | 482 | WARN_ON(type->cnt != 1 || type->total_size); |
476 | type->regions[0].base = base; | 483 | type->regions[0].base = base; |
477 | type->regions[0].size = size; | 484 | type->regions[0].size = size; |
485 | type->regions[0].flags = flags; | ||
478 | memblock_set_region_node(&type->regions[0], nid); | 486 | memblock_set_region_node(&type->regions[0], nid); |
479 | type->total_size = size; | 487 | type->total_size = size; |
480 | return 0; | 488 | return 0; |
@@ -505,7 +513,8 @@ repeat: | |||
505 | nr_new++; | 513 | nr_new++; |
506 | if (insert) | 514 | if (insert) |
507 | memblock_insert_region(type, i++, base, | 515 | memblock_insert_region(type, i++, base, |
508 | rbase - base, nid); | 516 | rbase - base, nid, |
517 | flags); | ||
509 | } | 518 | } |
510 | /* area below @rend is dealt with, forget about it */ | 519 | /* area below @rend is dealt with, forget about it */ |
511 | base = min(rend, end); | 520 | base = min(rend, end); |
@@ -515,7 +524,8 @@ repeat: | |||
515 | if (base < end) { | 524 | if (base < end) { |
516 | nr_new++; | 525 | nr_new++; |
517 | if (insert) | 526 | if (insert) |
518 | memblock_insert_region(type, i, base, end - base, nid); | 527 | memblock_insert_region(type, i, base, end - base, |
528 | nid, flags); | ||
519 | } | 529 | } |
520 | 530 | ||
521 | /* | 531 | /* |
@@ -537,12 +547,13 @@ repeat: | |||
537 | int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size, | 547 | int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size, |
538 | int nid) | 548 | int nid) |
539 | { | 549 | { |
540 | return memblock_add_region(&memblock.memory, base, size, nid); | 550 | return memblock_add_region(&memblock.memory, base, size, nid, 0); |
541 | } | 551 | } |
542 | 552 | ||
543 | int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) | 553 | int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) |
544 | { | 554 | { |
545 | return memblock_add_region(&memblock.memory, base, size, MAX_NUMNODES); | 555 | return memblock_add_region(&memblock.memory, base, size, |
556 | MAX_NUMNODES, 0); | ||
546 | } | 557 | } |
547 | 558 | ||
548 | /** | 559 | /** |
@@ -597,7 +608,8 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, | |||
597 | rgn->size -= base - rbase; | 608 | rgn->size -= base - rbase; |
598 | type->total_size -= base - rbase; | 609 | type->total_size -= base - rbase; |
599 | memblock_insert_region(type, i, rbase, base - rbase, | 610 | memblock_insert_region(type, i, rbase, base - rbase, |
600 | memblock_get_region_node(rgn)); | 611 | memblock_get_region_node(rgn), |
612 | rgn->flags); | ||
601 | } else if (rend > end) { | 613 | } else if (rend > end) { |
602 | /* | 614 | /* |
603 | * @rgn intersects from above. Split and redo the | 615 | * @rgn intersects from above. Split and redo the |
@@ -607,7 +619,8 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, | |||
607 | rgn->size -= end - rbase; | 619 | rgn->size -= end - rbase; |
608 | type->total_size -= end - rbase; | 620 | type->total_size -= end - rbase; |
609 | memblock_insert_region(type, i--, rbase, end - rbase, | 621 | memblock_insert_region(type, i--, rbase, end - rbase, |
610 | memblock_get_region_node(rgn)); | 622 | memblock_get_region_node(rgn), |
623 | rgn->flags); | ||
611 | } else { | 624 | } else { |
612 | /* @rgn is fully contained, record it */ | 625 | /* @rgn is fully contained, record it */ |
613 | if (!*end_rgn) | 626 | if (!*end_rgn) |
@@ -649,16 +662,24 @@ int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size) | |||
649 | return __memblock_remove(&memblock.reserved, base, size); | 662 | return __memblock_remove(&memblock.reserved, base, size); |
650 | } | 663 | } |
651 | 664 | ||
652 | int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) | 665 | static int __init_memblock memblock_reserve_region(phys_addr_t base, |
666 | phys_addr_t size, | ||
667 | int nid, | ||
668 | unsigned long flags) | ||
653 | { | 669 | { |
654 | struct memblock_type *_rgn = &memblock.reserved; | 670 | struct memblock_type *_rgn = &memblock.reserved; |
655 | 671 | ||
656 | memblock_dbg("memblock_reserve: [%#016llx-%#016llx] %pF\n", | 672 | memblock_dbg("memblock_reserve: [%#016llx-%#016llx] flags %#02lx %pF\n", |
657 | (unsigned long long)base, | 673 | (unsigned long long)base, |
658 | (unsigned long long)base + size - 1, | 674 | (unsigned long long)base + size - 1, |
659 | (void *)_RET_IP_); | 675 | flags, (void *)_RET_IP_); |
676 | |||
677 | return memblock_add_region(_rgn, base, size, nid, flags); | ||
678 | } | ||
660 | 679 | ||
661 | return memblock_add_region(_rgn, base, size, MAX_NUMNODES); | 680 | int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) |
681 | { | ||
682 | return memblock_reserve_region(base, size, MAX_NUMNODES, 0); | ||
662 | } | 683 | } |
663 | 684 | ||
664 | /** | 685 | /** |
@@ -1101,6 +1122,7 @@ void __init_memblock memblock_set_current_limit(phys_addr_t limit) | |||
1101 | static void __init_memblock memblock_dump(struct memblock_type *type, char *name) | 1122 | static void __init_memblock memblock_dump(struct memblock_type *type, char *name) |
1102 | { | 1123 | { |
1103 | unsigned long long base, size; | 1124 | unsigned long long base, size; |
1125 | unsigned long flags; | ||
1104 | int i; | 1126 | int i; |
1105 | 1127 | ||
1106 | pr_info(" %s.cnt = 0x%lx\n", name, type->cnt); | 1128 | pr_info(" %s.cnt = 0x%lx\n", name, type->cnt); |
@@ -1111,13 +1133,14 @@ static void __init_memblock memblock_dump(struct memblock_type *type, char *name | |||
1111 | 1133 | ||
1112 | base = rgn->base; | 1134 | base = rgn->base; |
1113 | size = rgn->size; | 1135 | size = rgn->size; |
1136 | flags = rgn->flags; | ||
1114 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 1137 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
1115 | if (memblock_get_region_node(rgn) != MAX_NUMNODES) | 1138 | if (memblock_get_region_node(rgn) != MAX_NUMNODES) |
1116 | snprintf(nid_buf, sizeof(nid_buf), " on node %d", | 1139 | snprintf(nid_buf, sizeof(nid_buf), " on node %d", |
1117 | memblock_get_region_node(rgn)); | 1140 | memblock_get_region_node(rgn)); |
1118 | #endif | 1141 | #endif |
1119 | pr_info(" %s[%#x]\t[%#016llx-%#016llx], %#llx bytes%s\n", | 1142 | pr_info(" %s[%#x]\t[%#016llx-%#016llx], %#llx bytes%s flags: %#lx\n", |
1120 | name, i, base, base + size - 1, size, nid_buf); | 1143 | name, i, base, base + size - 1, size, nid_buf, flags); |
1121 | } | 1144 | } |
1122 | } | 1145 | } |
1123 | 1146 | ||