| From e81703724a966120ace6504c993bda9e084cbf3e Mon Sep 17 00:00:00 2001 |
| From: Jon Tollefson <kniht@us.ibm.com> |
| Date: Thu, 16 Oct 2008 18:59:43 +0000 |
| Subject: powerpc/numa: Make memory reserve code more robust |
| |
| From: Jon Tollefson <kniht@us.ibm.com> |
| |
| commit e81703724a966120ace6504c993bda9e084cbf3e upstream. |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| arch/powerpc/mm/numa.c | 15 ++++++++++----- |
| 1 file changed, 10 insertions(+), 5 deletions(-) |
| |
| --- a/arch/powerpc/mm/numa.c |
| +++ b/arch/powerpc/mm/numa.c |
| @@ -116,6 +116,7 @@ static int __init get_active_region_work |
| |
| /* |
| * get_node_active_region - Return active region containing start_pfn |
| + * Active range returned is empty if none found. |
| * @start_pfn: The page to return the region for. |
| * @node_ar: Returned set to the active region containing start_pfn |
| */ |
| @@ -126,6 +127,7 @@ static void __init get_node_active_regio |
| |
| node_ar->nid = nid; |
| node_ar->start_pfn = start_pfn; |
| + node_ar->end_pfn = start_pfn; |
| work_with_active_regions(nid, get_active_region_work_fn, node_ar); |
| } |
| |
| @@ -888,18 +890,20 @@ void __init do_init_bootmem(void) |
| struct node_active_region node_ar; |
| |
| get_node_active_region(start_pfn, &node_ar); |
| - while (start_pfn < end_pfn) { |
| + while (start_pfn < end_pfn && |
| + node_ar.start_pfn < node_ar.end_pfn) { |
| + unsigned long reserve_size = size; |
| /* |
| * if reserved region extends past active region |
| * then trim size to active region |
| */ |
| if (end_pfn > node_ar.end_pfn) |
| - size = (node_ar.end_pfn << PAGE_SHIFT) |
| + reserve_size = (node_ar.end_pfn << PAGE_SHIFT) |
| - (start_pfn << PAGE_SHIFT); |
| - dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, size, |
| - node_ar.nid); |
| + dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, |
| + reserve_size, node_ar.nid); |
| reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, |
| - size, BOOTMEM_DEFAULT); |
| + reserve_size, BOOTMEM_DEFAULT); |
| /* |
| * if reserved region is contained in the active region |
| * then done. |
| @@ -914,6 +918,7 @@ void __init do_init_bootmem(void) |
| */ |
| start_pfn = node_ar.end_pfn; |
| physbase = start_pfn << PAGE_SHIFT; |
| + size = size - reserve_size; |
| get_node_active_region(start_pfn, &node_ar); |
| } |
| |