[tip:x86/memblock] memblock: Improve generic memblock_nid_range() using for_each_mem_pfn_range()

From: tip-bot for Tejun Heo
Date: Thu Jul 14 2011 - 17:29:37 EST


Commit-ID: b2fea988f4f3b38ff4edfc1556a843c91932804c
Gitweb: http://git.kernel.org/tip/b2fea988f4f3b38ff4edfc1556a843c91932804c
Author: Tejun Heo <tj@xxxxxxxxxx>
AuthorDate: Tue, 12 Jul 2011 10:46:31 +0200
Committer: H. Peter Anvin <hpa@xxxxxxxxxxxxxxx>
CommitDate: Thu, 14 Jul 2011 11:45:32 -0700

memblock: Improve generic memblock_nid_range() using for_each_mem_pfn_range()

Given an address range, memblock_nid_range() determines the node the
start of the range belongs to and upto where the range stays in the
same node.

It's implemented by calling get_pfn_range_for_nid(), which determines
min and max pfns for a given node, for each node and testing whether
start address falls in there. This is not only inefficient but also
incorrect when nodes interleave as min-max ranges for nodes overlap.

This patch reimplements memblock_nid_range() using
for_each_mem_pfn_range(). It's simpler, walks the mem ranges once and
can find the exact range the start address falls in.

Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
Link: http://lkml.kernel.org/r/1310460395-30913-5-git-send-email-tj@xxxxxxxxxx
Cc: Yinghai Lu <yinghai@xxxxxxxxxx>
Cc: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: H. Peter Anvin <hpa@xxxxxxxxxxxxxxx>
---
mm/memblock.c | 20 +++-----------------
1 files changed, 3 insertions(+), 17 deletions(-)

diff --git a/mm/memblock.c b/mm/memblock.c
index 0f9626f..97f3486 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -511,28 +511,14 @@ phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
phys_addr_t __weak __init memblock_nid_range(phys_addr_t start, phys_addr_t end, int *nid)
{
#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
- /*
- * This code originates from sparc which really wants use to walk by addresses
- * and returns the nid. This is not very convenient for early_pfn_map[] users
- * as the map isn't sorted yet, and it really wants to be walked by nid.
- *
- * For now, I implement the inefficient method below which walks the early
- * map multiple times. Eventually we may want to use an ARCH config option
- * to implement a completely different method for both case.
- */
unsigned long start_pfn, end_pfn;
int i;

- for (i = 0; i < MAX_NUMNODES; i++) {
- get_pfn_range_for_nid(i, &start_pfn, &end_pfn);
- if (start < PFN_PHYS(start_pfn) || start >= PFN_PHYS(end_pfn))
- continue;
- *nid = i;
- return min(end, PFN_PHYS(end_pfn));
- }
+ for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, nid)
+ if (start >= PFN_PHYS(start_pfn) && start < PFN_PHYS(end_pfn))
+ return min(end, PFN_PHYS(end_pfn));
#endif
*nid = 0;
-
return end;
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/