[PATCH 03/21] MIPS memblock: Alter traditional add_memory_region() method

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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.lancer@xxxxxxxxx>
---
 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

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux