Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / mips / kernel / setup.c
index 711ad59..397a70e 100644 (file)
 #include <linux/root_dev.h>
 #include <linux/highmem.h>
 #include <linux/console.h>
+#include <linux/mmzone.h>
+#include <linux/pfn.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
+#include <asm/cache.h>
 #include <asm/cpu.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/system.h>
 
-struct cpuinfo_mips cpu_data[NR_CPUS];
+struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
 EXPORT_SYMBOL(cpu_data);
 
@@ -56,15 +59,13 @@ unsigned int PCI_DMA_BUS_IS_PHYS;
 
 EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
 
-extern void * __rd_start, * __rd_end;
-
 /*
  * Setup information
  *
  * These are initialized so they are in the .data section
  */
-unsigned long mips_machtype = MACH_UNKNOWN;
-unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
+unsigned long mips_machtype __read_mostly = MACH_UNKNOWN;
+unsigned long mips_machgroup __read_mostly = MACH_GROUP_UNKNOWN;
 
 EXPORT_SYMBOL(mips_machtype);
 EXPORT_SYMBOL(mips_machgroup);
@@ -78,7 +79,7 @@ static char command_line[CL_SIZE];
  * mips_io_port_base is the begin of the address space to which x86 style
  * I/O ports are mapped.
  */
-const unsigned long mips_io_port_base = -1;
+const unsigned long mips_io_port_base __read_mostly = -1;
 EXPORT_SYMBOL(mips_io_port_base);
 
 /*
@@ -88,8 +89,8 @@ EXPORT_SYMBOL(mips_io_port_base);
 unsigned long isa_slot_offset;
 EXPORT_SYMBOL(isa_slot_offset);
 
-static struct resource code_resource = { "Kernel code" };
-static struct resource data_resource = { "Kernel data" };
+static struct resource code_resource = { .name = "Kernel code", };
+static struct resource data_resource = { .name = "Kernel data", };
 
 void __init add_memory_region(phys_t start, phys_t size, long type)
 {
@@ -194,10 +195,68 @@ static inline void parse_cmdline_early(void)
        }
 }
 
+static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
+{
+       /*
+        * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
+        * "rd_size=0xNN" it's size
+        */
+       unsigned long start = 0;
+       unsigned long size = 0;
+       unsigned long end;
+       char cmd_line[CL_SIZE];
+       char *start_str;
+       char *size_str;
+       char *tmp;
+
+       strcpy(cmd_line, command_line);
+       *command_line = 0;
+       tmp = cmd_line;
+       /* Ignore "rd_start=" strings in other parameters. */
+       start_str = strstr(cmd_line, "rd_start=");
+       if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
+               start_str = strstr(start_str, " rd_start=");
+       while (start_str) {
+               if (start_str != cmd_line)
+                       strncat(command_line, tmp, start_str - tmp);
+               start = memparse(start_str + 9, &start_str);
+               tmp = start_str + 1;
+               start_str = strstr(start_str, " rd_start=");
+       }
+       if (*tmp)
+               strcat(command_line, tmp);
+
+       strcpy(cmd_line, command_line);
+       *command_line = 0;
+       tmp = cmd_line;
+       /* Ignore "rd_size" strings in other parameters. */
+       size_str = strstr(cmd_line, "rd_size=");
+       if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
+               size_str = strstr(size_str, " rd_size=");
+       while (size_str) {
+               if (size_str != cmd_line)
+                       strncat(command_line, tmp, size_str - tmp);
+               size = memparse(size_str + 8, &size_str);
+               tmp = size_str + 1;
+               size_str = strstr(size_str, " rd_size=");
+       }
+       if (*tmp)
+               strcat(command_line, tmp);
 
-#define PFN_UP(x)      (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x)    ((x) << PAGE_SHIFT)
+#ifdef CONFIG_64BIT
+       /* HACK: Guess if the sign extension was forgotten */
+       if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
+               start |= 0xffffffff00000000UL;
+#endif
+
+       end = start + size;
+       if (start && end) {
+               *rd_start = start;
+               *rd_end = end;
+               return 1;
+       }
+       return 0;
+}
 
 #define MAXMEM         HIGHMEM_START
 #define MAXMEM_PFN     PFN_DOWN(MAXMEM)
@@ -205,30 +264,42 @@ static inline void parse_cmdline_early(void)
 static inline void bootmem_init(void)
 {
        unsigned long start_pfn;
+       unsigned long reserved_end = (unsigned long)&_end;
 #ifndef CONFIG_SGI_IP27
-       unsigned long bootmap_size, max_low_pfn, first_usable_pfn;
+       unsigned long first_usable_pfn;
+       unsigned long bootmap_size;
        int i;
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
-       unsigned long tmp;
-       unsigned long *initrd_header;
-
-       tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
-       if (tmp < (unsigned long)&_end)
-               tmp += PAGE_SIZE;
-       initrd_header = (unsigned long *)tmp;
-       if (initrd_header[0] == 0x494E5244) {
-               initrd_start = (unsigned long)&initrd_header[2];
-               initrd_end = initrd_start + initrd_header[1];
+       int initrd_reserve_bootmem = 0;
+
+       /* Board specific code should have set up initrd_start and initrd_end */
+       ROOT_DEV = Root_RAM0;
+       if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
+               reserved_end = max(reserved_end, initrd_end);
+               initrd_reserve_bootmem = 1;
+       } else {
+               unsigned long tmp;
+               u32 *initrd_header;
+
+               tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - sizeof(u32) * 2;
+               if (tmp < reserved_end)
+                       tmp += PAGE_SIZE;
+               initrd_header = (u32 *)tmp;
+               if (initrd_header[0] == 0x494E5244) {
+                       initrd_start = (unsigned long)&initrd_header[2];
+                       initrd_end = initrd_start + initrd_header[1];
+                       reserved_end = max(reserved_end, initrd_end);
+                       initrd_reserve_bootmem = 1;
+               }
        }
-       start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
-#else
+#endif /* CONFIG_BLK_DEV_INITRD */
+
        /*
         * Partially used pages are not usable - thus
         * we are rounding upwards.
         */
-       start_pfn = PFN_UP(CPHYSADDR(&_end));
-#endif /* CONFIG_BLK_DEV_INITRD */
+       start_pfn = PFN_UP(CPHYSADDR(reserved_end));
 
 #ifndef CONFIG_SGI_IP27
        /* Find the highest page frame number we have available.  */
@@ -337,33 +408,36 @@ static inline void bootmem_init(void)
 
                /* Register lowmem ranges */
                free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+               memory_present(0, curr_pfn, curr_pfn + size - 1);
        }
 
        /* Reserve the bootmap memory.  */
        reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
-#endif
+#endif /* CONFIG_SGI_IP27 */
 
 #ifdef CONFIG_BLK_DEV_INITRD
-       /* Board specific code should have set up initrd_start and initrd_end */
-       ROOT_DEV = Root_RAM0;
-       if (&__rd_start != &__rd_end) {
-               initrd_start = (unsigned long)&__rd_start;
-               initrd_end = (unsigned long)&__rd_end;
-       }
        initrd_below_start_ok = 1;
        if (initrd_start) {
-               unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start);
+               unsigned long initrd_size = ((unsigned char *)initrd_end) -
+                       ((unsigned char *)initrd_start);
+               const int width = sizeof(long) * 2;
+
                printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
-                      (void *)initrd_start,
-                      initrd_size);
+                      (void *)initrd_start, initrd_size);
 
                if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
                        printk("initrd extends beyond end of memory "
                               "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
-                              sizeof(long) * 2, CPHYSADDR(initrd_end),
-                              sizeof(long) * 2, PFN_PHYS(max_low_pfn));
+                              width,
+                              (unsigned long long) CPHYSADDR(initrd_end),
+                              width,
+                              (unsigned long long) PFN_PHYS(max_low_pfn));
                        initrd_start = initrd_end = 0;
+                       initrd_reserve_bootmem = 0;
                }
+
+               if (initrd_reserve_bootmem)
+                       reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
        }
 #endif /* CONFIG_BLK_DEV_INITRD  */
 }
@@ -418,66 +492,17 @@ static inline void resource_init(void)
        }
 }
 
-#undef PFN_UP
-#undef PFN_DOWN
-#undef PFN_PHYS
-
 #undef MAXMEM
 #undef MAXMEM_PFN
 
-static int __initdata earlyinit_debug;
-
-static int __init earlyinit_debug_setup(char *str)
-{
-       earlyinit_debug = 1;
-       return 1;
-}
-__setup("earlyinit_debug", earlyinit_debug_setup);
-
-extern initcall_t __earlyinitcall_start, __earlyinitcall_end;
-
-static void __init do_earlyinitcalls(void)
-{
-       initcall_t *call, *start, *end;
-
-       start = &__earlyinitcall_start;
-       end = &__earlyinitcall_end;
-
-       for (call = start; call < end; call++) {
-               if (earlyinit_debug)
-                       printk("calling earlyinitcall 0x%p\n", *call);
-
-               (*call)();
-       }
-}
+extern void plat_setup(void);
 
 void __init setup_arch(char **cmdline_p)
 {
-       unsigned int status;
-
        cpu_probe();
        prom_init();
        cpu_report();
 
-#ifdef CONFIG_MIPS32
-       /* Disable coprocessors and set FPU for 16/32 FPR register model */
-       status = read_c0_status();
-       status &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
-       status |= ST0_CU0;
-       write_c0_status(status);
-#endif
-#ifdef CONFIG_MIPS64
-       /*
-        * On IP27, I am seeing the TS bit set when the kernel is loaded.
-        * Maybe because the kernel is in ckseg0 and not xkphys? Clear it
-        * anyway ...
-        */
-       status = read_c0_status();
-       status &= ~(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3);
-       status |= (ST0_CU0|ST0_KX|ST0_SX|ST0_FR);
-       write_c0_status(status);
-#endif
-
 #if defined(CONFIG_VT)
 #if defined(CONFIG_VGA_CONSOLE)
         conswitchp = &vga_con;
@@ -487,7 +512,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        /* call board setup routine */
-       do_earlyinitcalls();
+       plat_setup();
 
        strlcpy(command_line, arcs_cmdline, sizeof(command_line));
        strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
@@ -496,15 +521,31 @@ void __init setup_arch(char **cmdline_p)
 
        parse_cmdline_early();
        bootmem_init();
+       sparse_init();
        paging_init();
        resource_init();
+#ifdef CONFIG_SMP
+       plat_smp_setup();
+#endif
 }
 
 int __init fpu_disable(char *s)
 {
-       cpu_data[0].options &= ~MIPS_CPU_FPU;
+       int i;
+
+       for (i = 0; i < NR_CPUS; i++)
+               cpu_data[i].options &= ~MIPS_CPU_FPU;
 
        return 1;
 }
 
 __setup("nofpu", fpu_disable);
+
+int __init dsp_disable(char *s)
+{
+       cpu_data[0].ases &= ~MIPS_ASE_DSP;
+
+       return 1;
+}
+
+__setup("nodsp", dsp_disable);