summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2005-09-15 15:17:59 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-09-15 15:17:59 +0100
commit1b3cb73f7306f97a68fa973dec9f3c3b68bd29cf (patch)
treeb88e67dcdce66832980245bcc450233599f857d0 /include
parent13b9d47ed36e8019a99c798b84c341ef75868e02 (diff)
downloadlinux-1b3cb73f7306f97a68fa973dec9f3c3b68bd29cf.tar.gz
[ARM] Tighten pfn_valid() test.
Thomas Gleixner reported that mmaping and unmapping each physical
page in turn eventually caused the kernel to oops.  It appears
that pfn_valid() in the discontigmem case was too simplistic for
proper operation.

Tighten the logic so we also check if the PFN is within the range
of the selected memory node.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'include')
-rw-r--r--include/asm-arm/memory.h15
1 files changed, 14 insertions, 1 deletions
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index e47bea7d1723..a8a933a775db 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -160,12 +160,25 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
 #define page_to_pfn(page)					\
 	(( (page) - page_zone(page)->zone_mem_map)		\
 	  + page_zone(page)->zone_start_pfn)
+
 #define pfn_to_page(pfn)					\
 	(PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT))
-#define pfn_valid(pfn)		(PFN_TO_NID(pfn) < MAX_NUMNODES)
+
+#define pfn_valid(pfn)						\
+	({							\
+		unsigned int nid = PFN_TO_NID(pfn);		\
+		int valid = nid < MAX_NUMNODES;			\
+		if (valid) {					\
+			pg_data_t *node = NODE_DATA(nid);	\
+			valid = (pfn - node->node_start_pfn) <	\
+				node->node_spanned_pages;	\
+		}						\
+		valid;						\
+	})
 
 #define virt_to_page(kaddr)					\
 	(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
+
 #define virt_addr_valid(kaddr)	(KVADDR_TO_NID(kaddr) < MAX_NUMNODES)
 
 /*