aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorTang Chen <tangchen@cn.fujitsu.com>2014-01-21 18:49:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 19:19:44 -0500
commit66a20757214d94b915f2d2aada1384dead9ab18d (patch)
tree2d320737d284ad5febd82d00bbe2807f2da011fe /mm
parent931d13f534a9bb39539f0a851209ca18013ba0c2 (diff)
memblock, numa: introduce flags field into memblock
There is no flag in memblock to describe what type the memory is. Sometimes, we may use memblock to reserve some memory for special usage. And we want to know what kind of memory it is. So we need a way to In hotplug environment, we want to reserve hotpluggable memory so the kernel won't be able to use it. And when the system is up, we have to free these hotpluggable memory to buddy. So we need to mark these memory first. In order to do so, we need to mark out these special memory in memblock. In this patch, we introduce a new "flags" member into memblock_region: struct memblock_region { phys_addr_t base; phys_addr_t size; unsigned long flags; /* This is new. */ #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP int nid; #endif }; This patch does the following things: 1) Add "flags" member to memblock_region. 2) Modify the following APIs' prototype: memblock_add_region() memblock_insert_region() 3) Add memblock_reserve_region() to support reserve memory with flags, and keep memblock_reserve()'s prototype unmodified. 4) Modify other APIs to support flags, but keep their prototype unmodified. The idea is from Wen Congyang <wency@cn.fujitsu.com> and Liu Jiang <jiang.liu@huawei.com>. Suggested-by: Wen Congyang <wency@cn.fujitsu.com> Suggested-by: Liu Jiang <jiang.liu@huawei.com> Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com> Reviewed-by: Zhang Yanfei <zhangyanfei@cn.fujitsu.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: "Rafael J . Wysocki" <rjw@sisk.pl> Cc: Chen Tang <imtangchen@gmail.com> Cc: Gong Chen <gong.chen@linux.intel.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Jiang Liu <jiang.liu@huawei.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Larry Woodman <lwoodman@redhat.com> Cc: Len Brown <lenb@kernel.org> Cc: Mel Gorman <mgorman@suse.de> Cc: Michal Nazarewicz <mina86@mina86.com> Cc: Minchan Kim <minchan@kernel.org> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Rik van Riel <riel@redhat.com> Cc: Taku Izumi <izumi.taku@jp.fujitsu.com> Cc: Tejun Heo <tj@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Thomas Renninger <trenn@suse.de> Cc: Toshi Kani <toshi.kani@hp.com> Cc: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com> Cc: Wanpeng Li <liwanp@linux.vnet.ibm.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/memblock.c53
1 files changed, 38 insertions, 15 deletions
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 */
432static void __init_memblock memblock_insert_region(struct memblock_type *type, 435static 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 */
462static int __init_memblock memblock_add_region(struct memblock_type *type, 468static 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:
537int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size, 547int __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
543int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size) 553int __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
652int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size) 665static 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); 680int __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)
1101static void __init_memblock memblock_dump(struct memblock_type *type, char *name) 1122static 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