mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 19:51:31 -04:00
mm: page_alloc: skip over regions of invalid pfns where possible
When using a sparse memory model memmap_init_zone() when invoked with the MEMMAP_EARLY context will skip over pages which aren't valid - ie. which aren't in a populated region of the sparse memory map. However if the memory map is extremely sparse then it can spend a long time linearly checking each PFN in a large non-populated region of the memory map & skipping it in turn. When CONFIG_HAVE_MEMBLOCK_NODE_MAP is enabled, we have sufficient information to quickly discover the next valid PFN given an invalid one by searching through the list of memory regions & skipping forwards to the first PFN covered by the memory region to the right of the non-populated region. Implement this in order to speed up memmap_init_zone() for systems with extremely sparse memory maps. James said "I have tested this patch on a virtual model of a Samurai CPU with a sparse memory map. The kernel boot time drops from 109 to 62 seconds. " Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Paul Burton <[email protected]> Tested-by: James Hartley <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
7f354a548d
commit
b92df1de5d
3 changed files with 36 additions and 1 deletions
|
|
@ -1105,6 +1105,31 @@ void __init_memblock __next_mem_pfn_range(int *idx, int nid,
|
|||
*out_nid = r->nid;
|
||||
}
|
||||
|
||||
unsigned long __init_memblock memblock_next_valid_pfn(unsigned long pfn,
|
||||
unsigned long max_pfn)
|
||||
{
|
||||
struct memblock_type *type = &memblock.memory;
|
||||
unsigned int right = type->cnt;
|
||||
unsigned int mid, left = 0;
|
||||
phys_addr_t addr = PFN_PHYS(pfn + 1);
|
||||
|
||||
do {
|
||||
mid = (right + left) / 2;
|
||||
|
||||
if (addr < type->regions[mid].base)
|
||||
right = mid;
|
||||
else if (addr >= (type->regions[mid].base +
|
||||
type->regions[mid].size))
|
||||
left = mid + 1;
|
||||
else {
|
||||
/* addr is within the region, so pfn + 1 is valid */
|
||||
return min(pfn + 1, max_pfn);
|
||||
}
|
||||
} while (left < right);
|
||||
|
||||
return min(PHYS_PFN(type->regions[right].base), max_pfn);
|
||||
}
|
||||
|
||||
/**
|
||||
* memblock_set_node - set node ID on memblock regions
|
||||
* @base: base of area to set node ID for
|
||||
|
|
|
|||
Loading…
Reference in a new issue