aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memblock.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memblock.c')
-rw-r--r--mm/memblock.c68
1 files changed, 58 insertions, 10 deletions
diff --git a/mm/memblock.c b/mm/memblock.c
index 952123eba433..d4382095f8bd 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -184,7 +184,24 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
184 } 184 }
185} 185}
186 186
187static int __init_memblock memblock_double_array(struct memblock_type *type) 187/**
188 * memblock_double_array - double the size of the memblock regions array
189 * @type: memblock type of the regions array being doubled
190 * @new_area_start: starting address of memory range to avoid overlap with
191 * @new_area_size: size of memory range to avoid overlap with
192 *
193 * Double the size of the @type regions array. If memblock is being used to
194 * allocate memory for a new reserved regions array and there is a previously
195 * allocated memory range [@new_area_start,@new_area_start+@new_area_size]
196 * waiting to be reserved, ensure the memory used by the new array does
197 * not overlap.
198 *
199 * RETURNS:
200 * 0 on success, -1 on failure.
201 */
202static int __init_memblock memblock_double_array(struct memblock_type *type,
203 phys_addr_t new_area_start,
204 phys_addr_t new_area_size)
188{ 205{
189 struct memblock_region *new_array, *old_array; 206 struct memblock_region *new_array, *old_array;
190 phys_addr_t old_size, new_size, addr; 207 phys_addr_t old_size, new_size, addr;
@@ -222,7 +239,18 @@ static int __init_memblock memblock_double_array(struct memblock_type *type)
222 new_array = kmalloc(new_size, GFP_KERNEL); 239 new_array = kmalloc(new_size, GFP_KERNEL);
223 addr = new_array ? __pa(new_array) : 0; 240 addr = new_array ? __pa(new_array) : 0;
224 } else { 241 } else {
225 addr = memblock_find_in_range(0, MEMBLOCK_ALLOC_ACCESSIBLE, new_size, sizeof(phys_addr_t)); 242 /* only exclude range when trying to double reserved.regions */
243 if (type != &memblock.reserved)
244 new_area_start = new_area_size = 0;
245
246 addr = memblock_find_in_range(new_area_start + new_area_size,
247 memblock.current_limit,
248 new_size, sizeof(phys_addr_t));
249 if (!addr && new_area_size)
250 addr = memblock_find_in_range(0,
251 min(new_area_start, memblock.current_limit),
252 new_size, sizeof(phys_addr_t));
253
226 new_array = addr ? __va(addr) : 0; 254 new_array = addr ? __va(addr) : 0;
227 } 255 }
228 if (!addr) { 256 if (!addr) {
@@ -399,7 +427,7 @@ repeat:
399 */ 427 */
400 if (!insert) { 428 if (!insert) {
401 while (type->cnt + nr_new > type->max) 429 while (type->cnt + nr_new > type->max)
402 if (memblock_double_array(type) < 0) 430 if (memblock_double_array(type, obase, size) < 0)
403 return -ENOMEM; 431 return -ENOMEM;
404 insert = true; 432 insert = true;
405 goto repeat; 433 goto repeat;
@@ -450,7 +478,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type,
450 478
451 /* we'll create at most two more regions */ 479 /* we'll create at most two more regions */
452 while (type->cnt + 2 > type->max) 480 while (type->cnt + 2 > type->max)
453 if (memblock_double_array(type) < 0) 481 if (memblock_double_array(type, base, size) < 0)
454 return -ENOMEM; 482 return -ENOMEM;
455 483
456 for (i = 0; i < type->cnt; i++) { 484 for (i = 0; i < type->cnt; i++) {
@@ -540,9 +568,9 @@ int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
540 * __next_free_mem_range - next function for for_each_free_mem_range() 568 * __next_free_mem_range - next function for for_each_free_mem_range()
541 * @idx: pointer to u64 loop variable 569 * @idx: pointer to u64 loop variable
542 * @nid: nid: node selector, %MAX_NUMNODES for all nodes 570 * @nid: nid: node selector, %MAX_NUMNODES for all nodes
543 * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL 571 * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
544 * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL 572 * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
545 * @p_nid: ptr to int for nid of the range, can be %NULL 573 * @out_nid: ptr to int for nid of the range, can be %NULL
546 * 574 *
547 * Find the first free area from *@idx which matches @nid, fill the out 575 * Find the first free area from *@idx which matches @nid, fill the out
548 * parameters, and update *@idx for the next iteration. The lower 32bit of 576 * parameters, and update *@idx for the next iteration. The lower 32bit of
@@ -616,9 +644,9 @@ void __init_memblock __next_free_mem_range(u64 *idx, int nid,
616 * __next_free_mem_range_rev - next function for for_each_free_mem_range_reverse() 644 * __next_free_mem_range_rev - next function for for_each_free_mem_range_reverse()
617 * @idx: pointer to u64 loop variable 645 * @idx: pointer to u64 loop variable
618 * @nid: nid: node selector, %MAX_NUMNODES for all nodes 646 * @nid: nid: node selector, %MAX_NUMNODES for all nodes
619 * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL 647 * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
620 * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL 648 * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
621 * @p_nid: ptr to int for nid of the range, can be %NULL 649 * @out_nid: ptr to int for nid of the range, can be %NULL
622 * 650 *
623 * Reverse of __next_free_mem_range(). 651 * Reverse of __next_free_mem_range().
624 */ 652 */
@@ -867,6 +895,16 @@ int __init_memblock memblock_is_memory(phys_addr_t addr)
867 return memblock_search(&memblock.memory, addr) != -1; 895 return memblock_search(&memblock.memory, addr) != -1;
868} 896}
869 897
898/**
899 * memblock_is_region_memory - check if a region is a subset of memory
900 * @base: base of region to check
901 * @size: size of region to check
902 *
903 * Check if the region [@base, @base+@size) is a subset of a memory block.
904 *
905 * RETURNS:
906 * 0 if false, non-zero if true
907 */
870int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size) 908int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
871{ 909{
872 int idx = memblock_search(&memblock.memory, base); 910 int idx = memblock_search(&memblock.memory, base);
@@ -879,6 +917,16 @@ int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size
879 memblock.memory.regions[idx].size) >= end; 917 memblock.memory.regions[idx].size) >= end;
880} 918}
881 919
920/**
921 * memblock_is_region_reserved - check if a region intersects reserved memory
922 * @base: base of region to check
923 * @size: size of region to check
924 *
925 * Check if the region [@base, @base+@size) intersects a reserved memory block.
926 *
927 * RETURNS:
928 * 0 if false, non-zero if true
929 */
882int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size) 930int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
883{ 931{
884 memblock_cap_size(base, &size); 932 memblock_cap_size(base, &size);