There is no safe and fast way to get rid of boot_mem_map usage in
the wide set of platform code. But it's luck, that the architecture
specific code doesn't make any direct changes in the boot_mem_map
structure. Additionally the platform specific code registers the
available memory using traditional add_memory_region() method.
It's obvious, that one needs to be modified adding regions to both
new memblock allocator and old boot_mem_map subsystem. In this way
most of architecture specific code won't be broken.

Signed-off-by: Serge Semin <fancer.lan...@gmail.com>
---
 arch/mips/kernel/setup.c | 51 ++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 084ba6c..9da6f8a 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -82,10 +82,19 @@ static struct resource data_resource = { .name = "Kernel 
data", };
 
 static void *detect_magic __initdata = detect_memory_region;
 
+/*
+ * General method to add RAM regions to the system
+ *
+ * NOTE Historically this method has been used to register memory blocks within
+ *      MIPS kernel code in the boot_mem_map array. So we need to support it
+ * up until it's discarded from platform-depended code.
+ * On the other hand it might be good to have it, since we can check regions
+ * before actually adding them
+ */
 void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type)
 {
        int x = boot_mem_map.nr_map;
-       int i;
+       int ret, i;
 
        /*
         * If the region reaches the top of the physical address space, adjust
@@ -94,15 +103,51 @@ void __init add_memory_region(phys_addr_t start, 
phys_addr_t size, long type)
        if (start + size - 1 == (phys_addr_t)ULLONG_MAX)
                --size;
 
-       /* Sanity check */
+       /* Sanity check the region */
        if (start + size < start) {
                pr_warn("Trying to add an invalid memory region, skipped\n");
                return;
        }
 
+       /* Make sure the type is supported */
+       if (type != BOOT_MEM_RAM && type != BOOT_MEM_INIT_RAM &&
+           type != BOOT_MEM_ROM_DATA && type != BOOT_MEM_RESERVED) {
+               pr_warn("Invalid type of memory region, skipped\n");
+               return;
+       }
+
        /*
-        * Try to merge with existing entry, if any.
+        * According to the request_resource logic RAM, INIT and ROM shouldn't
+        * intersect each other but being subset of one memory space
         */
+       if (type != BOOT_MEM_RESERVED && memblock_is_memory(start)) {
+               pr_warn("Drop already added memory region %08zx @ %pa\n",
+                       (size_t)size, &start);
+               return;
+       }
+
+       /*
+        * Add the region to the memblock allocator. Reserved regions should be
+        * in the memory as well to be actually reserved.
+        */
+       ret = memblock_add_node(start, size, 0);
+       if (ret < 0) {
+               pr_err("Could't add memblock %08zx @ %pa\n",
+                       (size_t)size, &start);
+               return;
+       }
+
+       /* Reserve memory region passed with the corresponding flags */
+       if (type != BOOT_MEM_RAM) {
+               ret = memblock_reserve(start, size);
+               if (ret < 0) {
+                       pr_err("Could't reserve memblock %08zx @ %pa\n",
+                               (size_t)size, &start);
+                       return;
+               }
+       }
+
+       /* Try to combine with existing entry, if any. */
        for (i = 0; i < boot_mem_map.nr_map; i++) {
                struct boot_mem_map_entry *entry = boot_mem_map.map + i;
                unsigned long top;
-- 
2.6.6

Reply via email to