Merge branch 'misc' into devel
authorRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 31 Jul 2010 13:20:02 +0000 (14:20 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 31 Jul 2010 13:20:02 +0000 (14:20 +0100)
Conflicts:
arch/arm/mm/init.c

1  2 
arch/arm/Kconfig
arch/arm/include/asm/memory.h
arch/arm/kernel/machine_kexec.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c

diff --combined arch/arm/Kconfig
index 4047f5724da30710de54713d15b0857370192c05,157b08aa03663ed744c24ee49f60df9937de1995..ba1ac08b4e02175a4581d1ef49f55f9af0fa17a1
@@@ -10,7 -10,6 +10,7 @@@ config AR
        default y
        select HAVE_AOUT
        select HAVE_IDE
 +      select HAVE_MEMBLOCK
        select RTC_LIB
        select SYS_SUPPORTS_APM_EMULATION
        select GENERIC_ATOMIC64 if (!CPU_32v6K)
@@@ -57,7 -56,7 +57,7 @@@ config GENERIC_CLOCKEVENT
  config GENERIC_CLOCKEVENTS_BROADCAST
        bool
        depends on GENERIC_CLOCKEVENTS
-       default y if SMP && !LOCAL_TIMERS
+       default y if SMP
  
  config HAVE_TCM
        bool
@@@ -441,6 -440,21 +441,6 @@@ config ARCH_IXP4X
        help
          Support for Intel's IXP4XX (XScale) family of processors.
  
 -config ARCH_L7200
 -      bool "LinkUp-L7200"
 -      select CPU_ARM720T
 -      select FIQ
 -      select ARCH_USES_GETTIMEOFFSET
 -      help
 -        Say Y here if you intend to run this kernel on a LinkUp Systems
 -        L7200 Software Development Board which uses an ARM720T processor.
 -        Information on this board can be obtained at:
 -
 -        <http://www.linkupsys.com/>
 -
 -        If you have any questions or comments about the Linux kernel port
 -        to this board, send e-mail to <sjhill@cotw.com>.
 -
  config ARCH_DOVE
        bool "Marvell Dove"
        select PCI
@@@ -706,6 -720,7 +706,6 @@@ config ARCH_SHAR
  config ARCH_LH7A40X
        bool "Sharp LH7A40X"
        select CPU_ARM922T
 -      select ARCH_DISCONTIGMEM_ENABLE if !LH7A40X_CONTIGMEM
        select ARCH_SPARSEMEM_ENABLE if !LH7A40X_CONTIGMEM
        select ARCH_USES_GETTIMEOFFSET
        help
@@@ -1153,10 -1168,9 +1153,10 @@@ config HOTPLUG_CP
  config LOCAL_TIMERS
        bool "Use local timer interrupts"
        depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
 -              REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500)
 +              REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
 +              ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
        default y
 -      select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500)
 +      select HAVE_ARM_TWD if (ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_OMAP4 || ARCH_U8500)
        help
          Enable support for local timers on SMP platforms, rather then the
          legacy IPI broadcast method.  Local timers allows the system
@@@ -1167,10 -1181,10 +1167,10 @@@ source kernel/Kconfig.preemp
  
  config HZ
        int
 -      default 128 if ARCH_L7200
        default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || ARCH_S5P6442 || ARCH_S5PV210
        default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
        default AT91_TIMER_HZ if ARCH_AT91
 +      default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE
        default 100
  
  config THUMB2_KERNEL
@@@ -1223,6 -1237,10 +1223,6 @@@ config OABI_COMPA
  config ARCH_HAS_HOLES_MEMORYMODEL
        bool
  
 -# Discontigmem is deprecated
 -config ARCH_DISCONTIGMEM_ENABLE
 -      bool
 -
  config ARCH_SPARSEMEM_ENABLE
        bool
  
@@@ -1230,7 -1248,13 +1230,7 @@@ config ARCH_SPARSEMEM_DEFAUL
        def_bool ARCH_SPARSEMEM_ENABLE
  
  config ARCH_SELECT_MEMORY_MODEL
 -      def_bool ARCH_DISCONTIGMEM_ENABLE && ARCH_SPARSEMEM_ENABLE
 -
 -config NODES_SHIFT
 -      int
 -      default "4" if ARCH_LH7A40X
 -      default "2"
 -      depends on NEED_MULTIPLE_NODES
 +      def_bool ARCH_SPARSEMEM_ENABLE
  
  config HIGHMEM
        bool "High Memory Support (EXPERIMENTAL)"
@@@ -1263,8 -1287,7 +1263,7 @@@ config HW_PERF_EVENT
          disabled, perf events will use software events only.
  
  config SPARSE_IRQ
-       bool "Support sparse irq numbering"
-       depends on EXPERIMENTAL
+       def_bool n
        help
          This enables support for sparse irqs. This is useful in general
          as most CPUs have a fairly sparse array of IRQ vectors, which
          number of off-chip IRQs will want to treat this as
          experimental until they have been independently verified.
  
-         If you don't know what to do here, say N.
  source "mm/Kconfig"
  
  config FORCE_MAX_ZONEORDER
index 82df0ae71bb4b110dd40b7c78b6a9cc172218571,ab08d977ad490399e976d81cab30477963cfca9d..23c2e8e5c0faaa09d81910456d4de63a96a513da
  
  #endif /* !CONFIG_MMU */
  
+ /*
+  * We fix the TCM memories max 32 KiB ITCM resp DTCM at these
+  * locations
+  */
+ #ifdef CONFIG_HAVE_TCM
+ #define ITCM_OFFSET   UL(0xfffe0000)
+ #define DTCM_OFFSET   UL(0xfffe8000)
+ #endif
  /*
   * Physical vs virtual RAM address space conversion.  These are
   * private definitions which should NOT be used outside memory.h
  #endif
  
  #ifndef arch_adjust_zones
 -#define arch_adjust_zones(node,size,holes) do { } while (0)
 +#define arch_adjust_zones(size,holes) do { } while (0)
  #elif !defined(CONFIG_ZONE_DMA)
  #error "custom arch_adjust_zones() requires CONFIG_ZONE_DMA"
  #endif
@@@ -234,11 -243,76 +243,11 @@@ static inline __deprecated void *bus_to
   *  virt_to_page(k)   convert a _valid_ virtual address to struct page *
   *  virt_addr_valid(k)        indicates whether a virtual address is valid
   */
 -#ifndef CONFIG_DISCONTIGMEM
 -
  #define ARCH_PFN_OFFSET               PHYS_PFN_OFFSET
  
  #define virt_to_page(kaddr)   pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
  #define virt_addr_valid(kaddr)        ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
  
 -#define PHYS_TO_NID(addr)     (0)
 -
 -#else /* CONFIG_DISCONTIGMEM */
 -
 -/*
 - * This is more complex.  We have a set of mem_map arrays spread
 - * around in memory.
 - */
 -#include <linux/numa.h>
 -
 -#define arch_pfn_to_nid(pfn)  PFN_TO_NID(pfn)
 -#define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)
 -
 -#define virt_to_page(kaddr)                                   \
 -      (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
 -
 -#define virt_addr_valid(kaddr)        (KVADDR_TO_NID(kaddr) < MAX_NUMNODES)
 -
 -/*
 - * Common discontigmem stuff.
 - *  PHYS_TO_NID is used by the ARM kernel/setup.c
 - */
 -#define PHYS_TO_NID(addr)     PFN_TO_NID((addr) >> PAGE_SHIFT)
 -
 -/*
 - * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
 - * and returns the mem_map of that node.
 - */
 -#define ADDR_TO_MAPBASE(kaddr)        NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
 -
 -/*
 - * Given a page frame number, find the owning node of the memory
 - * and returns the mem_map of that node.
 - */
 -#define PFN_TO_MAPBASE(pfn)   NODE_MEM_MAP(PFN_TO_NID(pfn))
 -
 -#ifdef NODE_MEM_SIZE_BITS
 -#define NODE_MEM_SIZE_MASK    ((1 << NODE_MEM_SIZE_BITS) - 1)
 -
 -/*
 - * Given a kernel address, find the home node of the underlying memory.
 - */
 -#define KVADDR_TO_NID(addr) \
 -      (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MEM_SIZE_BITS)
 -
 -/*
 - * Given a page frame number, convert it to a node id.
 - */
 -#define PFN_TO_NID(pfn) \
 -      (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MEM_SIZE_BITS - PAGE_SHIFT))
 -
 -/*
 - * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
 - * and returns the index corresponding to the appropriate page in the
 - * node's mem_map.
 - */
 -#define LOCAL_MAP_NR(addr) \
 -      (((unsigned long)(addr) & NODE_MEM_SIZE_MASK) >> PAGE_SHIFT)
 -
 -#endif /* NODE_MEM_SIZE_BITS */
 -
 -#endif /* !CONFIG_DISCONTIGMEM */
 -
  /*
   * Optional coherency support.  Currently used only by selected
   * Intel XSC3-based systems.
index 81e989858d42b33dcfe442abcccdaa4bec66dff4,df5958f6864fcde5cb3b8f1957f1cc589e0edd2e..1fc74cbd1a193ee4dcd2fd50afdd279804d9e5fd
@@@ -37,16 -37,8 +37,12 @@@ void machine_kexec_cleanup(struct kimag
  {
  }
  
- void machine_shutdown(void)
- {
- }
  void machine_crash_shutdown(struct pt_regs *regs)
  {
 +      local_irq_disable();
 +      crash_save_cpu(regs, smp_processor_id());
 +
 +      printk(KERN_INFO "Loading crashdump kernel...\n");
  }
  
  void machine_kexec(struct kimage *image)
                           (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        printk(KERN_INFO "Bye!\n");
  
-       cpu_proc_fin();
+       local_irq_disable();
+       local_fiq_disable();
        setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
+       flush_cache_all();
+       cpu_proc_fin();
+       flush_cache_all();
        cpu_reset(reboot_code_buffer_phys);
  }
index 333d04c5365024b30ef2c61a1922efe2d4e9a92c,f4fbb5ec645b0a04c27318319969441ef897c10c..61cd4d64b98596c7507dcaf67d069dbe22508e50
@@@ -348,7 -348,7 +348,7 @@@ int dma_needs_bounce(struct device *dev
   * This is really ugly and we need a better way of specifying
   * DMA-capable regions of memory.
   */
 -void __init ixp4xx_adjust_zones(int node, unsigned long *zone_size,
 +void __init ixp4xx_adjust_zones(unsigned long *zone_size,
        unsigned long *zhole_size)
  {
        unsigned int sz = SZ_64M >> PAGE_SHIFT;
        /*
         * Only adjust if > 64M on current system
         */
 -      if (node || (zone_size[0] <= sz))
 +      if (zone_size[0] <= sz)
                return;
  
        zone_size[1] = zone_size[0] - sz;
@@@ -382,7 -382,8 +382,8 @@@ void __init ixp4xx_pci_preinit(void
  
  
        /* hook in our fault handler for PCI errors */
-       hook_fault_code(16+6, abort_handler, SIGBUS, "imprecise external abort");
+       hook_fault_code(16+6, abort_handler, SIGBUS, 0,
+                       "imprecise external abort");
  
        pr_debug("setup PCI-AHB(inbound) and AHB-PCI(outbound) address mappings\n");
  
diff --combined arch/arm/mm/init.c
index 599d121c81e7d6b6beaddb8a784f1e4130b502b3,e00404e6f45b6d3f6d2ea166061a87151fd153ea..240b68d511dc1437c6fcb8bbfb491582fea72280
@@@ -17,7 -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>
@@@ -80,37 -79,38 +80,37 @@@ struct meminfo meminfo
  void show_mem(void)
  {
        int free = 0, total = 0, reserved = 0;
 -      int shared = 0, cached = 0, slab = 0, node, i;
 +      int shared = 0, cached = 0, slab = 0, i;
        struct meminfo * mi = &meminfo;
  
        printk("Mem-info:\n");
        show_free_areas();
 -      for_each_online_node(node) {
 -              for_each_nodebank (i,mi,node) {
 -                      struct membank *bank = &mi->bank[i];
 -                      unsigned int pfn1, pfn2;
 -                      struct page *page, *end;
 -
 -                      pfn1 = bank_pfn_start(bank);
 -                      pfn2 = bank_pfn_end(bank);
 -
 -                      page = pfn_to_page(pfn1);
 -                      end  = pfn_to_page(pfn2 - 1) + 1;
 -
 -                      do {
 -                              total++;
 -                              if (PageReserved(page))
 -                                      reserved++;
 -                              else if (PageSwapCache(page))
 -                                      cached++;
 -                              else if (PageSlab(page))
 -                                      slab++;
 -                              else if (!page_count(page))
 -                                      free++;
 -                              else
 -                                      shared += page_count(page) - 1;
 -                              page++;
 -                      } while (page < end);
 -              }
 +
 +      for_each_bank (i, mi) {
 +              struct membank *bank = &mi->bank[i];
 +              unsigned int pfn1, pfn2;
 +              struct page *page, *end;
 +
 +              pfn1 = bank_pfn_start(bank);
 +              pfn2 = bank_pfn_end(bank);
 +
 +              page = pfn_to_page(pfn1);
 +              end  = pfn_to_page(pfn2 - 1) + 1;
 +
 +              do {
 +                      total++;
 +                      if (PageReserved(page))
 +                              reserved++;
 +                      else if (PageSwapCache(page))
 +                              cached++;
 +                      else if (PageSlab(page))
 +                              slab++;
 +                      else if (!page_count(page))
 +                              free++;
 +                      else
 +                              shared += page_count(page) - 1;
 +                      page++;
 +              } while (page < end);
        }
  
        printk("%d pages of RAM\n", total);
        printk("%d pages swap cached\n", cached);
  }
  
 -static void __init find_node_limits(int node, struct meminfo *mi,
 +static void __init find_limits(struct meminfo *mi,
        unsigned long *min, unsigned long *max_low, unsigned long *max_high)
  {
        int i;
        *min = -1UL;
        *max_low = *max_high = 0;
  
 -      for_each_nodebank(i, mi, node) {
 +      for_each_bank (i, mi) {
                struct membank *bank = &mi->bank[i];
                unsigned long start, end;
  
        }
  }
  
 -/*
 - * 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(int node, 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_nodebank(i, mi, node) {
 -              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_node = -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_node = -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_node = bank->node;
 -              }
 -      }
 -
 -      if (initrd_node == -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_node;
 -}
 -
 -static void __init bootmem_init_node(int node, struct meminfo *mi,
 +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(node, mi, boot_pages);
 +      bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
 +                              __pfn_to_phys(end_pfn));
  
        /*
 -       * Initialise the bootmem allocator for this node, handing the
 +       * Initialise the bootmem allocator, handing the
         * memory banks over to bootmem.
         */
 -      node_set_online(node);
 -      pgdat = NODE_DATA(node);
 -      init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn);
 +      node_set_online(0);
 +      pgdat = NODE_DATA(0);
 +      init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
  
 -      for_each_nodebank(i, mi, node) {
 +      for_each_bank(i, mi) {
                struct membank *bank = &mi->bank[i];
                if (!bank->highmem)
 -                      free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
 +                      free_bootmem(bank_phys_start(bank), bank_phys_size(bank));
        }
  
        /*
 -       * Reserve the bootmem bitmap for this node.
 +       * Reserve the memblock reserved regions in bootmem.
         */
 -      reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
 -                           boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
 -}
 -
 -static void __init bootmem_reserve_initrd(int node)
 -{
 -#ifdef CONFIG_BLK_DEV_INITRD
 -      pg_data_t *pgdat = NODE_DATA(node);
 -      int res;
 -
 -      res = reserve_bootmem_node(pgdat, 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 bootmem_free_node(int node, 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_node_limits(node, mi, &min, &max_low, &max_high);
 -
        /*
 -       * initialise the zones within this node.
 +       * initialise the zones.
         */
        memset(zone_size, 0, sizeof(zone_size));
  
        /*
 -       * The size of this node has already been determined.  If we need
 -       * to do anything fancy with the allocation of this memory to the
 -       * zones, now is the time to do it.
 +       * The memory size has already been determined.  If we need
 +       * to do anything fancy with the allocation of this memory
 +       * to the zones, now is the time to do it.
         */
        zone_size[0] = max_low - min;
  #ifdef CONFIG_HIGHMEM
  #endif
  
        /*
 -       * For each bank in this node, calculate the size of the holes.
 -       *  holes = node_size - sum(bank_sizes_in_node)
 +       * Calculate the size of the holes.
 +       *  holes = node_size - sum(bank_sizes)
         */
        memcpy(zhole_size, zone_size, sizeof(zhole_size));
 -      for_each_nodebank(i, mi, node) {
 +      for_each_bank(i, mi) {
                int idx = 0;
  #ifdef CONFIG_HIGHMEM
                if (mi->bank[i].highmem)
         * Adjust the sizes according to any special requirements for
         * this machine type.
         */
 -      arch_adjust_zones(node, zone_size, zhole_size);
 +      arch_adjust_zones(zone_size, zhole_size);
  
 -      free_area_init_node(node, zone_size, min, zhole_size);
 +      free_area_init_node(0, zone_size, min, zhole_size);
  }
  
  #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;
  }
  EXPORT_SYMBOL(pfn_valid);
  
 -static void arm_memory_present(struct meminfo *mi, int node)
 +static void arm_memory_present(void)
  {
  }
  #else
 -static void arm_memory_present(struct meminfo *mi, int node)
 +static void arm_memory_present(void)
  {
        int i;
 -      for_each_nodebank(i, mi, node) {
 -              struct membank *bank = &mi->bank[i];
 -              memory_present(node, 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 bootmem_init(void)
 +void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
  {
 -      struct meminfo *mi = &meminfo;
 -      unsigned long min, max_low, max_high;
 -      int node, initrd_node;
 +      int i;
  
 -      /*
 -       * Locate which node contains the ramdisk image, if any.
 -       */
 -      initrd_node = check_initrd(mi);
 +      memblock_init();
 +      for (i = 0; i < mi->nr_banks; i++)
 +              memblock_add(mi->bank[i].start, mi->bank[i].size);
  
 -      max_low = max_high = 0;
 +      /* 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);
  
 -      /*
 -       * Run through each node initialising the bootmem allocator.
 -       */
 -      for_each_node(node) {
 -              unsigned long node_low, node_high;
 +              /* Now convert initrd to virtual addresses */
 +              initrd_start = __phys_to_virt(phys_initrd_start);
 +              initrd_end = initrd_start + phys_initrd_size;
 +      }
 +#endif
  
 -              find_node_limits(node, mi, &min, &node_low, &node_high);
 +      arm_mm_memblock_reserve();
  
 -              if (node_low > max_low)
 -                      max_low = node_low;
 -              if (node_high > max_high)
 -                      max_high = node_high;
 +      /* reserve any platform specific memblock areas */
 +      if (mdesc->reserve)
 +              mdesc->reserve();
  
 -              /*
 -               * If there is no memory in this node, ignore it.
 -               * (We can't have nodes which have no lowmem)
 -               */
 -              if (node_low == 0)
 -                      continue;
 +      memblock_analyze();
 +      memblock_dump_all();
 +}
  
 -              bootmem_init_node(node, mi, min, node_low);
 +void __init bootmem_init(void)
 +{
 +      struct meminfo *mi = &meminfo;
 +      unsigned long min, max_low, max_high;
  
 -              /*
 -               * Reserve any special node zero regions.
 -               */
 -              if (node == 0)
 -                      reserve_node_zero(NODE_DATA(node));
 +      max_low = max_high = 0;
  
 -              /*
 -               * If the initrd is in this node, reserve its memory.
 -               */
 -              if (node == initrd_node)
 -                      bootmem_reserve_initrd(node);
 +      find_limits(mi, &min, &max_low, &max_high);
  
 -              /*
 -               * Sparsemem tries to allocate bootmem in memory_present(),
 -               * so must be done after the fixed reservations
 -               */
 -              arm_memory_present(mi, node);
 -      }
 +      arm_bootmem_init(mi, min, max_low);
 +
 +      /*
 +       * Sparsemem tries to allocate bootmem in memory_present(),
 +       * so must be done after the fixed reservations
 +       */
 +      arm_memory_present();
  
        /*
         * sparse_init() needs the bootmem allocator up and running.
        sparse_init();
  
        /*
 -       * Now free memory in each node - free_area_init_node needs
 +       * Now free the memory - free_area_init_node needs
         * the sparse mem_map arrays initialized by sparse_init()
         * for memmap_init_zone(), otherwise all PFNs are invalid.
         */
 -      for_each_node(node)
 -              bootmem_free_node(node, mi);
 +      arm_bootmem_free(mi, min, max_low, max_high);
  
        high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
  
@@@ -363,7 -460,7 +363,7 @@@ static inline int free_area(unsigned lo
  }
  
  static inline void
 -free_memmap(int node, unsigned long start_pfn, unsigned long end_pfn)
 +free_memmap(unsigned long start_pfn, unsigned long end_pfn)
  {
        struct page *start_pg, *end_pg;
        unsigned long pg, pgend;
         * free the section of the memmap array.
         */
        if (pg < pgend)
 -              free_bootmem_node(NODE_DATA(node), pg, pgend - pg);
 +              free_bootmem(pg, pgend - pg);
  }
  
  /*
   * The mem_map array can get very big.  Free the unused area of the memory map.
   */
 -static void __init free_unused_memmap_node(int node, struct meminfo *mi)
 +static void __init free_unused_memmap(struct meminfo *mi)
  {
        unsigned long bank_start, prev_bank_end = 0;
        unsigned int i;
         * may not be the case, especially if the user has provided the
         * information on the command line.
         */
 -      for_each_nodebank(i, mi, node) {
 +      for_each_bank(i, mi) {
                struct membank *bank = &mi->bank[i];
  
                bank_start = bank_pfn_start(bank);
                 * between the current bank and the previous, free it.
                 */
                if (prev_bank_end && prev_bank_end != bank_start)
 -                      free_memmap(node, prev_bank_end, bank_start);
 +                      free_memmap(prev_bank_end, bank_start);
  
                prev_bank_end = bank_pfn_end(bank);
        }
  void __init mem_init(void)
  {
        unsigned long reserved_pages, free_pages;
 -      int i, node;
 +      int i;
+ #ifdef CONFIG_HAVE_TCM
+       /* These pointers are filled in on TCM detection */
+       extern u32 dtcm_end;
+       extern u32 itcm_end;
+ #endif
  
 -#ifndef CONFIG_DISCONTIGMEM
        max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 -#endif
  
        /* this will put all unused low memory onto the freelists */
 -      for_each_online_node(node) {
 -              pg_data_t *pgdat = NODE_DATA(node);
 -
 -              free_unused_memmap_node(node, &meminfo);
 +      free_unused_memmap(&meminfo);
  
 -              if (pgdat->node_spanned_pages != 0)
 -                      totalram_pages += free_all_bootmem_node(pgdat);
 -      }
 +      totalram_pages += free_all_bootmem();
  
  #ifdef CONFIG_SA1111
        /* now that our DMA memory is actually so designated, we can free it */
  
  #ifdef CONFIG_HIGHMEM
        /* set highmem page free */
 -      for_each_online_node(node) {
 -              for_each_nodebank (i, &meminfo, node) {
 -                      unsigned long start = bank_pfn_start(&meminfo.bank[i]);
 -                      unsigned long end = bank_pfn_end(&meminfo.bank[i]);
 -                      if (start >= max_low_pfn + PHYS_PFN_OFFSET)
 -                              totalhigh_pages += free_area(start, end, NULL);
 -              }
 +      for_each_bank (i, &meminfo) {
 +              unsigned long start = bank_pfn_start(&meminfo.bank[i]);
 +              unsigned long end = bank_pfn_end(&meminfo.bank[i]);
 +              if (start >= max_low_pfn + PHYS_PFN_OFFSET)
 +                      totalhigh_pages += free_area(start, end, NULL);
        }
        totalram_pages += totalhigh_pages;
  #endif
  
        reserved_pages = free_pages = 0;
  
 -      for_each_online_node(node) {
 -              for_each_nodebank(i, &meminfo, node) {
 -                      struct membank *bank = &meminfo.bank[i];
 -                      unsigned int pfn1, pfn2;
 -                      struct page *page, *end;
 -
 -                      pfn1 = bank_pfn_start(bank);
 -                      pfn2 = bank_pfn_end(bank);
 -
 -                      page = pfn_to_page(pfn1);
 -                      end  = pfn_to_page(pfn2 - 1) + 1;
 -
 -                      do {
 -                              if (PageReserved(page))
 -                                      reserved_pages++;
 -                              else if (!page_count(page))
 -                                      free_pages++;
 -                              page++;
 -                      } while (page < end);
 -              }
 +      for_each_bank(i, &meminfo) {
 +              struct membank *bank = &meminfo.bank[i];
 +              unsigned int pfn1, pfn2;
 +              struct page *page, *end;
 +
 +              pfn1 = bank_pfn_start(bank);
 +              pfn2 = bank_pfn_end(bank);
 +
 +              page = pfn_to_page(pfn1);
 +              end  = pfn_to_page(pfn2 - 1) + 1;
 +
 +              do {
 +                      if (PageReserved(page))
 +                              reserved_pages++;
 +                      else if (!page_count(page))
 +                              free_pages++;
 +                      page++;
 +              } while (page < end);
        }
  
        /*
  
        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"
  
                        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),
diff --combined arch/arm/mm/mmu.c
index d5541adc352043f241d9b3e7f90fa9452abe9b00,e53480148c05509688e0e2b3556379dfe6c0d09c..6e1c4f6a2b3f3a09ed3f10be9aeafab36c9a0924
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/init.h>
 -#include <linux/bootmem.h>
  #include <linux/mman.h>
  #include <linux/nodemask.h>
 +#include <linux/memblock.h>
  #include <linux/sort.h>
  
  #include <asm/cputype.h>
 -#include <asm/mach-types.h>
  #include <asm/sections.h>
  #include <asm/cachetype.h>
  #include <asm/setup.h>
@@@ -257,6 -258,19 +257,19 @@@ static struct mem_type mem_types[] = 
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
        },
+       [MT_MEMORY_DTCM] = {
+               .prot_pte       = L_PTE_PRESENT | L_PTE_YOUNG |
+                                 L_PTE_DIRTY | L_PTE_WRITE,
+               .prot_l1        = PMD_TYPE_TABLE,
+               .prot_sect      = PMD_TYPE_SECT | PMD_SECT_XN,
+               .domain         = DOMAIN_KERNEL,
+       },
+       [MT_MEMORY_ITCM] = {
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+                               L_PTE_USER | L_PTE_EXEC,
+               .prot_l1   = PMD_TYPE_TABLE,
+               .domain    = DOMAIN_IO,
+       },
  };
  
  const struct mem_type *get_mem_type(unsigned int type)
@@@ -487,28 -501,18 +500,28 @@@ static void __init build_mem_type_table
  
  #define vectors_base()        (vectors_high() ? 0xffff0000 : 0)
  
 -static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 -                                unsigned long end, unsigned long pfn,
 -                                const struct mem_type *type)
 +static void __init *early_alloc(unsigned long sz)
  {
 -      pte_t *pte;
 +      void *ptr = __va(memblock_alloc(sz, sz));
 +      memset(ptr, 0, sz);
 +      return ptr;
 +}
  
 +static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
 +{
        if (pmd_none(*pmd)) {
 -              pte = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t));
 -              __pmd_populate(pmd, __pa(pte) | type->prot_l1);
 +              pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t));
 +              __pmd_populate(pmd, __pa(pte) | prot);
        }
 +      BUG_ON(pmd_bad(*pmd));
 +      return pte_offset_kernel(pmd, addr);
 +}
  
 -      pte = pte_offset_kernel(pmd, addr);
 +static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 +                                unsigned long end, unsigned long pfn,
 +                                const struct mem_type *type)
 +{
 +      pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
        do {
                set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)), 0);
                pfn++;
@@@ -677,7 -681,7 +690,7 @@@ void __init iotable_init(struct map_des
                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'
   */
  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;
                        "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)
 +phys_addr_t lowmem_end_addr;
  
  static void __init sanity_check_meminfo(void)
  {
        int i, j, highmem = 0;
  
 +      lowmem_end_addr = __pa(vmalloc_min - 1) + 1;
 +
        for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
                struct membank *bank = &meminfo.bank[j];
                *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;
  
                 * 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");
                                        (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;
                 * 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",
                 * 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,
@@@ -840,23 -840,101 +853,23 @@@ static inline void prepare_page_table(v
  }
  
  /*
 - * Reserve the various regions of node 0
 + * Reserve the special regions of memory
   */
 -void __init reserve_node_zero(pg_data_t *pgdat)
 +void __init arm_mm_memblock_reserve(void)
  {
 -      unsigned long res_size = 0;
 -
 -      /*
 -       * Register the kernel text and data with bootmem.
 -       * Note that this can only be in node 0.
 -       */
 -#ifdef CONFIG_XIP_KERNEL
 -      reserve_bootmem_node(pgdat, __pa(_data), _end - _data,
 -                      BOOTMEM_DEFAULT);
 -#else
 -      reserve_bootmem_node(pgdat, __pa(_stext), _end - _stext,
 -                      BOOTMEM_DEFAULT);
 -#endif
 -
        /*
         * Reserve the page tables.  These are already in use,
         * and can only be in node 0.
         */
 -      reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
 -                           PTRS_PER_PGD * sizeof(pgd_t), BOOTMEM_DEFAULT);
 -
 -      /*
 -       * Hmm... This should go elsewhere, but we really really need to
 -       * stop things allocating the low memory; ideally we need a better
 -       * implementation of GFP_DMA which does not assume that DMA-able
 -       * memory starts at zero.
 -       */
 -      if (machine_is_integrator() || machine_is_cintegrator())
 -              res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
 -
 -      /*
 -       * These should likewise go elsewhere.  They pre-reserve the
 -       * screen memory region at the start of main system memory.
 -       */
 -      if (machine_is_edb7211())
 -              res_size = 0x00020000;
 -      if (machine_is_p720t())
 -              res_size = 0x00014000;
 -
 -      /* H1940, RX3715 and RX1950 need to reserve this for suspend */
 -
 -      if (machine_is_h1940() || machine_is_rx3715()
 -              || machine_is_rx1950()) {
 -              reserve_bootmem_node(pgdat, 0x30003000, 0x1000,
 -                              BOOTMEM_DEFAULT);
 -              reserve_bootmem_node(pgdat, 0x30081000, 0x1000,
 -                              BOOTMEM_DEFAULT);
 -      }
 -
 -      if (machine_is_palmld() || machine_is_palmtx()) {
 -              reserve_bootmem_node(pgdat, 0xa0000000, 0x1000,
 -                              BOOTMEM_EXCLUSIVE);
 -              reserve_bootmem_node(pgdat, 0xa0200000, 0x1000,
 -                              BOOTMEM_EXCLUSIVE);
 -      }
 -
 -      if (machine_is_treo680() || machine_is_centro()) {
 -              reserve_bootmem_node(pgdat, 0xa0000000, 0x1000,
 -                              BOOTMEM_EXCLUSIVE);
 -              reserve_bootmem_node(pgdat, 0xa2000000, 0x1000,
 -                              BOOTMEM_EXCLUSIVE);
 -      }
 -
 -      if (machine_is_palmt5())
 -              reserve_bootmem_node(pgdat, 0xa0200000, 0x1000,
 -                              BOOTMEM_EXCLUSIVE);
 -
 -      /*
 -       * U300 - This platform family can share physical memory
 -       * between two ARM cpus, one running Linux and the other
 -       * running another OS.
 -       */
 -      if (machine_is_u300()) {
 -#ifdef CONFIG_MACH_U300_SINGLE_RAM
 -#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) &&  \
 -      CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
 -              res_size = 0x00100000;
 -#endif
 -#endif
 -      }
 +      memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
  
  #ifdef CONFIG_SA1111
        /*
         * Because of the SA1111 DMA bug, we want to preserve our
         * precious DMA-able memory...
         */
 -      res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
 +      memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
  #endif
 -      if (res_size)
 -              reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size,
 -                              BOOTMEM_DEFAULT);
  }
  
  /*
@@@ -875,7 -953,7 +888,7 @@@ static void __init devicemaps_init(stru
        /*
         * Allocate the vector page early.
         */
 -      vectors = alloc_bootmem_low_pages(PAGE_SIZE);
 +      vectors = early_alloc(PAGE_SIZE);
  
        for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
                pmd_clear(pmd_off_k(addr));
  static void __init kmap_init(void)
  {
  #ifdef CONFIG_HIGHMEM
 -      pmd_t *pmd = pmd_off_k(PKMAP_BASE);
 -      pte_t *pte = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t));
 -      BUG_ON(!pmd_none(*pmd) || !pte);
 -      __pmd_populate(pmd, __pa(pte) | _PAGE_KERNEL_TABLE);
 -      pkmap_page_table = pte + PTRS_PER_PTE;
 +      pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE),
 +              PKMAP_BASE, _PAGE_KERNEL_TABLE);
  #endif
  }
  
@@@ -998,16 -1079,17 +1011,16 @@@ void __init paging_init(struct machine_
        sanity_check_meminfo();
        prepare_page_table();
        map_lowmem();
 -      bootmem_init();
        devicemaps_init(mdesc);
        kmap_init();
  
        top_pmd = pmd_off_k(0xffff0000);
  
 -      /*
 -       * allocate the zero page.  Note that this always succeeds and
 -       * returns a zeroed result.
 -       */
 -      zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
 +      /* allocate the zero page. */
 +      zero_page = early_alloc(PAGE_SIZE);
 +
 +      bootmem_init();
 +
        empty_zero_page = virt_to_page(zero_page);
        __flush_dcache_page(NULL, empty_zero_page);
  }