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

From: Serge Semin
Date: Sun Dec 18 2016 - 21:26:14 EST


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