
From: Rusty Russell <rusty@rustcorp.com.au>

Clean up initrd handling.

1) Expose initrd_start and initrd_end to prom.c (replacing its local
   initrd_start and initrd_len).

2) Don't hand mem (aka klimit) through functions which don't need it.

3) Add more debugging under DEBUG_PROM in case we broke anything.


---

 25-akpm/arch/ppc64/kernel/chrp_setup.c |   33 ++------
 25-akpm/arch/ppc64/kernel/process.c    |    3 
 25-akpm/arch/ppc64/kernel/prom.c       |  135 +++++++++++++++++++++++++++------
 25-akpm/arch/ppc64/kernel/setup.c      |   43 ++--------
 25-akpm/arch/ppc64/mm/init.c           |    8 -
 5 files changed, 133 insertions(+), 89 deletions(-)

diff -puN arch/ppc64/kernel/chrp_setup.c~ppc64-initrd-cleanup arch/ppc64/kernel/chrp_setup.c
--- 25/arch/ppc64/kernel/chrp_setup.c~ppc64-initrd-cleanup	Fri Apr 23 13:30:27 2004
+++ 25-akpm/arch/ppc64/kernel/chrp_setup.c	Fri Apr 23 13:30:27 2004
@@ -31,7 +31,6 @@
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
-#include <linux/initrd.h>
 #include <linux/ioport.h>
 #include <linux/console.h>
 #include <linux/pci.h>
@@ -136,15 +135,10 @@ chrp_setup_arch(void)
 	/* init to some ~sane value until calibrate_delay() runs */
 	loops_per_jiffy = 50000000;
 
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* this is fine for chrp */
-	initrd_below_start_ok = 1;
-	
-	if (initrd_start)
-		ROOT_DEV = Root_RAM0;
-	else
-#endif
-	ROOT_DEV = Root_SDA2;
+	if (ROOT_DEV == 0) {
+		printk("No ramdisk, default root is /dev/sda2\n");
+		ROOT_DEV = Root_SDA2;
+	}
 
 	printk("Boot arguments: %s\n", cmd_line);
 
@@ -239,17 +233,6 @@ chrp_init(unsigned long r3, unsigned lon
 	char * hypertas;
 	unsigned int len;
 
-#if 0 /* PPPBBB remove this later... -Peter */
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* take care of initrd if we have one */
-	if ( r6 )
-	{
-		initrd_start = __va(r6);
-		initrd_end = __va(r6 + r7);
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-#endif
-
 	ppc_md.setup_arch     = chrp_setup_arch;
 	ppc_md.get_cpuinfo    = chrp_get_cpuinfo;
 	if (naca->interrupt_controller == IC_OPEN_PIC) {
@@ -280,8 +263,13 @@ chrp_init(unsigned long r3, unsigned lon
          * using contents of device-tree/ibm,hypertas-functions.
          * Ultimately this functionality may be moved into prom.c prom_init().
          */
-	dn = of_find_node_by_path("/rtas");
 	cur_cpu_spec->firmware_features = 0;
+	dn = of_find_node_by_path("/rtas");
+	if (dn == NULL) {
+		printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
+		goto no_rtas;
+	}
+
 	hypertas = get_property(dn, "ibm,hypertas-functions", &len);
 	if (hypertas) {
 		while (len > 0){
@@ -303,6 +291,7 @@ chrp_init(unsigned long r3, unsigned lon
 	}
 
 	of_node_put(dn);
+ no_rtas:
 	printk(KERN_INFO "firmware_features = 0x%lx\n", 
 	       cur_cpu_spec->firmware_features);
 }
diff -puN arch/ppc64/kernel/process.c~ppc64-initrd-cleanup arch/ppc64/kernel/process.c
--- 25/arch/ppc64/kernel/process.c~ppc64-initrd-cleanup	Fri Apr 23 13:30:27 2004
+++ 25-akpm/arch/ppc64/kernel/process.c	Fri Apr 23 13:30:27 2004
@@ -65,9 +65,6 @@ struct mm_struct ioremap_mm = {
 	.page_table_lock = SPIN_LOCK_UNLOCKED,
 };
 
-char *sysmap = NULL;
-unsigned long sysmap_size = 0;
-
 void enable_kernel_fp(void)
 {
 #ifdef CONFIG_SMP
diff -puN arch/ppc64/kernel/prom.c~ppc64-initrd-cleanup arch/ppc64/kernel/prom.c
--- 25/arch/ppc64/kernel/prom.c~ppc64-initrd-cleanup	Fri Apr 23 13:30:27 2004
+++ 25-akpm/arch/ppc64/kernel/prom.c	Fri Apr 23 13:30:27 2004
@@ -32,6 +32,7 @@
 #include <linux/proc_fs.h>
 #include <linux/stringify.h>
 #include <linux/delay.h>
+#include <linux/initrd.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/lmb.h>
@@ -137,6 +138,9 @@ phandle prom_display_nodes[FB_MAX] __ini
 unsigned int prom_num_displays = 0;
 char *of_stdout_device = 0;
 
+static int iommu_force_on;
+int ppc64_iommu_off;
+
 extern struct rtas_t rtas;
 extern unsigned long klimit;
 extern struct lmb lmb;
@@ -162,8 +166,6 @@ extern void enter_prom(struct prom_args 
 extern void copy_and_flush(unsigned long dest, unsigned long src,
 			   unsigned long size, unsigned long offset);
 
-static unsigned long __initdata initrd_start /* = 0 */, initrd_len;
-
 unsigned long dev_tree_size;
 unsigned long _get_PIR(void);
 
@@ -288,8 +290,8 @@ static int __init prom_next_node(phandle
 	}
 }
 
-static unsigned long
-prom_initialize_naca(unsigned long mem)
+
+static void __init prom_initialize_naca(void)
 {
 	phandle node;
 	char type[64];
@@ -504,12 +506,8 @@ prom_initialize_naca(unsigned long mem)
 
 	prom_print(RELOC("prom_initialize_naca: end...\n"));
 #endif
-
-	return mem;
 }
 
-static int iommu_force_on;
-int ppc64_iommu_off;
 
 static void __init early_cmdline_parse(void)
 {
@@ -592,8 +590,7 @@ void prom_dump_lmb(void)
 }
 #endif /* DEBUG_PROM */
 
-static unsigned long __init
-prom_initialize_lmb(unsigned long mem)
+static void __init prom_initialize_lmb(void)
 {
 	phandle node;
 	char type[64];
@@ -655,8 +652,6 @@ prom_initialize_lmb(unsigned long mem)
 #ifdef DEBUG_PROM
 	prom_dump_lmb();
 #endif /* DEBUG_PROM */
-
-	return mem;
 }
 
 static char hypertas_funcs[1024];
@@ -1555,7 +1550,7 @@ static void __init *__make_room(unsigned
 	if (*mem_start + needed > *mem_end) {
 		if (*mem_end != RELOC(initrd_start))
 			prom_panic(RELOC("No memory for copy_device_tree"));
-		*mem_start = RELOC(initrd_start) + RELOC(initrd_len);
+		*mem_start = RELOC(initrd_end);
 		/* We can't pass huge values to OF, so use 1G. */
 		*mem_end = *mem_start + 1024*1024*1024;
 	}
@@ -1714,22 +1709,52 @@ copy_device_tree(unsigned long mem_start
 static struct bi_record * __init prom_bi_rec_verify(struct bi_record *bi_recs)
 {
 	struct bi_record *first, *last;
+#ifdef DEBUG_PROM
+	unsigned long offset = reloc_offset();
+
+  	prom_print(RELOC("birec_verify: r6=0x"));
+  	prom_print_hex((unsigned long)bi_recs);
+  	prom_print_nl();
+	if (bi_recs != NULL) {
+		prom_print(RELOC("  tag=0x"));
+		prom_print_hex(bi_recs->tag);
+		prom_print_nl();
+	}
+#endif /* DEBUG_PROM */
 
 	if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
 		return NULL;
 
 	last = (struct bi_record *)(long)bi_recs->data[0];
+
+#ifdef DEBUG_PROM
+  	prom_print(RELOC("  last=0x"));
+  	prom_print_hex((unsigned long)last);
+  	prom_print_nl();
+	if (last != NULL) {
+		prom_print(RELOC("  last_tag=0x"));
+		prom_print_hex(last->tag);
+		prom_print_nl();
+	}
+#endif /* DEBUG_PROM */
+
 	if ( last == NULL || last->tag != BI_LAST )
 		return NULL;
 
 	first = (struct bi_record *)(long)last->data[0];
+#ifdef DEBUG_PROM
+  	prom_print(RELOC("  first=0x"));
+  	prom_print_hex((unsigned long)first);
+  	prom_print_nl();
+#endif /* DEBUG_PROM */
+
 	if ( first == NULL || first != bi_recs )
 		return NULL;
 
 	return bi_recs;
 }
 
-static unsigned long __init prom_bi_rec_reserve(unsigned long mem)
+static void __init prom_bi_rec_reserve(void)
 {
 	unsigned long offset = reloc_offset();
 	struct prom_t *_prom = PTRRELOC(&prom);
@@ -1740,11 +1765,16 @@ static unsigned long __init prom_bi_rec_
 		for ( rec=_prom->bi_recs;
 		      rec->tag != BI_LAST;
 		      rec=bi_rec_next(rec) ) {
+#ifdef DEBUG_PROM
+			prom_print(RELOC("bi: 0x"));
+			prom_print_hex(rec->tag);
+			prom_print_nl();
+#endif /* DEBUG_PROM */
 			switch (rec->tag) {
 #ifdef CONFIG_BLK_DEV_INITRD
 			case BI_INITRD:
-				RELOC(initrd_start) = rec->data[0];
-				RELOC(initrd_len) = rec->data[1];
+				RELOC(initrd_start) = (unsigned long)(rec->data[0]);
+				RELOC(initrd_end) = RELOC(initrd_start) + rec->data[1];
 				break;
 #endif /* CONFIG_BLK_DEV_INITRD */
 			}
@@ -1755,8 +1785,6 @@ static unsigned long __init prom_bi_rec_
 	 	 */
 		_prom->bi_recs = PTRUNRELOC(_prom->bi_recs);
 	}
-
-	return mem;
 }
 
 /*
@@ -1794,11 +1822,43 @@ prom_init(unsigned long r3, unsigned lon
 	/* Init prom stdout device */
 	prom_init_stdout();
 
+#ifdef DEBUG_PROM
+  	prom_print(RELOC("klimit=0x"));
+  	prom_print_hex(RELOC(klimit));
+  	prom_print_nl();
+  	prom_print(RELOC("offset=0x"));
+  	prom_print_hex(offset);
+  	prom_print_nl();
+  	prom_print(RELOC("->mem=0x"));
+  	prom_print_hex(RELOC(klimit) - offset);
+  	prom_print_nl();
+#endif /* DEBUG_PROM */
+
 	/* check out if we have bi_recs */
 	_prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);
-	if ( _prom->bi_recs != NULL )
+	if ( _prom->bi_recs != NULL ) {
 		RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs +
 					   _prom->bi_recs->data[1]);
+#ifdef DEBUG_PROM
+		prom_print(RELOC("bi_recs=0x"));
+		prom_print_hex((unsigned long)_prom->bi_recs);
+		prom_print_nl();
+		prom_print(RELOC("new mem=0x"));
+		prom_print_hex(RELOC(klimit) - offset);
+		prom_print_nl();
+#endif /* DEBUG_PROM */
+	}
+
+	/* If we don't have birec's or didn't find them, check for an initrd
+	 * using the "yaboot" way
+	 */
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( _prom->bi_recs == NULL && r3 && r4 && r4 != 0xdeadbeef) {
+		RELOC(initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
+		RELOC(initrd_end) = RELOC(initrd_start) + r4;
+		RELOC(initrd_below_start_ok) = 1;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
 
 	/* Default machine type. */
 	_systemcfg->platform = prom_find_machine_type();
@@ -1870,9 +1930,9 @@ prom_init(unsigned long r3, unsigned lon
 
 	early_cmdline_parse();
 
-	mem = prom_initialize_lmb(mem);
+	prom_initialize_lmb();
 
-	mem = prom_bi_rec_reserve(mem);
+	prom_bi_rec_reserve();
 
 	mem = check_display(mem);
 
@@ -1880,7 +1940,7 @@ prom_init(unsigned long r3, unsigned lon
 		prom_instantiate_rtas();
 
         /* Initialize some system info into the Naca early... */
-        mem = prom_initialize_naca(mem);
+        prom_initialize_naca();
 
 	smt_setup();
 
@@ -1891,17 +1951,36 @@ prom_init(unsigned long r3, unsigned lon
 	prom_hold_cpus(mem);
 
 #ifdef DEBUG_PROM
+  	prom_print(RELOC("after basic inits, mem=0x"));
+  	prom_print_hex(mem);
+  	prom_print_nl();
+	prom_print(RELOC("initrd_start=0x"));
+	prom_print_hex(RELOC(initrd_start));
+	prom_print_nl();
+	prom_print(RELOC("initrd_end=0x"));
+	prom_print_hex(RELOC(initrd_end));
+	prom_print_nl();
 	prom_print(RELOC("copying OF device tree...\n"));
-#endif
+#endif /* DEBUG_PROM */
 	mem = copy_device_tree(mem);
 
 	RELOC(klimit) = mem + offset;
 
+#ifdef DEBUG_PROM
+	prom_print(RELOC("new klimit is\n"));
+  	prom_print(RELOC("klimit=0x"));
+  	prom_print_hex(RELOC(klimit));
+	prom_print(RELOC(" ->mem=0x\n"));
+  	prom_print(RELOC("klimit=0x"));
+  	prom_print_hex(mem);
+  	prom_print_nl();
+#endif /* DEBUG_PROM */
+
 	lmb_reserve(0, __pa(RELOC(klimit)));
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* If this didn't cover the initrd, do so now */
 	if (mem < RELOC(initrd_start))
-		lmb_reserve(RELOC(initrd_start), RELOC(initrd_len));
+		lmb_reserve(RELOC(initrd_start), RELOC(initrd_end) - RELOC(initrd_start));
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 	if (_systemcfg->platform == PLATFORM_PSERIES)
@@ -1923,6 +2002,14 @@ prom_init(unsigned long r3, unsigned lon
 	call_prom(RELOC("quiesce"), 0, 0);
 	phys = KERNELBASE - offset;
 
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* If we had an initrd, we convert its address to virtual */
+	if (RELOC(initrd_start)) {
+		RELOC(initrd_start) = (unsigned long)__va(RELOC(initrd_start));
+		RELOC(initrd_end) = (unsigned long)__va(RELOC(initrd_end));
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
 	prom_print(RELOC("returning from prom_init\n"));
 	return phys;
 }
diff -puN arch/ppc64/kernel/setup.c~ppc64-initrd-cleanup arch/ppc64/kernel/setup.c
--- 25/arch/ppc64/kernel/setup.c~ppc64-initrd-cleanup	Fri Apr 23 13:30:27 2004
+++ 25-akpm/arch/ppc64/kernel/setup.c	Fri Apr 23 13:30:27 2004
@@ -188,30 +188,32 @@ void setup_system(unsigned long r3, unsi
 #ifdef CONFIG_PPC_PSERIES
 	case PLATFORM_PSERIES:
 		pSeries_init_early();
-#ifdef CONFIG_BLK_DEV_INITRD
-		initrd_start = initrd_end = 0;
-#endif
 		parse_bootinfo();
 		break;
 
 	case PLATFORM_PSERIES_LPAR:
 		pSeriesLP_init_early();
-#ifdef CONFIG_BLK_DEV_INITRD
-		initrd_start = initrd_end = 0;
-#endif
 		parse_bootinfo();
 		break;
 #endif /* CONFIG_PPC_PSERIES */
 #ifdef CONFIG_PPC_PMAC
 	case PLATFORM_POWERMAC:
 		pmac_init_early();
-#ifdef CONFIG_BLK_DEV_INITRD
-		initrd_start = initrd_end = 0;
-#endif
 		parse_bootinfo();
 #endif /* CONFIG_PPC_PMAC */
 	}
 
+	/* If we were passed an initrd, set the ROOT_DEV properly if the values
+	 * look sensible. If not, clear initrd reference.
+	 */
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
+	    initrd_end > initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+		initrd_start = initrd_end = 0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
 #ifdef CONFIG_BOOTX_TEXT
 	map_boot_text();
 	if (systemcfg->platform == PLATFORM_POWERMAC) {
@@ -425,15 +427,6 @@ struct seq_operations cpuinfo_op = {
 void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
 		  unsigned long r6, unsigned long r7)
 {
-#ifdef CONFIG_BLK_DEV_INITRD
-	if ((initrd_start == 0) && r3 && r4 && r4 != 0xdeadbeef) {
-		initrd_start = (r3 >= KERNELBASE) ? r3 : (unsigned long)__va(r3);
-		initrd_end = initrd_start + r4;
-		ROOT_DEV = Root_RAM0;
-		initrd_below_start_ok = 1;
-	}
-#endif
-
 	cmd_line[0] = 0;
 
 #ifdef CONFIG_CMDLINE
@@ -533,8 +526,6 @@ console_initcall(set_preferred_console);
 int parse_bootinfo(void)
 {
 	struct bi_record *rec;
-	extern char *sysmap;
-	extern unsigned long sysmap_size;
 
 	rec = prom.bi_recs;
 
@@ -546,18 +537,6 @@ int parse_bootinfo(void)
 		case BI_CMD_LINE:
 			strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
 			break;
-		case BI_SYSMAP:
-			sysmap = __va(rec->data[0]);
-			sysmap_size = rec->data[1];
-			break;
-#ifdef CONFIG_BLK_DEV_INITRD
-		case BI_INITRD:
-			initrd_start = (unsigned long)__va(rec->data[0]);
-			initrd_end = initrd_start + rec->data[1];
-			ROOT_DEV = Root_RAM0;
-			initrd_below_start_ok = 1;
-			break;
-#endif /* CONFIG_BLK_DEV_INITRD */
 		}
 	}
 
diff -puN arch/ppc64/mm/init.c~ppc64-initrd-cleanup arch/ppc64/mm/init.c
--- 25/arch/ppc64/mm/init.c~ppc64-initrd-cleanup	Fri Apr 23 13:30:27 2004
+++ 25-akpm/arch/ppc64/mm/init.c	Fri Apr 23 13:30:27 2004
@@ -621,8 +621,6 @@ module_init(setup_kcore);
 void __init mem_init(void)
 {
 #ifndef CONFIG_DISCONTIGMEM
-	extern char *sysmap; 
-	extern unsigned long sysmap_size;
 	unsigned long addr;
 #endif
 	int codepages = 0;
@@ -656,12 +654,6 @@ void __init mem_init(void)
 
 	totalram_pages += free_all_bootmem();
 
-	if ( sysmap_size )
-		for (addr = (unsigned long)sysmap;
-		     addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
-		     addr += PAGE_SIZE)
-			SetPageReserved(virt_to_page(addr));
-	
 	for (addr = KERNELBASE; addr <= (unsigned long)__va(lmb_end_of_DRAM());
 	     addr += PAGE_SIZE) {
 		if (!PageReserved(virt_to_page(addr)))

_
