Commit 0ec7ec75 authored by Ralf Baechle's avatar Ralf Baechle

MIPS: Merge overlapping bootmem ranges

Without this, we may end up with something like this in /proc/iomem:

01100000-014fffff : System RAM
  01100000-013bf48f : Kernel code
  013bf490-0149e01f : Kernel data
01500000-0c0fffff : System RAM

but the two System RAM ranges should be one single range.  This particular
case will result in kexec failure on Octeon systems if the kernel being
loaded by kexec is bigger than the already running kernel.
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent f4a75d2e
...@@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", }; ...@@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", };
void __init add_memory_region(phys_t start, phys_t size, long type) void __init add_memory_region(phys_t start, phys_t size, long type)
{ {
int x = boot_mem_map.nr_map; int x = boot_mem_map.nr_map;
struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; int i;
/* Sanity check */ /* Sanity check */
if (start + size < start) { if (start + size < start) {
...@@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type) ...@@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
} }
/* /*
* Try to merge with previous entry if any. This is far less than * Try to merge with existing entry, if any.
* perfect but is sufficient for most real world cases.
*/ */
if (x && prev->addr + prev->size == start && prev->type == type) { for (i = 0; i < boot_mem_map.nr_map; i++) {
prev->size += size; struct boot_mem_map_entry *entry = boot_mem_map.map + i;
unsigned long top;
if (entry->type != type)
continue;
if (start + size < entry->addr)
continue; /* no overlap */
if (entry->addr + entry->size < start)
continue; /* no overlap */
top = max(entry->addr + entry->size, start + size);
entry->addr = min(entry->addr, start);
entry->size = top - entry->addr;
return; return;
} }
if (x == BOOT_MEM_MAP_MAX) { if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) {
pr_err("Ooops! Too many entries in the memory map!\n"); pr_err("Ooops! Too many entries in the memory map!\n");
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment