diff options
author | Bob Picco <bob.picco@hp.com> | 2006-06-28 12:55:43 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2006-08-03 13:13:23 -0400 |
commit | e44e41d0c832ebbda7311a1fe43584d844026357 (patch) | |
tree | 05a8ac85029b041db8defef35bf808d431bb3528 /arch/ia64/mm/init.c | |
parent | 921eea1cdf6ce7f0db88e4579474a04b1fb0fe6d (diff) |
[IA64] fix show_mem for VIRTUAL_MEM_MAP+FLATMEM
contig.c (FLATMEM) requires the same optimization as in discontig.c for show_mem
when VIRTUAL_MEM_MAP is in use. Otherwise FLATMEM has softlockup timeouts.
This was boot tested for memory configuration: SPARSEMEM,
DISCONTIG+VIRTUAL_MEM_MAP, FLATMEM, FLATMEM+VIRTUAL_MEM_MAP and
FLATMEM+VIRTUAL_MEM_MAP with largest memory gap less than LARGE_GAP by
using boot parameter "mem=".
This was boot tested and "echo m >/proc/sysrq-trigger" output evaluated for
: FLATMEM, FLATMEM+VIRTUAL_MEM_MAP, DISCONTIGMEM+VIRTUAL_MEM_MAP and
SPARSEMEM.
Signed-off-by: Bob Picco <bob.picco@hp.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
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) | |||
415 | } | 415 | } |
416 | 416 | ||
417 | #ifdef CONFIG_VIRTUAL_MEM_MAP | 417 | #ifdef CONFIG_VIRTUAL_MEM_MAP |
418 | int vmemmap_find_next_valid_pfn(int node, int i) | ||
419 | { | ||
420 | unsigned long end_address, hole_next_pfn; | ||
421 | unsigned long stop_address; | ||
422 | pg_data_t *pgdat = NODE_DATA(node); | ||
423 | |||
424 | end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i]; | ||
425 | end_address = PAGE_ALIGN(end_address); | ||
426 | |||
427 | stop_address = (unsigned long) &vmem_map[ | ||
428 | pgdat->node_start_pfn + pgdat->node_spanned_pages]; | ||
429 | |||
430 | do { | ||
431 | pgd_t *pgd; | ||
432 | pud_t *pud; | ||
433 | pmd_t *pmd; | ||
434 | pte_t *pte; | ||
435 | |||
436 | pgd = pgd_offset_k(end_address); | ||
437 | if (pgd_none(*pgd)) { | ||
438 | end_address += PGDIR_SIZE; | ||
439 | continue; | ||
440 | } | ||
441 | |||
442 | pud = pud_offset(pgd, end_address); | ||
443 | if (pud_none(*pud)) { | ||
444 | end_address += PUD_SIZE; | ||
445 | continue; | ||
446 | } | ||
447 | |||
448 | pmd = pmd_offset(pud, end_address); | ||
449 | if (pmd_none(*pmd)) { | ||
450 | end_address += PMD_SIZE; | ||
451 | continue; | ||
452 | } | ||
453 | |||
454 | pte = pte_offset_kernel(pmd, end_address); | ||
455 | retry_pte: | ||
456 | if (pte_none(*pte)) { | ||
457 | end_address += PAGE_SIZE; | ||
458 | pte++; | ||
459 | if ((end_address < stop_address) && | ||
460 | (end_address != ALIGN(end_address, 1UL << PMD_SHIFT))) | ||
461 | goto retry_pte; | ||
462 | continue; | ||
463 | } | ||
464 | /* Found next valid vmem_map page */ | ||
465 | break; | ||
466 | } while (end_address < stop_address); | ||
467 | |||
468 | end_address = min(end_address, stop_address); | ||
469 | end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1; | ||
470 | hole_next_pfn = end_address / sizeof(struct page); | ||
471 | return hole_next_pfn - pgdat->node_start_pfn; | ||
472 | } | ||
418 | 473 | ||
419 | int __init | 474 | int __init |
420 | create_mem_map_page_table (u64 start, u64 end, void *arg) | 475 | create_mem_map_page_table (u64 start, u64 end, void *arg) |