diff options
Diffstat (limited to 'arch/ia64/mm')
-rw-r--r-- | arch/ia64/mm/contig.c | 16 | ||||
-rw-r--r-- | arch/ia64/mm/discontig.c | 84 | ||||
-rw-r--r-- | arch/ia64/mm/init.c | 55 | ||||
-rw-r--r-- | arch/ia64/mm/ioremap.c | 6 |
4 files changed, 86 insertions, 75 deletions
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 2a88cdd6d924..e004143ba86b 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -27,6 +27,7 @@ #ifdef CONFIG_VIRTUAL_MEM_MAP static unsigned long num_dma_physpages; +static unsigned long max_gap; #endif /** @@ -45,9 +46,15 @@ show_mem (void) printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); i = max_mapnr; - while (i-- > 0) { - if (!pfn_valid(i)) + for (i = 0; i < max_mapnr; i++) { + if (!pfn_valid(i)) { +#ifdef CONFIG_VIRTUAL_MEM_MAP + if (max_gap < LARGE_GAP) + continue; + i = vmemmap_find_next_valid_pfn(0, i) - 1; +#endif continue; + } total++; if (PageReserved(mem_map+i)) reserved++; @@ -234,7 +241,6 @@ paging_init (void) unsigned long zones_size[MAX_NR_ZONES]; #ifdef CONFIG_VIRTUAL_MEM_MAP unsigned long zholes_size[MAX_NR_ZONES]; - unsigned long max_gap; #endif /* initialize mem_map[] */ @@ -266,7 +272,6 @@ paging_init (void) } } - max_gap = 0; efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); if (max_gap < LARGE_GAP) { vmem_map = (struct page *) 0; @@ -277,7 +282,8 @@ paging_init (void) /* allocate virtual_mem_map */ - map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page)); + map_size = PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * + sizeof(struct page)); vmalloc_end -= map_size; vmem_map = (struct page *) vmalloc_end; efi_memmap_walk(create_mem_map_page_table, NULL); diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 525b082eb661..d260bffa01ab 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -313,9 +313,19 @@ static void __meminit scatter_node_data(void) pg_data_t **dst; int node; - for_each_online_node(node) { - dst = LOCAL_DATA_ADDR(pgdat_list[node])->pg_data_ptrs; - memcpy(dst, pgdat_list, sizeof(pgdat_list)); + /* + * for_each_online_node() can't be used at here. + * node_online_map is not set for hot-added nodes at this time, + * because we are halfway through initialization of the new node's + * structures. If for_each_online_node() is used, a new node's + * pg_data_ptrs will be not initialized. Insted of using it, + * pgdat_list[] is checked. + */ + for_each_node(node) { + if (pgdat_list[node]) { + dst = LOCAL_DATA_ADDR(pgdat_list[node])->pg_data_ptrs; + memcpy(dst, pgdat_list, sizeof(pgdat_list)); + } } } @@ -524,68 +534,6 @@ void __cpuinit *per_cpu_init(void) } #endif /* CONFIG_SMP */ -#ifdef CONFIG_VIRTUAL_MEM_MAP -static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i) -{ - unsigned long end_address, hole_next_pfn; - unsigned long stop_address; - - 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; -} -#else -static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i) -{ - return i + 1; -} -#endif - /** * show_mem - give short summary of memory stats * @@ -615,7 +563,8 @@ void show_mem(void) if (pfn_valid(pgdat->node_start_pfn + i)) page = pfn_to_page(pgdat->node_start_pfn + i); else { - i = find_next_valid_pfn_for_pgdat(pgdat, i) - 1; + i = vmemmap_find_next_valid_pfn(pgdat->node_id, + i) - 1; continue; } if (PageReserved(page)) @@ -741,7 +690,8 @@ void __init paging_init(void) efi_memmap_walk(filter_rsvd_memory, count_node_pages); #ifdef CONFIG_VIRTUAL_MEM_MAP - vmalloc_end -= PAGE_ALIGN(max_low_pfn * sizeof(struct page)); + vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) * + sizeof(struct page)); vmem_map = (struct page *) vmalloc_end; efi_memmap_walk(create_mem_map_page_table, NULL); printk("Virtual mem_map starts at 0x%p\n", vmem_map); 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) diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c index 07bd02b6c372..4280c074d64e 100644 --- a/arch/ia64/mm/ioremap.c +++ b/arch/ia64/mm/ioremap.c @@ -32,7 +32,7 @@ ioremap (unsigned long offset, unsigned long size) */ attr = kern_mem_attribute(offset, size); if (attr & EFI_MEMORY_WB) - return phys_to_virt(offset); + return (void __iomem *) phys_to_virt(offset); else if (attr & EFI_MEMORY_UC) return __ioremap(offset, size); @@ -43,7 +43,7 @@ ioremap (unsigned long offset, unsigned long size) gran_base = GRANULEROUNDDOWN(offset); gran_size = GRANULEROUNDUP(offset + size) - gran_base; if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB) - return phys_to_virt(offset); + return (void __iomem *) phys_to_virt(offset); return __ioremap(offset, size); } @@ -53,7 +53,7 @@ void __iomem * ioremap_nocache (unsigned long offset, unsigned long size) { if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB) - return 0; + return NULL; return __ioremap(offset, size); } |