diff options
author | Jon Tollefson <kniht@us.ibm.com> | 2008-10-16 14:59:43 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-21 00:17:48 -0400 |
commit | e81703724a966120ace6504c993bda9e084cbf3e (patch) | |
tree | 0b0914346bc745cab9e59b9edbe95aa764aa6959 | |
parent | a5598ca0d49821912a5053c05f07fd650671eb6d (diff) |
powerpc/numa: Make memory reserve code more robust
Adjust amount to reserve based on previous nodes for reserves spanning
multiple nodes. Check if the node active range is empty before attempting
to pass the reserve to bootmem. In practice the range shouldn't be empty,
but to be sure we check.
Signed-off-by: Jon Tollefson <kniht@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/mm/numa.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 6cf5c71c431f..195bfcd08959 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -116,6 +116,7 @@ static int __init get_active_region_work_fn(unsigned long start_pfn, | |||
116 | 116 | ||
117 | /* | 117 | /* |
118 | * get_node_active_region - Return active region containing start_pfn | 118 | * get_node_active_region - Return active region containing start_pfn |
119 | * Active range returned is empty if none found. | ||
119 | * @start_pfn: The page to return the region for. | 120 | * @start_pfn: The page to return the region for. |
120 | * @node_ar: Returned set to the active region containing start_pfn | 121 | * @node_ar: Returned set to the active region containing start_pfn |
121 | */ | 122 | */ |
@@ -126,6 +127,7 @@ static void __init get_node_active_region(unsigned long start_pfn, | |||
126 | 127 | ||
127 | node_ar->nid = nid; | 128 | node_ar->nid = nid; |
128 | node_ar->start_pfn = start_pfn; | 129 | node_ar->start_pfn = start_pfn; |
130 | node_ar->end_pfn = start_pfn; | ||
129 | work_with_active_regions(nid, get_active_region_work_fn, node_ar); | 131 | work_with_active_regions(nid, get_active_region_work_fn, node_ar); |
130 | } | 132 | } |
131 | 133 | ||
@@ -933,18 +935,20 @@ void __init do_init_bootmem(void) | |||
933 | struct node_active_region node_ar; | 935 | struct node_active_region node_ar; |
934 | 936 | ||
935 | get_node_active_region(start_pfn, &node_ar); | 937 | get_node_active_region(start_pfn, &node_ar); |
936 | while (start_pfn < end_pfn) { | 938 | while (start_pfn < end_pfn && |
939 | node_ar.start_pfn < node_ar.end_pfn) { | ||
940 | unsigned long reserve_size = size; | ||
937 | /* | 941 | /* |
938 | * if reserved region extends past active region | 942 | * if reserved region extends past active region |
939 | * then trim size to active region | 943 | * then trim size to active region |
940 | */ | 944 | */ |
941 | if (end_pfn > node_ar.end_pfn) | 945 | if (end_pfn > node_ar.end_pfn) |
942 | size = (node_ar.end_pfn << PAGE_SHIFT) | 946 | reserve_size = (node_ar.end_pfn << PAGE_SHIFT) |
943 | - (start_pfn << PAGE_SHIFT); | 947 | - (start_pfn << PAGE_SHIFT); |
944 | dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, size, | 948 | dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, |
945 | node_ar.nid); | 949 | reserve_size, node_ar.nid); |
946 | reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, | 950 | reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, |
947 | size, BOOTMEM_DEFAULT); | 951 | reserve_size, BOOTMEM_DEFAULT); |
948 | /* | 952 | /* |
949 | * if reserved region is contained in the active region | 953 | * if reserved region is contained in the active region |
950 | * then done. | 954 | * then done. |
@@ -959,6 +963,7 @@ void __init do_init_bootmem(void) | |||
959 | */ | 963 | */ |
960 | start_pfn = node_ar.end_pfn; | 964 | start_pfn = node_ar.end_pfn; |
961 | physbase = start_pfn << PAGE_SHIFT; | 965 | physbase = start_pfn << PAGE_SHIFT; |
966 | size = size - reserve_size; | ||
962 | get_node_active_region(start_pfn, &node_ar); | 967 | get_node_active_region(start_pfn, &node_ar); |
963 | } | 968 | } |
964 | 969 | ||