From: Dave Hansen <haveblue@us.ibm.com>

When using CONFIG_NONLINEAR, a zone's mem_map isn't contiguous, and isn't
allocated in the same place.  This means that nonlinear doesn't really have
a mem_map[] to pass into free_area_init_node() or memmap_init_zone() which
makes any sense.  

So, this patch removes the 'struct page *mem_map' argument to both of those
functions.  All non-NUMA architectures just pass a NULL in there, which is
ignored.  The solution on the NUMA arches is to pass the mem_map in via the
pgdat, which works just fine.  

To replace the removed arguments, a call to pfn_to_page(node_start_pfn) is
made.  This is valid because all of the pfn_to_page() implementations rely
only on the pgdats, which are already set up at this time.  Plus, the
pfn_to_page() method should work for any future nonlinear-type code.  

Finally, the patch creates a function: node_alloc_mem_map(), which I plan
to effectively #ifdef out for nonlinear at some future date.  

Compile tested and booted on SMP x86, NUMAQ, and ppc64.
DESC
don't pass mem_map into init functions: ia64 fix
EDESC
From: Jesse Barnes <jbarnes@engr.sgi.com>

Fix up ia64 specific memory map init function in light of Dave's
memmap_init cleanups.

Signed-off-by: Jesse Barnes <jbarnes@sgi.com>
DESC
don't pass mem_map into init functions: other architectures
EDESC
From: Dave Hansen <haveblue@us.ibm.com>

Looks like I missed a couple of architectures.  This patch, on top of my
previous one and Jesse's should clean up the rest.
DESC
dont-pass-mem_map-into-init-functions-ia64-fix-2
EDESC
DESC
dont-pass-mem_map-into-init-functions x86_64 fix
EDESC
From: William Lee Irwin III <wli@holomorphy.com>

x86-64 wouldn't compile with NUMA support on, as node_alloc_mem_map()
references mem_map outside #ifdefs on CONFIG_NUMA/CONFIG_DISCONTIGMEM. 
This patch wraps that reference in such an #ifdef.
DESC
dont-pass-mem_map-into-init-functions x86 fix
EDESC
From: William Lee Irwin III <wli@holomorphy.com>

On Mon, Aug 09, 2004 at 01:20:37AM -0700, Rick Lindsley wrote:
> Got complaints from arch/i386/mm/discontig.c:
[...]
> arch/i386/mm/discontig.c:430: warning: passing arg 3 of `free_area_init_node' from incompatible pointer type
> arch/i386/mm/discontig.c:430: warning: passing arg 4 of `free_area_init_node' makes integer from pointer without a cast
> arch/i386/mm/discontig.c:430: warning: passing arg 5 of `free_area_init_node' makes pointer from integer without a cast
> arch/i386/mm/discontig.c:430: too many arguments to function `free_area_init_node'
> Looks like I can't get by with just deleting the third argument in the
> second case.

Initializing NODE_DATA(nid)->node_mem_map prior to calling it should do.
DESC
dont-pass-mem_map-into-init-functions more fixes
EDESC
From: Dave Hansen <haveblue@us.ibm.com>

Rick, I bet you didn't think your nerf weapons would be so effective in
getting that compile error fixed, did you?

Applying the attached patch and commenting out this line:

arch/i386/kernel/nmi.c: In function `proc_unknown_nmi_panic':
arch/i386/kernel/nmi.c:558: too few arguments to function
`proc_dointvec'

will let it compile.  

I'm taking a look at the nmi.c error now, although I think it's
unrelated.

My testing of the original patch was flawed from the beginning because I
never tested them in isolation.  If you haven't already, you should
probably drop them.  I'll rework and make sure to get testing on a wider
variety of arches. 
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/alpha/mm/numa.c             |    2 -
 25-akpm/arch/arm/mm/init.c               |    2 -
 25-akpm/arch/i386/mm/discontig.c         |    8 +++---
 25-akpm/arch/ia64/mm/contig.c            |    5 ++-
 25-akpm/arch/ia64/mm/discontig.c         |    3 --
 25-akpm/arch/ia64/mm/init.c              |   10 ++++---
 25-akpm/arch/mips/sgi-ip27/ip27-memory.c |    2 -
 25-akpm/arch/parisc/mm/init.c            |    2 -
 25-akpm/arch/ppc64/mm/init.c             |    2 -
 25-akpm/arch/sh/mm/init.c                |    2 -
 25-akpm/arch/sparc/mm/srmmu.c            |    2 -
 25-akpm/arch/sparc/mm/sun4c.c            |    2 -
 25-akpm/arch/sparc64/mm/init.c           |    2 -
 25-akpm/arch/x86_64/mm/numa.c            |    2 -
 25-akpm/include/asm-ia64/pgtable.h       |    2 -
 25-akpm/include/linux/mm.h               |    5 +--
 25-akpm/mm/page_alloc.c                  |   41 +++++++++++++++++--------------
 17 files changed, 50 insertions(+), 44 deletions(-)

diff -puN arch/alpha/mm/numa.c~dont-pass-mem_map-into-init-functions arch/alpha/mm/numa.c
--- 25/arch/alpha/mm/numa.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.566626200 -0700
+++ 25-akpm/arch/alpha/mm/numa.c	2004-08-16 23:35:44.862402624 -0700
@@ -313,7 +313,7 @@ void __init paging_init(void)
 			zones_size[ZONE_DMA] = dma_local_pfn;
 			zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
 		}
-		free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn, NULL);
+		free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL);
 	}
 
 	/* Initialize the kernel's ZERO_PGE. */
diff -puN arch/ia64/mm/contig.c~dont-pass-mem_map-into-init-functions arch/ia64/mm/contig.c
--- 25/arch/ia64/mm/contig.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.568625896 -0700
+++ 25-akpm/arch/ia64/mm/contig.c	2004-08-16 23:35:44.863402472 -0700
@@ -267,7 +267,7 @@ paging_init (void)
 	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
 	if (max_gap < LARGE_GAP) {
 		vmem_map = (struct page *) 0;
-		free_area_init_node(0, &contig_page_data, NULL, zones_size, 0,
+		free_area_init_node(0, &contig_page_data, zones_size, 0,
 				    zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	} else {
@@ -280,7 +280,8 @@ paging_init (void)
 		vmem_map = (struct page *) vmalloc_end;
 		efi_memmap_walk(create_mem_map_page_table, 0);
 
-		free_area_init_node(0, &contig_page_data, vmem_map, zones_size,
+		contig_page_data.node_mem_map = vmem_map;
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    0, zholes_size);
 
 		mem_map = contig_page_data.node_mem_map;
diff -puN arch/ia64/mm/init.c~dont-pass-mem_map-into-init-functions arch/ia64/mm/init.c
--- 25/arch/ia64/mm/init.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.569625744 -0700
+++ 25-akpm/arch/ia64/mm/init.c	2004-08-16 23:35:44.865402168 -0700
@@ -429,20 +429,22 @@ virtual_memmap_init (u64 start, u64 end,
 		    / sizeof(struct page));
 
 	if (map_start < map_end)
-		memmap_init_zone(map_start, (unsigned long) (map_end - map_start),
+		memmap_init_zone((unsigned long)(map_end - map_start),
 				 args->nid, args->zone, page_to_pfn(map_start));
 	return 0;
 }
 
 void
-memmap_init (struct page *start, unsigned long size, int nid,
-	     unsigned long zone, unsigned long start_pfn)
+memmap_init (unsigned long size, int nid, unsigned long zone,
+	     unsigned long start_pfn)
 {
 	if (!vmem_map)
-		memmap_init_zone(start, size, nid, zone, start_pfn);
+		memmap_init_zone(size, nid, zone, start_pfn);
 	else {
+		struct page *start;
 		struct memmap_init_callback_data args;
 
+		start = pfn_to_page(start_pfn);
 		args.start = start;
 		args.end = start + size;
 		args.nid = nid;
diff -puN arch/ppc64/mm/init.c~dont-pass-mem_map-into-init-functions arch/ppc64/mm/init.c
--- 25/arch/ppc64/mm/init.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.570625592 -0700
+++ 25-akpm/arch/ppc64/mm/init.c	2004-08-16 23:35:44.868401712 -0700
@@ -587,7 +587,7 @@ void __init paging_init(void)
 	zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 	zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
 
-	free_area_init_node(0, &contig_page_data, NULL, zones_size,
+	free_area_init_node(0, &contig_page_data, zones_size,
 			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 	mem_map = contig_page_data.node_mem_map;
 }
diff -puN arch/sh/mm/init.c~dont-pass-mem_map-into-init-functions arch/sh/mm/init.c
--- 25/arch/sh/mm/init.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.572625288 -0700
+++ 25-akpm/arch/sh/mm/init.c	2004-08-16 23:35:44.868401712 -0700
@@ -225,7 +225,7 @@ void __init paging_init(void)
 	 */
 	zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
 	zones_size[ZONE_NORMAL] = 0;
-	free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
+	free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
 #endif
 }
 
diff -puN include/linux/mm.h~dont-pass-mem_map-into-init-functions include/linux/mm.h
--- 25/include/linux/mm.h~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.573625136 -0700
+++ 25-akpm/include/linux/mm.h	2004-08-16 23:35:44.891398216 -0700
@@ -594,11 +594,10 @@ static inline pmd_t *pmd_alloc(struct mm
 }
 
 extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
+extern void free_area_init_node(int nid, pg_data_t *pgdat,
 	unsigned long * zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size);
-extern void memmap_init_zone(struct page *, unsigned long, int,
-	unsigned long, unsigned long);
+extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
 extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
diff -puN mm/page_alloc.c~dont-pass-mem_map-into-init-functions mm/page_alloc.c
--- 25/mm/page_alloc.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.575624832 -0700
+++ 25-akpm/mm/page_alloc.c	2004-08-16 23:35:44.893397912 -0700
@@ -1385,9 +1385,10 @@ static void __init calculate_zone_totalp
  * up by free_all_bootmem() once the early boot process is
  * done. Non-atomic initialization, single-pass.
  */
-void __init memmap_init_zone(struct page *start, unsigned long size, int nid,
-		unsigned long zone, unsigned long start_pfn)
+void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+		unsigned long start_pfn)
 {
+	struct page *start = pfn_to_page(start_pfn);
 	struct page *page;
 
 	for (page = start; page < (start + size); page++) {
@@ -1451,8 +1452,8 @@ void zone_init_free_lists(struct pglist_
 }
 
 #ifndef __HAVE_ARCH_MEMMAP_INIT
-#define memmap_init(start, size, nid, zone, start_pfn) \
-	memmap_init_zone((start), (size), (nid), (zone), (start_pfn))
+#define memmap_init(size, nid, zone, start_pfn) \
+	memmap_init_zone((size), (nid), (zone), (start_pfn))
 #endif
 
 /*
@@ -1467,7 +1468,6 @@ static void __init free_area_init_core(s
 	unsigned long i, j;
 	const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1);
 	int cpu, nid = pgdat->node_id;
-	struct page *lmem_map = pgdat->node_mem_map;
 	unsigned long zone_start_pfn = pgdat->node_start_pfn;
 
 	pgdat->nr_zones = 0;
@@ -1555,35 +1555,41 @@ static void __init free_area_init_core(s
 
 		pgdat->nr_zones = j+1;
 
-		zone->zone_mem_map = lmem_map;
+		zone->zone_mem_map = pfn_to_page(zone_start_pfn);
 		zone->zone_start_pfn = zone_start_pfn;
 
 		if ((zone_start_pfn) & (zone_required_alignment-1))
 			printk("BUG: wrong zone alignment, it will crash\n");
 
-		memmap_init(lmem_map, size, nid, j, zone_start_pfn);
+		memmap_init(size, nid, j, zone_start_pfn);
 
 		zone_start_pfn += size;
-		lmem_map += size;
 
 		zone_init_free_lists(pgdat, zone, zone->spanned_pages);
 	}
 }
 
-void __init free_area_init_node(int nid, struct pglist_data *pgdat,
-		struct page *node_mem_map, unsigned long *zones_size,
-		unsigned long node_start_pfn, unsigned long *zholes_size)
+void __init node_alloc_mem_map(struct pglist_data *pgdat)
 {
 	unsigned long size;
 
+	size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
+	pgdat->node_mem_map = alloc_bootmem_node(pgdat, size);
+#ifndef CONFIG_DISCONTIGMEM
+	mem_map = contig_page_data.node_mem_map;
+#endif
+}
+
+void __init free_area_init_node(int nid, struct pglist_data *pgdat,
+		unsigned long *zones_size, unsigned long node_start_pfn,
+		unsigned long *zholes_size)
+{
 	pgdat->node_id = nid;
 	pgdat->node_start_pfn = node_start_pfn;
 	calculate_zone_totalpages(pgdat, zones_size, zholes_size);
-	if (!node_mem_map) {
-		size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
-		node_mem_map = alloc_bootmem_node(pgdat, size);
-	}
-	pgdat->node_mem_map = node_mem_map;
+
+	if (!pfn_to_page(node_start_pfn))
+		node_alloc_mem_map(pgdat);
 
 	free_area_init_core(pgdat, zones_size, zholes_size);
 }
@@ -1596,9 +1602,8 @@ EXPORT_SYMBOL(contig_page_data);
 
 void __init free_area_init(unsigned long *zones_size)
 {
-	free_area_init_node(0, &contig_page_data, NULL, zones_size,
+	free_area_init_node(0, &contig_page_data, zones_size,
 			__pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
-	mem_map = contig_page_data.node_mem_map;
 }
 #endif
 
diff -puN include/asm-ia64/pgtable.h~dont-pass-mem_map-into-init-functions include/asm-ia64/pgtable.h
--- 25/include/asm-ia64/pgtable.h~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.576624680 -0700
+++ 25-akpm/include/asm-ia64/pgtable.h	2004-08-16 23:35:44.890398368 -0700
@@ -520,7 +520,7 @@ do {											\
 #  ifdef CONFIG_VIRTUAL_MEM_MAP
   /* arch mem_map init routine is needed due to holes in a virtual mem_map */
 #   define __HAVE_ARCH_MEMMAP_INIT
-    extern void memmap_init (struct page *start, unsigned long size, int nid, unsigned long zone,
+    extern void memmap_init (unsigned long size, int nid, unsigned long zone,
 			     unsigned long start_pfn);
 #  endif /* CONFIG_VIRTUAL_MEM_MAP */
 # endif /* !__ASSEMBLY__ */
diff -puN arch/arm/mm/init.c~dont-pass-mem_map-into-init-functions arch/arm/mm/init.c
--- 25/arch/arm/mm/init.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.578624376 -0700
+++ 25-akpm/arch/arm/mm/init.c	2004-08-16 23:35:44.863402472 -0700
@@ -495,7 +495,7 @@ void __init paging_init(struct meminfo *
 		 */
 		arch_adjust_zones(node, zone_size, zhole_size);
 
-		free_area_init_node(node, pgdat, NULL, zone_size,
+		free_area_init_node(node, pgdat, zone_size,
 				bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
 	}
 
diff -puN arch/mips/sgi-ip27/ip27-memory.c~dont-pass-mem_map-into-init-functions arch/mips/sgi-ip27/ip27-memory.c
--- 25/arch/mips/sgi-ip27/ip27-memory.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.579624224 -0700
+++ 25-akpm/arch/mips/sgi-ip27/ip27-memory.c	2004-08-16 23:35:44.866402016 -0700
@@ -225,7 +225,7 @@ void __init paging_init(void)
 		pfn_t end_pfn = node_getmaxclick(node) + 1;
 
 		zones_size[ZONE_DMA] = end_pfn - start_pfn;
-		free_area_init_node(node, NODE_DATA(node), NULL,
+		free_area_init_node(node, NODE_DATA(node),
 				zones_size, start_pfn, NULL);
 
 		if (end_pfn > max_low_pfn)
diff -puN arch/parisc/mm/init.c~dont-pass-mem_map-into-init-functions arch/parisc/mm/init.c
--- 25/arch/parisc/mm/init.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.580624072 -0700
+++ 25-akpm/arch/parisc/mm/init.c	2004-08-16 23:35:44.867401864 -0700
@@ -804,7 +804,7 @@ void __init paging_init(void)
 		   ZONE_DMA zone. */
 		zones_size[ZONE_DMA] = pmem_ranges[i].pages;
 
-		free_area_init_node(i,NODE_DATA(i),NULL,zones_size,
+		free_area_init_node(i, NODE_DATA(i), zones_size,
 				pmem_ranges[i].start_pfn, 0);
 
 #ifdef CONFIG_DISCONTIGMEM
diff -puN arch/sparc64/mm/init.c~dont-pass-mem_map-into-init-functions arch/sparc64/mm/init.c
--- 25/arch/sparc64/mm/init.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.582623768 -0700
+++ 25-akpm/arch/sparc64/mm/init.c	2004-08-16 23:35:44.880399888 -0700
@@ -1502,7 +1502,7 @@ void __init paging_init(void)
 		zones_size[ZONE_DMA] = npages;
 		zholes_size[ZONE_DMA] = npages - pages_avail;
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    phys_base >> PAGE_SHIFT, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff -puN arch/sparc/mm/srmmu.c~dont-pass-mem_map-into-init-functions arch/sparc/mm/srmmu.c
--- 25/arch/sparc/mm/srmmu.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.583623616 -0700
+++ 25-akpm/arch/sparc/mm/srmmu.c	2004-08-16 23:35:44.887398824 -0700
@@ -1341,7 +1341,7 @@ void __init srmmu_paging_init(void)
 		zones_size[ZONE_HIGHMEM] = npages;
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    pfn_base, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff -puN arch/sparc/mm/sun4c.c~dont-pass-mem_map-into-init-functions arch/sparc/mm/sun4c.c
--- 25/arch/sparc/mm/sun4c.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.585623312 -0700
+++ 25-akpm/arch/sparc/mm/sun4c.c	2004-08-16 23:35:44.889398520 -0700
@@ -2114,7 +2114,7 @@ void __init sun4c_paging_init(void)
 		zones_size[ZONE_HIGHMEM] = npages;
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    pfn_base, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff -puN arch/x86_64/mm/numa.c~dont-pass-mem_map-into-init-functions arch/x86_64/mm/numa.c
--- 25/arch/x86_64/mm/numa.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.586623160 -0700
+++ 25-akpm/arch/x86_64/mm/numa.c	2004-08-16 23:35:44.889398520 -0700
@@ -136,7 +136,7 @@ void __init setup_node_zones(int nodeid)
 		zones[ZONE_NORMAL] = end_pfn - start_pfn; 
 	} 
     
-	free_area_init_node(nodeid, NODE_DATA(nodeid), NULL, zones, 
+	free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
 			    start_pfn, NULL); 
 } 
 
diff -puN arch/ia64/mm/discontig.c~dont-pass-mem_map-into-init-functions arch/ia64/mm/discontig.c
--- 25/arch/ia64/mm/discontig.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.588622856 -0700
+++ 25-akpm/arch/ia64/mm/discontig.c	2004-08-16 23:35:44.864402320 -0700
@@ -665,8 +665,7 @@ void paging_init(void)
 
 		pfn_offset = mem_data[node].min_pfn;
 
-		free_area_init_node(node, NODE_DATA(node),
-				    vmem_map + pfn_offset, zones_size,
+		free_area_init_node(node, NODE_DATA(node), zones_size,
 				    pfn_offset, zholes_size);
 	}
 
diff -puN arch/i386/mm/discontig.c~dont-pass-mem_map-into-init-functions arch/i386/mm/discontig.c
--- 25/arch/i386/mm/discontig.c~dont-pass-mem_map-into-init-functions	2004-08-16 23:33:51.589622704 -0700
+++ 25-akpm/arch/i386/mm/discontig.c	2004-08-16 23:33:51.594621944 -0700
@@ -418,15 +418,15 @@ void __init zone_sizes_init(void)
 		 * remapped KVA area - mbligh
 		 */
 		if (!nid)
-			free_area_init_node(nid, NODE_DATA(nid), 0, 
-				zones_size, start, zholes_size);
+			free_area_init_node(nid, NODE_DATA(nid),
+					zones_size, start, zholes_size);
 		else {
 			unsigned long lmem_map;
 			lmem_map = (unsigned long)node_remap_start_vaddr[nid];
 			lmem_map += sizeof(pg_data_t) + PAGE_SIZE - 1;
 			lmem_map &= PAGE_MASK;
-			free_area_init_node(nid, NODE_DATA(nid), 
-				(struct page *)lmem_map, zones_size, 
+			NODE_DATA(nid)->node_mem_map = (struct page *)lmem_map;
+			free_area_init_node(nid, NODE_DATA(nid), zones_size,
 				start, zholes_size);
 		}
 	}
_