of: fdt: Use IS_ENABLED(CONFIG_BLK_DEV_INITRD) instead of #ifdef
[linux-2.6-microblaze.git] / drivers / of / fdt.c
index e0f96e3..a261990 100644 (file)
@@ -8,6 +8,7 @@
 
 #define pr_fmt(fmt)    "OF: fdt: " fmt
 
+#include <linux/crash_dump.h>
 #include <linux/crc32.h>
 #include <linux/kernel.h>
 #include <linux/initrd.h>
@@ -193,16 +194,12 @@ static void populate_properties(const void *blob,
                        pp->length = len;
                        pp->value  = pp + 1;
                        *pprev     = pp;
-                       pprev      = &pp->next;
                        memcpy(pp->value, ps, len - 1);
                        ((char *)pp->value)[len - 1] = 0;
                        pr_debug("fixed up name for %s -> %s\n",
                                 nodename, (char *)pp->value);
                }
        }
-
-       if (!dryrun)
-               *pprev = NULL;
 }
 
 static int populate_node(const void *blob,
@@ -479,6 +476,22 @@ void *initial_boot_params __ro_after_init;
 
 static u32 of_fdt_crc32;
 
+static int __init early_init_dt_reserve_memory_arch(phys_addr_t base,
+                                       phys_addr_t size, bool nomap)
+{
+       if (nomap) {
+               /*
+                * If the memory is already reserved (by another region), we
+                * should not allow it to be marked nomap.
+                */
+               if (memblock_is_region_reserved(base, size))
+                       return -EBUSY;
+
+               return memblock_mark_nomap(base, size);
+       }
+       return memblock_reserve(base, size);
+}
+
 /*
  * __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property
  */
@@ -585,6 +598,30 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
        return 0;
 }
 
+/*
+ * reserve_elfcorehdr() - reserves memory for elf core header
+ *
+ * This function reserves the memory occupied by an elf core header
+ * described in the device tree. This region contains all the
+ * information about primary kernel's core image and is used by a dump
+ * capture kernel to access the system memory on primary kernel.
+ */
+static void __init reserve_elfcorehdr(void)
+{
+       if (!IS_ENABLED(CONFIG_CRASH_DUMP) || !elfcorehdr_size)
+               return;
+
+       if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) {
+               pr_warn("elfcorehdr is overlapped\n");
+               return;
+       }
+
+       memblock_reserve(elfcorehdr_addr, elfcorehdr_size);
+
+       pr_info("Reserving %llu KiB of memory at 0x%llx for elfcorehdr\n",
+               elfcorehdr_size >> 10, elfcorehdr_addr);
+}
+
 /**
  * early_init_fdt_scan_reserved_mem() - create reserved memory regions
  *
@@ -610,6 +647,7 @@ void __init early_init_fdt_scan_reserved_mem(void)
 
        of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);
        fdt_init_reserved_mem();
+       reserve_elfcorehdr();
 }
 
 /**
@@ -858,7 +896,6 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
        return best_data;
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
 static void __early_init_dt_declare_initrd(unsigned long start,
                                           unsigned long end)
 {
@@ -884,6 +921,9 @@ static void __init early_init_dt_check_for_initrd(unsigned long node)
        int len;
        const __be32 *prop;
 
+       if (!IS_ENABLED(CONFIG_BLK_DEV_INITRD))
+               return;
+
        pr_debug("Looking for initrd properties... ");
 
        prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
@@ -902,11 +942,58 @@ static void __init early_init_dt_check_for_initrd(unsigned long node)
 
        pr_debug("initrd_start=0x%llx  initrd_end=0x%llx\n", start, end);
 }
-#else
-static inline void early_init_dt_check_for_initrd(unsigned long node)
+
+/**
+ * early_init_dt_check_for_elfcorehdr - Decode elfcorehdr location from flat
+ * tree
+ * @node: reference to node containing elfcorehdr location ('chosen')
+ */
+static void __init early_init_dt_check_for_elfcorehdr(unsigned long node)
+{
+       const __be32 *prop;
+       int len;
+
+       if (!IS_ENABLED(CONFIG_CRASH_DUMP))
+               return;
+
+       pr_debug("Looking for elfcorehdr property... ");
+
+       prop = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len);
+       if (!prop || (len < (dt_root_addr_cells + dt_root_size_cells)))
+               return;
+
+       elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, &prop);
+       elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+       pr_debug("elfcorehdr_start=0x%llx elfcorehdr_size=0x%llx\n",
+                elfcorehdr_addr, elfcorehdr_size);
+}
+
+static phys_addr_t cap_mem_addr;
+static phys_addr_t cap_mem_size;
+
+/**
+ * early_init_dt_check_for_usable_mem_range - Decode usable memory range
+ * location from flat tree
+ * @node: reference to node containing usable memory range location ('chosen')
+ */
+static void __init early_init_dt_check_for_usable_mem_range(unsigned long node)
 {
+       const __be32 *prop;
+       int len;
+
+       pr_debug("Looking for usable-memory-range property... ");
+
+       prop = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len);
+       if (!prop || (len < (dt_root_addr_cells + dt_root_size_cells)))
+               return;
+
+       cap_mem_addr = dt_mem_next_cell(dt_root_addr_cells, &prop);
+       cap_mem_size = dt_mem_next_cell(dt_root_size_cells, &prop);
+
+       pr_debug("cap_mem_start=%pa cap_mem_size=%pa\n", &cap_mem_addr,
+                &cap_mem_size);
 }
-#endif /* CONFIG_BLK_DEV_INITRD */
 
 #ifdef CONFIG_SERIAL_EARLYCON
 
@@ -1033,7 +1120,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
                if (!hotpluggable)
                        continue;
 
-               if (early_init_dt_mark_hotplug_memory_arch(base, size))
+               if (memblock_mark_hotplug(base, size))
                        pr_warn("failed to mark hotplug range 0x%llx - 0x%llx\n",
                                base, base + size);
        }
@@ -1055,6 +1142,8 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
                return 0;
 
        early_init_dt_check_for_initrd(node);
+       early_init_dt_check_for_elfcorehdr(node);
+       early_init_dt_check_for_usable_mem_range(node);
 
        /* Retrieve command line */
        p = of_get_flat_dt_prop(node, "bootargs", &l);
@@ -1146,27 +1235,6 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
        memblock_add(base, size);
 }
 
-int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size)
-{
-       return memblock_mark_hotplug(base, size);
-}
-
-int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
-                                       phys_addr_t size, bool nomap)
-{
-       if (nomap) {
-               /*
-                * If the memory is already reserved (by another region), we
-                * should not allow it to be marked nomap.
-                */
-               if (memblock_is_region_reserved(base, size))
-                       return -EBUSY;
-
-               return memblock_mark_nomap(base, size);
-       }
-       return memblock_reserve(base, size);
-}
-
 static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
 {
        void *ptr = memblock_alloc(size, align);
@@ -1199,16 +1267,19 @@ void __init early_init_dt_scan_nodes(void)
 {
        int rc = 0;
 
+       /* Initialize {size,address}-cells info */
+       of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
        /* Retrieve various information from the /chosen node */
        rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
        if (!rc)
                pr_warn("No chosen node found, continuing without\n");
 
-       /* Initialize {size,address}-cells info */
-       of_scan_flat_dt(early_init_dt_scan_root, NULL);
-
        /* Setup memory, calling early_init_dt_add_memory_arch */
        of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+       /* Handle linux,usable-memory-range property */
+       memblock_cap_memory_range(cap_mem_addr, cap_mem_size);
 }
 
 bool __init early_init_dt_scan(void *params)