Merge branch 'x86-mce-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / arm / mm / init.c
index 4011e52..7185b00 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/initrd.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
+#include <linux/memblock.h>
 
 #include <asm/mach-types.h>
 #include <asm/sections.h>
@@ -146,95 +147,21 @@ static void __init find_limits(struct meminfo *mi,
        }
 }
 
-/*
- * FIXME: We really want to avoid allocating the bootmap bitmap
- * over the top of the initrd.  Hopefully, this is located towards
- * the start of a bank, so if we allocate the bootmap bitmap at
- * the end, we won't clash.
- */
-static unsigned int __init
-find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages)
-{
-       unsigned int start_pfn, i, bootmap_pfn;
-
-       start_pfn   = PAGE_ALIGN(__pa(_end)) >> PAGE_SHIFT;
-       bootmap_pfn = 0;
-
-       for_each_bank(i, mi) {
-               struct membank *bank = &mi->bank[i];
-               unsigned int start, end;
-
-               start = bank_pfn_start(bank);
-               end   = bank_pfn_end(bank);
-
-               if (end < start_pfn)
-                       continue;
-
-               if (start < start_pfn)
-                       start = start_pfn;
-
-               if (end <= start)
-                       continue;
-
-               if (end - start >= bootmap_pages) {
-                       bootmap_pfn = start;
-                       break;
-               }
-       }
-
-       if (bootmap_pfn == 0)
-               BUG();
-
-       return bootmap_pfn;
-}
-
-static int __init check_initrd(struct meminfo *mi)
-{
-       int initrd = -2;
-#ifdef CONFIG_BLK_DEV_INITRD
-       unsigned long end = phys_initrd_start + phys_initrd_size;
-
-       /*
-        * Make sure that the initrd is within a valid area of
-        * memory.
-        */
-       if (phys_initrd_size) {
-               unsigned int i;
-
-               initrd = -1;
-
-               for (i = 0; i < mi->nr_banks; i++) {
-                       struct membank *bank = &mi->bank[i];
-                       if (bank_phys_start(bank) <= phys_initrd_start &&
-                           end <= bank_phys_end(bank))
-                               initrd = 0;
-               }
-       }
-
-       if (initrd == -1) {
-               printk(KERN_ERR "INITRD: 0x%08lx+0x%08lx extends beyond "
-                      "physical memory - disabling initrd\n",
-                      phys_initrd_start, phys_initrd_size);
-               phys_initrd_start = phys_initrd_size = 0;
-       }
-#endif
-
-       return initrd;
-}
-
 static void __init arm_bootmem_init(struct meminfo *mi,
        unsigned long start_pfn, unsigned long end_pfn)
 {
-       unsigned long boot_pfn;
        unsigned int boot_pages;
+       phys_addr_t bitmap;
        pg_data_t *pgdat;
        int i;
 
        /*
-        * Allocate the bootmem bitmap page.
+        * Allocate the bootmem bitmap page.  This must be in a region
+        * of memory which has already been mapped.
         */
        boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
-       boot_pfn = find_bootmap_pfn(mi, boot_pages);
+       bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
+                               __pfn_to_phys(end_pfn));
 
        /*
         * Initialise the bootmem allocator, handing the
@@ -242,7 +169,7 @@ static void __init arm_bootmem_init(struct meminfo *mi,
         */
        node_set_online(0);
        pgdat = NODE_DATA(0);
-       init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn);
+       init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
 
        for_each_bank(i, mi) {
                struct membank *bank = &mi->bank[i];
@@ -251,40 +178,24 @@ static void __init arm_bootmem_init(struct meminfo *mi,
        }
 
        /*
-        * Reserve the bootmem bitmap.
+        * Reserve the memblock reserved regions in bootmem.
         */
-       reserve_bootmem(boot_pfn << PAGE_SHIFT,
-                       boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
-}
-
-static void __init bootmem_reserve_initrd(void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
-       int res;
-
-       res = reserve_bootmem(phys_initrd_start,
-                             phys_initrd_size, BOOTMEM_EXCLUSIVE);
-
-       if (res == 0) {
-               initrd_start = __phys_to_virt(phys_initrd_start);
-               initrd_end = initrd_start + phys_initrd_size;
-       } else {
-               printk(KERN_ERR
-                       "INITRD: 0x%08lx+0x%08lx overlaps in-use "
-                       "memory region - disabling initrd\n",
-                       phys_initrd_start, phys_initrd_size);
+       for (i = 0; i < memblock.reserved.cnt; i++) {
+               phys_addr_t start = memblock_start_pfn(&memblock.reserved, i);
+               if (start >= start_pfn &&
+                   memblock_end_pfn(&memblock.reserved, i) <= end_pfn)
+                       reserve_bootmem_node(pgdat, __pfn_to_phys(start),
+                               memblock_size_bytes(&memblock.reserved, i),
+                               BOOTMEM_DEFAULT);
        }
-#endif
 }
 
-static void __init arm_bootmem_free(struct meminfo *mi)
+static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min,
+       unsigned long max_low, unsigned long max_high)
 {
        unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
-       unsigned long min, max_low, max_high;
        int i;
 
-       find_limits(mi, &min, &max_low, &max_high);
-
        /*
         * initialise the zones.
         */
@@ -318,7 +229,7 @@ static void __init arm_bootmem_free(struct meminfo *mi)
         * Adjust the sizes according to any special requirements for
         * this machine type.
         */
-       arch_adjust_zones(0, zone_size, zhole_size);
+       arch_adjust_zones(zone_size, zhole_size);
 
        free_area_init_node(0, zone_size, min, zhole_size);
 }
@@ -326,16 +237,15 @@ static void __init arm_bootmem_free(struct meminfo *mi)
 #ifndef CONFIG_SPARSEMEM
 int pfn_valid(unsigned long pfn)
 {
-       struct meminfo *mi = &meminfo;
-       unsigned int left = 0, right = mi->nr_banks;
+       struct memblock_region *mem = &memblock.memory;
+       unsigned int left = 0, right = mem->cnt;
 
        do {
                unsigned int mid = (right + left) / 2;
-               struct membank *bank = &mi->bank[mid];
 
-               if (pfn < bank_pfn_start(bank))
+               if (pfn < memblock_start_pfn(mem, mid))
                        right = mid;
-               else if (pfn >= bank_pfn_end(bank))
+               else if (pfn >= memblock_end_pfn(mem, mid))
                        left = mid + 1;
                else
                        return 1;
@@ -344,30 +254,57 @@ int pfn_valid(unsigned long pfn)
 }
 EXPORT_SYMBOL(pfn_valid);
 
-static void arm_memory_present(struct meminfo *mi)
+static void arm_memory_present(void)
 {
 }
 #else
-static void arm_memory_present(struct meminfo *mi)
+static void arm_memory_present(void)
 {
        int i;
-       for_each_bank(i, mi) {
-               struct membank *bank = &mi->bank[i];
-               memory_present(0, bank_pfn_start(bank), bank_pfn_end(bank));
-       }
+       for (i = 0; i < memblock.memory.cnt; i++)
+               memory_present(0, memblock_start_pfn(&memblock.memory, i),
+                                 memblock_end_pfn(&memblock.memory, i));
 }
 #endif
 
+void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
+{
+       int i;
+
+       memblock_init();
+       for (i = 0; i < mi->nr_banks; i++)
+               memblock_add(mi->bank[i].start, mi->bank[i].size);
+
+       /* Register the kernel text, kernel data and initrd with memblock. */
+#ifdef CONFIG_XIP_KERNEL
+       memblock_reserve(__pa(_data), _end - _data);
+#else
+       memblock_reserve(__pa(_stext), _end - _stext);
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (phys_initrd_size) {
+               memblock_reserve(phys_initrd_start, phys_initrd_size);
+
+               /* Now convert initrd to virtual addresses */
+               initrd_start = __phys_to_virt(phys_initrd_start);
+               initrd_end = initrd_start + phys_initrd_size;
+       }
+#endif
+
+       arm_mm_memblock_reserve();
+
+       /* reserve any platform specific memblock areas */
+       if (mdesc->reserve)
+               mdesc->reserve();
+
+       memblock_analyze();
+       memblock_dump_all();
+}
+
 void __init bootmem_init(void)
 {
        struct meminfo *mi = &meminfo;
        unsigned long min, max_low, max_high;
-       int initrd;
-
-       /*
-        * Locate the ramdisk image, if any.
-        */
-       initrd = check_initrd(mi);
 
        max_low = max_high = 0;
 
@@ -375,22 +312,11 @@ void __init bootmem_init(void)
 
        arm_bootmem_init(mi, min, max_low);
 
-       /*
-        * Reserve any special regions.
-        */
-       reserve_special_regions();
-
-       /*
-        * If the initrd is present, reserve its memory.
-        */
-       if (initrd == 0)
-               bootmem_reserve_initrd();
-
        /*
         * Sparsemem tries to allocate bootmem in memory_present(),
         * so must be done after the fixed reservations
         */
-       arm_memory_present(mi);
+       arm_memory_present();
 
        /*
         * sparse_init() needs the bootmem allocator up and running.
@@ -402,7 +328,7 @@ void __init bootmem_init(void)
         * the sparse mem_map arrays initialized by sparse_init()
         * for memmap_init_zone(), otherwise all PFNs are invalid.
         */
-       arm_bootmem_free(mi);
+       arm_bootmem_free(mi, min, max_low, max_high);
 
        high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
 
@@ -472,28 +398,27 @@ static void __init free_unused_memmap(struct meminfo *mi)
        unsigned int i;
 
        /*
-        * [FIXME] This relies on each bank being in address order.  This
-        * may not be the case, especially if the user has provided the
-        * information on the command line.
+        * This relies on each bank being in address order.
+        * The banks are sorted previously in bootmem_init().
         */
        for_each_bank(i, mi) {
                struct membank *bank = &mi->bank[i];
 
                bank_start = bank_pfn_start(bank);
-               if (bank_start < prev_bank_end) {
-                       printk(KERN_ERR "MEM: unordered memory banks.  "
-                               "Not freeing memmap.\n");
-                       break;
-               }
 
                /*
                 * If we had a previous bank, and there is a space
                 * between the current bank and the previous, free it.
                 */
-               if (prev_bank_end && prev_bank_end != bank_start)
+               if (prev_bank_end && prev_bank_end < bank_start)
                        free_memmap(prev_bank_end, bank_start);
 
-               prev_bank_end = bank_pfn_end(bank);
+               /*
+                * Align up here since the VM subsystem insists that the
+                * memmap entries are valid from the bank end aligned to
+                * MAX_ORDER_NR_PAGES.
+                */
+               prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
        }
 }
 
@@ -506,6 +431,11 @@ void __init mem_init(void)
 {
        unsigned long reserved_pages, free_pages;
        int i;
+#ifdef CONFIG_HAVE_TCM
+       /* These pointers are filled in on TCM detection */
+       extern u32 dtcm_end;
+       extern u32 itcm_end;
+#endif
 
        max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 
@@ -577,6 +507,10 @@ void __init mem_init(void)
 
        printk(KERN_NOTICE "Virtual kernel memory layout:\n"
                        "    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#ifdef CONFIG_HAVE_TCM
+                       "    DTCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+                       "    ITCM    : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#endif
                        "    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
 #ifdef CONFIG_MMU
                        "    DMA     : 0x%08lx - 0x%08lx   (%4ld MB)\n"
@@ -593,6 +527,10 @@ void __init mem_init(void)
 
                        MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
                                (PAGE_SIZE)),
+#ifdef CONFIG_HAVE_TCM
+                       MLK(DTCM_OFFSET, (unsigned long) dtcm_end),
+                       MLK(ITCM_OFFSET, (unsigned long) itcm_end),
+#endif
                        MLK(FIXADDR_START, FIXADDR_TOP),
 #ifdef CONFIG_MMU
                        MLM(CONSISTENT_BASE, CONSISTENT_END),