diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-08-03 12:50:20 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-08-03 12:50:20 -0700 |
commit | c31ca59e25f82879644088c97fe9cffbaa292786 (patch) | |
tree | eb1652fb3fe83d5aa2c943ec4e072ec6d775e424 /arch/ia64/mm/init.c | |
parent | fd60ae404f104f12369e654af9cf03b1f1047661 (diff) | |
parent | e44e41d0c832ebbda7311a1fe43584d844026357 (diff) | |
download | blackbird-obmc-linux-c31ca59e25f82879644088c97fe9cffbaa292786.tar.gz blackbird-obmc-linux-c31ca59e25f82879644088c97fe9cffbaa292786.zip |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6:
[IA64] fix show_mem for VIRTUAL_MEM_MAP+FLATMEM
[IA64] align high endpoint of VIRTUAL_MEM_MAP
[PATCH] Fix RAID5 + IA64 compile
[IA64] Don't alloc empty frame in ia64_switch_mode_phys
[IA64] Do not assume output registers be reservered.
[IA64] add platform check to snsc driver init
[IA64] sparse cleanups
[IA64] Fix breakage in simscsi.c
[IA64] Format /proc/pal/*/version_info correctly
Diffstat (limited to 'arch/ia64/mm/init.c')
-rw-r--r-- | arch/ia64/mm/init.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 2f50c064513c..30617ccb4f7e 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -415,6 +415,61 @@ ia64_mmu_init (void *my_cpu_data) } #ifdef CONFIG_VIRTUAL_MEM_MAP +int vmemmap_find_next_valid_pfn(int node, int i) +{ + unsigned long end_address, hole_next_pfn; + unsigned long stop_address; + pg_data_t *pgdat = NODE_DATA(node); + + end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i]; + end_address = PAGE_ALIGN(end_address); + + stop_address = (unsigned long) &vmem_map[ + pgdat->node_start_pfn + pgdat->node_spanned_pages]; + + do { + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + + pgd = pgd_offset_k(end_address); + if (pgd_none(*pgd)) { + end_address += PGDIR_SIZE; + continue; + } + + pud = pud_offset(pgd, end_address); + if (pud_none(*pud)) { + end_address += PUD_SIZE; + continue; + } + + pmd = pmd_offset(pud, end_address); + if (pmd_none(*pmd)) { + end_address += PMD_SIZE; + continue; + } + + pte = pte_offset_kernel(pmd, end_address); +retry_pte: + if (pte_none(*pte)) { + end_address += PAGE_SIZE; + pte++; + if ((end_address < stop_address) && + (end_address != ALIGN(end_address, 1UL << PMD_SHIFT))) + goto retry_pte; + continue; + } + /* Found next valid vmem_map page */ + break; + } while (end_address < stop_address); + + end_address = min(end_address, stop_address); + end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1; + hole_next_pfn = end_address / sizeof(struct page); + return hole_next_pfn - pgdat->node_start_pfn; +} int __init create_mem_map_page_table (u64 start, u64 end, void *arg) |