]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - arch/arm/mm/mmu.c
ARM: Precalculate vmalloc_min
[net-next-2.6.git] / arch / arm / mm / mmu.c
index 241c24a1c18f391b6795612786ef6139213b7cbf..6a08087ab022d83090ac46d4f92e06f6d8c10f97 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/bootmem.h>
 #include <linux/mman.h>
 #include <linux/nodemask.h>
+#include <linux/sort.h>
 
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
@@ -603,7 +604,7 @@ static void __init create_36bit_mapping(struct map_desc *md,
  * offsets, and we take full advantage of sections and
  * supersections.
  */
-void __init create_mapping(struct map_desc *md)
+static void __init create_mapping(struct map_desc *md)
 {
        unsigned long phys, addr, length, end;
        const struct mem_type *type;
@@ -667,7 +668,7 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
                create_mapping(io_desc + i);
 }
 
-static unsigned long __initdata vmalloc_reserve = SZ_128M;
+static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M);
 
 /*
  * vmalloc=size forces the vmalloc area to be exactly 'size'
@@ -676,7 +677,7 @@ static unsigned long __initdata vmalloc_reserve = SZ_128M;
  */
 static int __init early_vmalloc(char *arg)
 {
-       vmalloc_reserve = memparse(arg, NULL);
+       unsigned long vmalloc_reserve = memparse(arg, NULL);
 
        if (vmalloc_reserve < SZ_16M) {
                vmalloc_reserve = SZ_16M;
@@ -691,12 +692,12 @@ static int __init early_vmalloc(char *arg)
                        "vmalloc area is too big, limiting to %luMB\n",
                        vmalloc_reserve >> 20);
        }
+
+       vmalloc_min = (void *)(VMALLOC_END - vmalloc_reserve);
        return 0;
 }
 early_param("vmalloc", early_vmalloc);
 
-#define VMALLOC_MIN    (void *)(VMALLOC_END - vmalloc_reserve)
-
 static void __init sanity_check_meminfo(void)
 {
        int i, j, highmem = 0;
@@ -706,7 +707,7 @@ static void __init sanity_check_meminfo(void)
                *bank = meminfo.bank[i];
 
 #ifdef CONFIG_HIGHMEM
-               if (__va(bank->start) > VMALLOC_MIN ||
+               if (__va(bank->start) > vmalloc_min ||
                    __va(bank->start) < (void *)PAGE_OFFSET)
                        highmem = 1;
 
@@ -716,8 +717,8 @@ static void __init sanity_check_meminfo(void)
                 * Split those memory banks which are partially overlapping
                 * the vmalloc area greatly simplifying things later.
                 */
-               if (__va(bank->start) < VMALLOC_MIN &&
-                   bank->size > VMALLOC_MIN - __va(bank->start)) {
+               if (__va(bank->start) < vmalloc_min &&
+                   bank->size > vmalloc_min - __va(bank->start)) {
                        if (meminfo.nr_banks >= NR_BANKS) {
                                printk(KERN_CRIT "NR_BANKS too low, "
                                                 "ignoring high memory\n");
@@ -726,12 +727,12 @@ static void __init sanity_check_meminfo(void)
                                        (meminfo.nr_banks - i) * sizeof(*bank));
                                meminfo.nr_banks++;
                                i++;
-                               bank[1].size -= VMALLOC_MIN - __va(bank->start);
-                               bank[1].start = __pa(VMALLOC_MIN - 1) + 1;
+                               bank[1].size -= vmalloc_min - __va(bank->start);
+                               bank[1].start = __pa(vmalloc_min - 1) + 1;
                                bank[1].highmem = highmem = 1;
                                j++;
                        }
-                       bank->size = VMALLOC_MIN - __va(bank->start);
+                       bank->size = vmalloc_min - __va(bank->start);
                }
 #else
                bank->highmem = highmem;
@@ -740,7 +741,7 @@ static void __init sanity_check_meminfo(void)
                 * Check whether this memory bank would entirely overlap
                 * the vmalloc area.
                 */
-               if (__va(bank->start) >= VMALLOC_MIN ||
+               if (__va(bank->start) >= vmalloc_min ||
                    __va(bank->start) < (void *)PAGE_OFFSET) {
                        printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx "
                               "(vmalloc region overlap).\n",
@@ -752,9 +753,9 @@ static void __init sanity_check_meminfo(void)
                 * Check whether this memory bank would partially overlap
                 * the vmalloc area.
                 */
-               if (__va(bank->start + bank->size) > VMALLOC_MIN ||
+               if (__va(bank->start + bank->size) > vmalloc_min ||
                    __va(bank->start + bank->size) < __va(bank->start)) {
-                       unsigned long newsize = VMALLOC_MIN - __va(bank->start);
+                       unsigned long newsize = vmalloc_min - __va(bank->start);
                        printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx "
                               "to -%.8lx (vmalloc region overlap).\n",
                               bank->start, bank->start + bank->size - 1,
@@ -869,9 +870,10 @@ void __init reserve_node_zero(pg_data_t *pgdat)
        if (machine_is_p720t())
                res_size = 0x00014000;
 
-       /* H1940 and RX3715 need to reserve this for suspend */
+       /* H1940, RX3715 and RX1950 need to reserve this for suspend */
 
-       if (machine_is_h1940() || machine_is_rx3715()) {
+       if (machine_is_h1940() || machine_is_rx3715()
+               || machine_is_rx1950()) {
                reserve_bootmem_node(pgdat, 0x30003000, 0x1000,
                                BOOTMEM_DEFAULT);
                reserve_bootmem_node(pgdat, 0x30081000, 0x1000,
@@ -1017,6 +1019,39 @@ static void __init kmap_init(void)
 #endif
 }
 
+static inline void map_memory_bank(struct membank *bank)
+{
+       struct map_desc map;
+
+       map.pfn = bank_pfn_start(bank);
+       map.virtual = __phys_to_virt(bank_phys_start(bank));
+       map.length = bank_phys_size(bank);
+       map.type = MT_MEMORY;
+
+       create_mapping(&map);
+}
+
+static void __init map_lowmem(void)
+{
+       struct meminfo *mi = &meminfo;
+       int i;
+
+       /* Map all the lowmem memory banks. */
+       for (i = 0; i < mi->nr_banks; i++) {
+               struct membank *bank = &mi->bank[i];
+
+               if (!bank->highmem)
+                       map_memory_bank(bank);
+       }
+}
+
+static int __init meminfo_cmp(const void *_a, const void *_b)
+{
+       const struct membank *a = _a, *b = _b;
+       long cmp = bank_pfn_start(a) - bank_pfn_start(b);
+       return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
+}
+
 /*
  * paging_init() sets up the page tables, initialises the zone memory
  * maps, and sets up the zero page, bad page and bad page tables.
@@ -1025,9 +1060,12 @@ void __init paging_init(struct machine_desc *mdesc)
 {
        void *zero_page;
 
+       sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
+
        build_mem_type_table();
        sanity_check_meminfo();
        prepare_page_table();
+       map_lowmem();
        bootmem_init();
        devicemaps_init(mdesc);
        kmap_init();