patch-2.4.23 linux-2.4.23/arch/ia64/kernel/setup.c

Next file: linux-2.4.23/arch/ia64/kernel/signal.c
Previous file: linux-2.4.23/arch/ia64/kernel/salinfo.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/arch/ia64/kernel/setup.c linux-2.4.23/arch/ia64/kernel/setup.c
@@ -32,6 +32,10 @@
 #include <linux/ioport.h>
 #include <linux/efi.h>
 
+#ifdef CONFIG_BLK_DEV_RAM
+# include <linux/blk.h>
+#endif
+
 #include <asm/ia32.h>
 #include <asm/page.h>
 #include <asm/machvec.h>
@@ -39,6 +43,8 @@
 #include <asm/sal.h>
 #include <asm/system.h>
 #include <asm/mca.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 #include <asm/smp.h>
 
 #ifdef CONFIG_BLK_DEV_RAM
@@ -55,7 +61,7 @@
 extern char _end;
 
 #ifdef CONFIG_NUMA
- struct cpuinfo_ia64 *boot_cpu_data;
+ struct cpuinfo_ia64 *_cpu_data[NR_CPUS];
 #else
  struct cpuinfo_ia64 _cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section")));
 #endif
@@ -97,6 +103,7 @@
 static struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
 static int num_rsvd_regions;
 
+#ifndef CONFIG_DISCONTIGMEM
 static unsigned long bootmap_start; /* physical address where the bootmem map is located */
 
 static int
@@ -109,18 +116,74 @@
 		*max_pfn = pfn;
 	return 0;
 }
+#endif /* !CONFIG_DISCONTIGMEM */
 
 #define IGNORE_PFN0	1	/* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
 
+#ifdef CONFIG_DISCONTIGMEM
 /*
- * Free available memory based on the primitive map created from
- * the boot parameters. This routine does not assume the incoming
- * segments are sorted.
+ * efi_memmap_walk() knows nothing about layout of memory across nodes. Find
+ * out to which node a block of memory belongs.  Ignore memory that we cannot
+ * identify, and split blocks that run across multiple nodes.
+ *
+ * Take this opportunity to round the start address up and the end address
+ * down to page boundaries.
  */
+void
+call_pernode_memory (unsigned long start, unsigned long end, void *arg)
+{
+	unsigned long rs, re;
+	void (*func)(unsigned long, unsigned long, int);
+	int i;
+
+	start = PAGE_ALIGN(start);
+	end &= PAGE_MASK;
+	if (start >= end)
+		return;
+
+	func = arg;
+
+	if (!num_memblks) {
+		/* this machine doesn't have SRAT, */
+		/* so call func with nid=0, bank=0 */
+		if (start < end)
+			(*func)(start, end, 0);
+		return;
+	}
+
+	for (i = 0; i < num_memblks; i++) {
+		rs = MAX(__pa(start), node_memblk[i].start_paddr);
+		re = MIN(__pa(end), node_memblk[i].start_paddr+node_memblk[i].size);
+
+		if (rs < re)
+			(*func)((unsigned long)__va(rs), (unsigned long)__va(re), node_memblk[i].nid);
+		if ((unsigned long)__va(re) == end)
+			break;
+	}
+}
+
+#else /* CONFIG_DISCONTIGMEM */
+
 static int
 free_available_memory (unsigned long start, unsigned long end, void *arg)
 {
+	free_bootmem(__pa(start), end - start);
+	return 0;
+}
+#endif /* CONFIG_DISCONTIGMEM */
+
+/*
+ * Filter incoming memory segments based on the primitive map created from
+ * the boot parameters. Segments contained in the map are removed from the
+ * memory ranges. A caller-specified function is called with the memory
+ * ranges that remain after filtering.
+ * This routine does not assume the incoming segments are sorted.
+ */
+int
+filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
+{
 	unsigned long range_start, range_end, prev_start;
+	void (*func)(unsigned long, unsigned long, int);
 	int i;
 
 #if IGNORE_PFN0
@@ -134,13 +197,18 @@
 	 * lowest possible address(walker uses virtual)
 	 */
 	prev_start = PAGE_OFFSET;
+	func = arg;
 
 	for (i = 0; i < num_rsvd_regions; ++i) {
 		range_start = MAX(start, prev_start);
 		range_end   = MIN(end, rsvd_region[i].start);
 
 		if (range_start < range_end)
-			free_bootmem(__pa(range_start), range_end - range_start);
+#ifdef CONFIG_DISCONTIGMEM
+			call_pernode_memory(range_start, range_end, func);
+#else
+			(*func)(range_start, range_end, 0);
+#endif
 
 		/* nothing more available in this segment */
 		if (range_end == end) return 0;
@@ -152,6 +220,7 @@
 }
 
 
+#ifndef CONFIG_DISCONTIGMEM
 /*
  * Find a place to put the bootmap and return its starting address in bootmap_start.
  * This address must be page-aligned.
@@ -190,6 +259,7 @@
 	}
 	return 0;
 }
+#endif /* CONFIG_DISCONTIGMEM */
 
 static void
 sort_regions (struct rsvd_region *rsvd_region, int max)
@@ -233,8 +303,8 @@
 				+ strlen(__va(ia64_boot_param->command_line)) + 1);
 	n++;
 
-	rsvd_region[n].start = KERNEL_START;
-	rsvd_region[n].end   = KERNEL_END;
+	rsvd_region[n].start = ia64_imva(KERNEL_START);
+	rsvd_region[n].end   = ia64_imva(KERNEL_END);
 	n++;
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -254,6 +324,14 @@
 
 	sort_regions(rsvd_region, num_rsvd_regions);
 
+#ifdef CONFIG_DISCONTIGMEM
+	{
+		extern void discontig_mem_init(void);
+		bootmap_size = max_pfn = 0;     /* stop gcc warnings */
+		discontig_mem_init();
+	}
+#else /* !CONFIG_DISCONTIGMEM */
+
 	/* first find highest page frame number */
 	max_pfn = 0;
 	efi_memmap_walk(find_max_pfn, &max_pfn);
@@ -270,8 +348,9 @@
 	bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
 
 	/* Free all available memory, then mark bootmem-map as being in use.  */
-	efi_memmap_walk(free_available_memory, 0);
+	efi_memmap_walk(filter_rsvd_memory, free_available_memory);
 	reserve_bootmem(bootmap_start, bootmap_size);
+#endif /* !CONFIG_DISCONTIGMEM */
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (ia64_boot_param->initrd_start) {
@@ -297,9 +376,22 @@
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';		/* for safety */
 
 	efi_init();
+	find_memory();
+
+#ifdef CONFIG_ACPI_BOOT
+	/* Initialize the ACPI boot-time table parser */
+	acpi_table_init();
+
+# ifdef CONFIG_ACPI_NUMA
+	acpi_numa_init();
+# endif
+#else
+# ifdef CONFIG_SMP
+	smp_build_cpu_map();	/* happens, e.g., with the Ski simulator */
+# endif
+#endif /* CONFIG_APCI_BOOT */
 
 	iomem_resource.end = ~0UL;	/* FIXME probably belongs elsewhere */
-	find_memory();
 
 #if 0
 	/* XXX fix me */
@@ -353,7 +445,7 @@
 	cpu_init();	/* initialize the bootstrap CPU */
 
 #ifdef CONFIG_ACPI_BOOT
-	acpi_boot_init(*cmdline_p);
+	acpi_boot_init();
 #endif
 #ifdef CONFIG_SERIAL_HCDP
 	if (efi.hcdp) {
@@ -446,6 +538,8 @@
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
 		   lpj*HZ/500000, (lpj*HZ/5000) % 100);
 	return 0;
+#undef lpj
+#undef cpu
 }
 
 static void *
@@ -546,7 +640,7 @@
 	unsigned int max_ctx;
 	struct cpuinfo_ia64 *my_cpu_data;
 #ifdef CONFIG_NUMA
-	int cpu, order;
+	int cpu;
 
 	/*
 	 * If NUMA is configured, the cpu_data array is not preallocated. The boot cpu
@@ -555,28 +649,14 @@
 	 * is required because some boot code references all cpu_data structures
 	 * before the cpus are actually started.
 	 */
-	if (!boot_cpu_data) {
-		my_cpu_data = alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
-						       sizeof(struct cpuinfo_ia64));
-		boot_cpu_data = my_cpu_data;
-		my_cpu_data->cpu_data[0] = my_cpu_data;
-		for (cpu = 1; cpu < NR_CPUS; ++cpu)
-			my_cpu_data->cpu_data[cpu]
-				= alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
-							   sizeof(struct cpuinfo_ia64));
-		for (cpu = 1; cpu < NR_CPUS; ++cpu)
-			memcpy(my_cpu_data->cpu_data[cpu]->cpu_data,
-			       my_cpu_data->cpu_data, sizeof(my_cpu_data->cpu_data));
-	} else {
-		order = get_order(sizeof(struct cpuinfo_ia64));
-		my_cpu_data = page_address(alloc_pages_node(numa_node_id(), GFP_KERNEL, order));
-		memcpy(my_cpu_data, boot_cpu_data->cpu_data[smp_processor_id()],
-		       sizeof(struct cpuinfo_ia64));
-		__free_pages(virt_to_page(boot_cpu_data->cpu_data[smp_processor_id()]),
-			     order);
-		for (cpu = 0; cpu < NR_CPUS; ++cpu)
-			boot_cpu_data->cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
-	}
+	for (cpu=0; cpu < NR_CPUS; cpu++)
+		if (node_cpuid[cpu].phys_id == hard_smp_processor_id())
+			break;
+	my_cpu_data = _cpu_data[cpu];
+	my_cpu_data->node_data->active_cpu_count++;
+
+	for (cpu=0; cpu<NR_CPUS; cpu++)
+		_cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
 #else
 	my_cpu_data = cpu_data(smp_processor_id());
 #endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)