|
@@ -184,7 +184,24 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int __init_memblock memblock_double_array(struct memblock_type *type)
|
|
|
+/**
|
|
|
+ * memblock_double_array - double the size of the memblock regions array
|
|
|
+ * @type: memblock type of the regions array being doubled
|
|
|
+ * @new_area_start: starting address of memory range to avoid overlap with
|
|
|
+ * @new_area_size: size of memory range to avoid overlap with
|
|
|
+ *
|
|
|
+ * Double the size of the @type regions array. If memblock is being used to
|
|
|
+ * allocate memory for a new reserved regions array and there is a previously
|
|
|
+ * allocated memory range [@new_area_start,@new_area_start+@new_area_size]
|
|
|
+ * waiting to be reserved, ensure the memory used by the new array does
|
|
|
+ * not overlap.
|
|
|
+ *
|
|
|
+ * RETURNS:
|
|
|
+ * 0 on success, -1 on failure.
|
|
|
+ */
|
|
|
+static int __init_memblock memblock_double_array(struct memblock_type *type,
|
|
|
+ phys_addr_t new_area_start,
|
|
|
+ phys_addr_t new_area_size)
|
|
|
{
|
|
|
struct memblock_region *new_array, *old_array;
|
|
|
phys_addr_t old_size, new_size, addr;
|
|
@@ -222,7 +239,18 @@ static int __init_memblock memblock_double_array(struct memblock_type *type)
|
|
|
new_array = kmalloc(new_size, GFP_KERNEL);
|
|
|
addr = new_array ? __pa(new_array) : 0;
|
|
|
} else {
|
|
|
- addr = memblock_find_in_range(0, MEMBLOCK_ALLOC_ACCESSIBLE, new_size, sizeof(phys_addr_t));
|
|
|
+ /* only exclude range when trying to double reserved.regions */
|
|
|
+ if (type != &memblock.reserved)
|
|
|
+ new_area_start = new_area_size = 0;
|
|
|
+
|
|
|
+ addr = memblock_find_in_range(new_area_start + new_area_size,
|
|
|
+ memblock.current_limit,
|
|
|
+ new_size, sizeof(phys_addr_t));
|
|
|
+ if (!addr && new_area_size)
|
|
|
+ addr = memblock_find_in_range(0,
|
|
|
+ min(new_area_start, memblock.current_limit),
|
|
|
+ new_size, sizeof(phys_addr_t));
|
|
|
+
|
|
|
new_array = addr ? __va(addr) : 0;
|
|
|
}
|
|
|
if (!addr) {
|
|
@@ -399,7 +427,7 @@ repeat:
|
|
|
*/
|
|
|
if (!insert) {
|
|
|
while (type->cnt + nr_new > type->max)
|
|
|
- if (memblock_double_array(type) < 0)
|
|
|
+ if (memblock_double_array(type, obase, size) < 0)
|
|
|
return -ENOMEM;
|
|
|
insert = true;
|
|
|
goto repeat;
|
|
@@ -450,7 +478,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,
|
|
|
|
|
|
/* we'll create at most two more regions */
|
|
|
while (type->cnt + 2 > type->max)
|
|
|
- if (memblock_double_array(type) < 0)
|
|
|
+ if (memblock_double_array(type, base, size) < 0)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
for (i = 0; i < type->cnt; i++) {
|