
By: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---

 memhotplug-dave/arch/ppc64/Kconfig         |   17 +++++++++---
 memhotplug-dave/arch/ppc64/mm/Makefile     |    2 -
 memhotplug-dave/arch/ppc64/mm/init.c       |    8 ++---
 memhotplug-dave/arch/ppc64/mm/numa.c       |    5 +++
 memhotplug-dave/include/asm-ppc64/mmzone.h |   40 ++++++++++++++++++++++++-----
 memhotplug-dave/include/asm-ppc64/page.h   |    4 ++
 6 files changed, 60 insertions(+), 16 deletions(-)

diff -puN arch/ppc64/Kconfig~B-sparse-170-sparsemem-ppc64 arch/ppc64/Kconfig
--- memhotplug/arch/ppc64/Kconfig~B-sparse-170-sparsemem-ppc64	2005-03-03 09:05:07.000000000 -0800
+++ memhotplug-dave/arch/ppc64/Kconfig	2005-03-03 09:05:07.000000000 -0800
@@ -196,9 +196,17 @@ config HMT
 	bool "Hardware multithreading"
 	depends on SMP && PPC_PSERIES
 
-config DISCONTIGMEM
-	bool "Discontiguous Memory Support"
-	depends on SMP && PPC_PSERIES
+config ARCH_SPARSEMEM_DEFAULT
+	bool
+	depends on PPC_PSERIES
+
+config ARCH_DISCONTIGMEM_DISABLE
+	bool
+	depends on !SMP || !PPC_PSERIES
+
+config ARCH_SPARSEMEM_DISABLE
+	bool
+	depends on !SMP || !PPC_PSERIES
 
 config HAVE_MEMORY_PRESENT
 	bool
@@ -212,7 +220,8 @@ config NEED_NODE_MEMMAP_SIZE
 
 config NUMA
 	bool "NUMA support"
-	depends on DISCONTIGMEM
+	default y if (DISCONTIGMEM)
+	default y if (SPARSEMEM)
 
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
diff -puN arch/ppc64/mm/Makefile~B-sparse-170-sparsemem-ppc64 arch/ppc64/mm/Makefile
--- memhotplug/arch/ppc64/mm/Makefile~B-sparse-170-sparsemem-ppc64	2005-03-03 09:05:07.000000000 -0800
+++ memhotplug-dave/arch/ppc64/mm/Makefile	2005-03-03 09:05:07.000000000 -0800
@@ -6,6 +6,6 @@ EXTRA_CFLAGS += -mno-minimal-toc
 
 obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
 	slb_low.o slb.o stab.o mmap.o
-obj-$(CONFIG_DISCONTIGMEM) += numa.o
+obj-$(CONFIG_NUMA) += numa.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
diff -puN arch/ppc64/mm/init.c~B-sparse-170-sparsemem-ppc64 arch/ppc64/mm/init.c
--- memhotplug/arch/ppc64/mm/init.c~B-sparse-170-sparsemem-ppc64	2005-03-03 09:05:07.000000000 -0800
+++ memhotplug-dave/arch/ppc64/mm/init.c	2005-03-03 09:05:07.000000000 -0800
@@ -593,7 +593,7 @@ EXPORT_SYMBOL(page_is_ram);
  * Initialize the bootmem system and give it all the memory we
  * have available.
  */
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 void __init do_init_bootmem(void)
 {
 	unsigned long i;
@@ -690,7 +690,7 @@ module_init(setup_kcore);
 
 void __init mem_init(void)
 {
-#ifdef CONFIG_DISCONTIGMEM
+#if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_SPARSEMEM)
 	int nid;
 #endif
 	pg_data_t *pgdat;
@@ -701,7 +701,7 @@ void __init mem_init(void)
 	num_physpages = max_low_pfn;	/* RAM is assumed contiguous */
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
-#ifdef CONFIG_DISCONTIGMEM
+#if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_SPARSEMEM)
         for_each_online_node(nid) {
 		if (NODE_DATA(nid)->node_spanned_pages != 0) {
 			printk("freeing bootmem node %x\n", nid);
@@ -716,7 +716,7 @@ void __init mem_init(void)
 
 	for_each_pgdat(pgdat) {
 		for (i = 0; i < pgdat->node_spanned_pages; i++) {
-			page = pgdat->node_mem_map + i;
+			page = pfn_to_page(i);
 			if (PageReserved(page))
 				reservedpages++;
 		}
diff -puN arch/ppc64/mm/numa.c~B-sparse-170-sparsemem-ppc64 arch/ppc64/mm/numa.c
--- memhotplug/arch/ppc64/mm/numa.c~B-sparse-170-sparsemem-ppc64	2005-03-03 09:05:07.000000000 -0800
+++ memhotplug-dave/arch/ppc64/mm/numa.c	2005-03-03 09:05:07.000000000 -0800
@@ -58,6 +58,10 @@ EXPORT_SYMBOL(numa_memory_lookup_table);
 EXPORT_SYMBOL(numa_cpumask_lookup_table);
 EXPORT_SYMBOL(nr_cpus_in_node);
 
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * SPARSEMEM has its own version of this
+ */
 void memory_present(int nid, unsigned long start_pfn,
 			     unsigned long end_pfn)
 {
@@ -68,6 +72,7 @@ void memory_present(int nid, unsigned lo
 	for (i = start_addr; i < end_addr; i += MEMORY_INCREMENT)
 		numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = nid;
 }
+#endif /* CONFIG_DISCONTIGMEM */
 
 static inline void map_cpu_to_node(int cpu, int node)
 {
diff -puN include/asm-ppc64/mmzone.h~B-sparse-170-sparsemem-ppc64 include/asm-ppc64/mmzone.h
--- memhotplug/include/asm-ppc64/mmzone.h~B-sparse-170-sparsemem-ppc64	2005-03-03 09:05:07.000000000 -0800
+++ memhotplug-dave/include/asm-ppc64/mmzone.h	2005-03-03 09:05:07.000000000 -0800
@@ -10,9 +10,13 @@
 #include <linux/config.h>
 #include <asm/smp.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#if defined(CONFIG_DISCONTIGMEM) || defined(CONFIG_SPARSEMEM)
 
 extern struct pglist_data *node_data[];
+/*
+ * Return a pointer to the node data for node n.
+ */
+#define NODE_DATA(nid)		(node_data[nid])
 
 /*
  * Following are specific to this numa platform.
@@ -27,6 +31,10 @@ extern int nr_cpus_in_node[];
 #define MEMORY_INCREMENT_SHIFT 24
 #define MEMORY_INCREMENT (1UL << MEMORY_INCREMENT_SHIFT)
 
+#endif /* !CONFIG_DISCONTIGMEM || !CONFIG_SPARSEMEM */
+
+#ifdef CONFIG_DISCONTIGMEM
+
 /* NUMA debugging, will not work on a DLPAR machine */
 #undef DEBUG_NUMA
 
@@ -49,11 +57,6 @@ static inline int pa_to_nid(unsigned lon
 
 #define pfn_to_nid(pfn)		pa_to_nid((pfn) << PAGE_SHIFT)
 
-/*
- * Return a pointer to the node data for node n.
- */
-#define NODE_DATA(nid)		(node_data[nid])
-
 #define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
 
 /*
@@ -91,4 +94,29 @@ static inline int pa_to_nid(unsigned lon
 #define discontigmem_pfn_valid(pfn)		((pfn) < num_physpages)
 
 #endif /* CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_SPARSEMEM
+
+/* generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the
+ *    flags field of the struct page
+ */
+
+/*
+ * SECTION_SIZE_BITS		2^N: how big each section will be
+ * MAX_PHYSADDR_BITS		2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS		2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS       24
+#define MAX_PHYSADDR_BITS       38
+#define MAX_PHYSMEM_BITS        36
+
+#define pa_to_nid(pa)							\
+({									\
+	pfn_to_nid(pa >> PAGE_SHIFT);					\
+})
+
+#endif /* CONFIG_SPARSEMEM */
+
 #endif /* _ASM_MMZONE_H_ */
diff -puN include/asm-ppc64/page.h~B-sparse-170-sparsemem-ppc64 include/asm-ppc64/page.h
--- memhotplug/include/asm-ppc64/page.h~B-sparse-170-sparsemem-ppc64	2005-03-03 09:05:07.000000000 -0800
+++ memhotplug-dave/include/asm-ppc64/page.h	2005-03-03 09:05:07.000000000 -0800
@@ -221,7 +221,9 @@ extern u64 ppc64_pft_size;		/* Log 2 of 
 #define page_to_pfn(page)	discontigmem_page_to_pfn(page)
 #define pfn_to_page(pfn)	discontigmem_pfn_to_page(pfn)
 #define pfn_valid(pfn)		discontigmem_pfn_valid(pfn)
-#else
+#endif
+/* XXX/APW: why is SPARSEMEM not here */
+#ifdef CONFIG_FLATMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
_
