memblock: make memblock_find_in_range method private
[linux-2.6-microblaze.git] / arch / arm64 / mm / init.c
index 8490ed2..bf5b8a5 100644 (file)
@@ -74,6 +74,7 @@ phys_addr_t arm64_dma_phys_limit __ro_after_init;
 static void __init reserve_crashkernel(void)
 {
        unsigned long long crash_base, crash_size;
+       unsigned long long crash_max = arm64_dma_phys_limit;
        int ret;
 
        ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
@@ -84,33 +85,18 @@ static void __init reserve_crashkernel(void)
 
        crash_size = PAGE_ALIGN(crash_size);
 
-       if (crash_base == 0) {
-               /* Current arm64 boot protocol requires 2MB alignment */
-               crash_base = memblock_find_in_range(0, arm64_dma_phys_limit,
-                               crash_size, SZ_2M);
-               if (crash_base == 0) {
-                       pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
-                               crash_size);
-                       return;
-               }
-       } else {
-               /* User specifies base address explicitly. */
-               if (!memblock_is_region_memory(crash_base, crash_size)) {
-                       pr_warn("cannot reserve crashkernel: region is not memory\n");
-                       return;
-               }
+       /* User specifies base address explicitly. */
+       if (crash_base)
+               crash_max = crash_base + crash_size;
 
-               if (memblock_is_region_reserved(crash_base, crash_size)) {
-                       pr_warn("cannot reserve crashkernel: region overlaps reserved memory\n");
-                       return;
-               }
-
-               if (!IS_ALIGNED(crash_base, SZ_2M)) {
-                       pr_warn("cannot reserve crashkernel: base address is not 2MB aligned\n");
-                       return;
-               }
+       /* Current arm64 boot protocol requires 2MB alignment */
+       crash_base = memblock_phys_alloc_range(crash_size, SZ_2M,
+                                              crash_base, crash_max);
+       if (!crash_base) {
+               pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
+                       crash_size);
+               return;
        }
-       memblock_reserve(crash_base, crash_size);
 
        pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
                crash_base, crash_base + crash_size, crash_size >> 20);
@@ -219,6 +205,43 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
        free_area_init(max_zone_pfns);
 }
 
+int pfn_valid(unsigned long pfn)
+{
+       phys_addr_t addr = PFN_PHYS(pfn);
+       struct mem_section *ms;
+
+       /*
+        * Ensure the upper PAGE_SHIFT bits are clear in the
+        * pfn. Else it might lead to false positives when
+        * some of the upper bits are set, but the lower bits
+        * match a valid pfn.
+        */
+       if (PHYS_PFN(addr) != pfn)
+               return 0;
+
+       if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+               return 0;
+
+       ms = __pfn_to_section(pfn);
+       if (!valid_section(ms))
+               return 0;
+
+       /*
+        * ZONE_DEVICE memory does not have the memblock entries.
+        * memblock_is_map_memory() check for ZONE_DEVICE based
+        * addresses will always fail. Even the normal hotplugged
+        * memory will never have MEMBLOCK_NOMAP flag set in their
+        * memblock entries. Skip memblock search for all non early
+        * memory sections covering all of hotplug memory including
+        * both normal and ZONE_DEVICE based.
+        */
+       if (!early_section(ms))
+               return pfn_section_valid(ms, pfn);
+
+       return memblock_is_memory(addr);
+}
+EXPORT_SYMBOL(pfn_valid);
+
 int pfn_is_map_memory(unsigned long pfn)
 {
        phys_addr_t addr = PFN_PHYS(pfn);