Merge tag 'v3.10.86' into linux-linaro-lsk-v3.10
[firefly-linux-kernel-4.4.55.git] / arch / arm64 / mm / init.c
index 5c5516611b5e5fbbd68dd7ed6f080be4b5168a9d..67ad3c079ae6497ffbbc2593511da64c5e207765 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/memblock.h>
 #include <linux/sort.h>
 #include <linux/of_fdt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
 
 #include <asm/prom.h>
 #include <asm/sections.h>
@@ -44,8 +46,7 @@ static unsigned long phys_initrd_size __initdata = 0;
 
 phys_addr_t memstart_addr __read_mostly = 0;
 
-void __init early_init_dt_setup_initrd_arch(unsigned long start,
-                                           unsigned long end)
+void __init early_init_dt_setup_initrd_arch(u64 start, u64 end)
 {
        phys_initrd_start = start;
        phys_initrd_size = end - start;
@@ -67,22 +68,31 @@ static int __init early_initrd(char *p)
 }
 early_param("initrd", early_initrd);
 
-#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
+/*
+ * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
+ * currently assumes that for memory starting above 4G, 32-bit devices will
+ * use a DMA offset.
+ */
+static phys_addr_t max_zone_dma_phys(void)
+{
+       phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
+       return min(offset + (1ULL << 32), memblock_end_of_DRAM());
+}
 
 static void __init zone_sizes_init(unsigned long min, unsigned long max)
 {
        struct memblock_region *reg;
        unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
-       unsigned long max_dma32 = min;
+       unsigned long max_dma = min;
 
        memset(zone_size, 0, sizeof(zone_size));
 
-#ifdef CONFIG_ZONE_DMA32
        /* 4GB maximum for 32-bit only capable devices */
-       max_dma32 = max(min, min(max, MAX_DMA32_PFN));
-       zone_size[ZONE_DMA32] = max_dma32 - min;
-#endif
-       zone_size[ZONE_NORMAL] = max - max_dma32;
+       if (IS_ENABLED(CONFIG_ZONE_DMA)) {
+               max_dma = PFN_DOWN(max_zone_dma_phys());
+               zone_size[ZONE_DMA] = max_dma - min;
+       }
+       zone_size[ZONE_NORMAL] = max - max_dma;
 
        memcpy(zhole_size, zone_size, sizeof(zhole_size));
 
@@ -92,15 +102,15 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 
                if (start >= max)
                        continue;
-#ifdef CONFIG_ZONE_DMA32
-               if (start < max_dma32) {
-                       unsigned long dma_end = min(end, max_dma32);
-                       zhole_size[ZONE_DMA32] -= dma_end - start;
+
+               if (IS_ENABLED(CONFIG_ZONE_DMA) && start < max_dma) {
+                       unsigned long dma_end = min(end, max_dma);
+                       zhole_size[ZONE_DMA] -= dma_end - start;
                }
-#endif
-               if (end > max_dma32) {
+
+               if (end > max_dma) {
                        unsigned long normal_end = min(end, max);
-                       unsigned long normal_start = max(start, max_dma32);
+                       unsigned long normal_start = max(start, max_dma);
                        zhole_size[ZONE_NORMAL] -= normal_end - normal_start;
                }
        }
@@ -131,11 +141,34 @@ static void arm64_memory_present(void)
 }
 #endif
 
+static phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX;
+
+/*
+ * Limit the memory size that was specified via FDT.
+ */
+static int __init early_mem(char *p)
+{
+       if (!p)
+               return 1;
+
+       memory_limit = memparse(p, &p) & PAGE_MASK;
+       pr_notice("Memory limited to %lldMB\n", memory_limit >> 20);
+
+       return 0;
+}
+early_param("mem", early_mem);
+
 void __init arm64_memblock_init(void)
 {
        u64 *reserve_map, base, size;
+       phys_addr_t dma_phys_limit = 0;
 
-       /* Register the kernel text, kernel data and initrd with memblock */
+       memblock_enforce_memory_limit(memory_limit);
+
+       /*
+        * Register the kernel text, kernel data, initrd, and initial
+        * pagetables with memblock.
+        */
        memblock_reserve(__pa(_text), _end - _text);
 #ifdef CONFIG_BLK_DEV_INITRD
        if (phys_initrd_size) {
@@ -147,13 +180,6 @@ void __init arm64_memblock_init(void)
        }
 #endif
 
-       /*
-        * Reserve the page tables.  These are already in use,
-        * and can only be in node 0.
-        */
-       memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE);
-       memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE);
-
        /* Reserve the dtb region */
        memblock_reserve(virt_to_phys(initial_boot_params),
                         be32_to_cpu(initial_boot_params->totalsize));
@@ -173,6 +199,13 @@ void __init arm64_memblock_init(void)
                memblock_reserve(base, size);
        }
 
+       early_init_fdt_scan_reserved_mem();
+
+       /* 4GB maximum for 32-bit only capable devices */
+       if (IS_ENABLED(CONFIG_ZONE_DMA))
+               dma_phys_limit = max_zone_dma_phys();
+       dma_contiguous_reserve(dma_phys_limit);
+
        memblock_allow_resize();
        memblock_dump_all();
 }
@@ -283,8 +316,6 @@ void __init mem_init(void)
        unsigned long reserved_pages, free_pages;
        struct memblock_region *reg;
 
-       arm64_swiotlb_init();
-
        max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP