diff options
Diffstat (limited to 'arch/arm/mm')
48 files changed, 679 insertions, 600 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ed15f876c72..330814d1ee2 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -735,6 +735,14 @@ config CACHE_FEROCEON_L2 help This option enables the Feroceon L2 cache controller. +config CACHE_FEROCEON_L2_WRITETHROUGH + bool "Force Feroceon L2 cache write through" + depends on CACHE_FEROCEON_L2 + default n + help + Say Y here to use the Feroceon L2 cache in writethrough mode. + Unless you specifically require this, say N for writeback mode. + config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 2e27a8c8372..480f78a3611 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux arm-specific parts of the memory manager. # -obj-y := consistent.o extable.o fault.o init.o \ +obj-y := dma-mapping.o extable.o fault.o init.o \ iomap.o obj-$(CONFIG_MMU) += fault-armv.o flush.o ioremap.o mmap.o \ diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S index eb90bce38e1..2e6dc040c65 100644 --- a/arch/arm/mm/abort-ev7.S +++ b/arch/arm/mm/abort-ev7.S @@ -30,3 +30,4 @@ ENTRY(v7_early_abort) * New designs should not need to patch up faults. */ mov pc, lr +ENDPROC(v7_early_abort) diff --git a/arch/arm/mm/abort-nommu.S b/arch/arm/mm/abort-nommu.S index a7cc7f9ee45..625e580945b 100644 --- a/arch/arm/mm/abort-nommu.S +++ b/arch/arm/mm/abort-nommu.S @@ -17,3 +17,4 @@ ENTRY(nommu_early_abort) mov r0, #0 @ clear r0, r1 (no FSR/FAR) mov r1, #0 mov pc, lr +ENDPROC(nommu_early_abort) diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index e162cca5917..133e65d166b 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -17,8 +17,8 @@ #include <linux/string.h> #include <linux/proc_fs.h> #include <linux/init.h> +#include <linux/uaccess.h> -#include <asm/uaccess.h> #include <asm/unaligned.h> #include "fault.h" diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index 7b5a25d8157..13cdae8b0d4 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -48,11 +48,12 @@ static inline void l2_clean_mva_range(unsigned long start, unsigned long end) * L2 is PIPT and range operations only do a TLB lookup on * the start address. */ - BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); + BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); - __asm__("mcr p15, 1, %0, c15, c9, 4" : : "r" (start)); - __asm__("mcr p15, 1, %0, c15, c9, 5" : : "r" (end)); + __asm__("mcr p15, 1, %0, c15, c9, 4\n\t" + "mcr p15, 1, %1, c15, c9, 5" + : : "r" (start), "r" (end)); raw_local_irq_restore(flags); } @@ -80,11 +81,12 @@ static inline void l2_inv_mva_range(unsigned long start, unsigned long end) * L2 is PIPT and range operations only do a TLB lookup on * the start address. */ - BUG_ON((start ^ end) & ~(PAGE_SIZE - 1)); + BUG_ON((start ^ end) >> PAGE_SHIFT); raw_local_irq_save(flags); - __asm__("mcr p15, 1, %0, c15, c11, 4" : : "r" (start)); - __asm__("mcr p15, 1, %0, c15, c11, 5" : : "r" (end)); + __asm__("mcr p15, 1, %0, c15, c11, 4\n\t" + "mcr p15, 1, %1, c15, c11, 5" + : : "r" (start), "r" (end)); raw_local_irq_restore(flags); } @@ -205,7 +207,7 @@ static void feroceon_l2_flush_range(unsigned long start, unsigned long end) * time. These are necessary because the L2 cache can only be enabled * or disabled while the L1 Dcache and Icache are both disabled. */ -static void __init invalidate_and_disable_dcache(void) +static int __init flush_and_disable_dcache(void) { u32 cr; @@ -217,7 +219,9 @@ static void __init invalidate_and_disable_dcache(void) flush_cache_all(); set_cr(cr & ~CR_C); raw_local_irq_restore(flags); + return 1; } + return 0; } static void __init enable_dcache(void) @@ -225,18 +229,17 @@ static void __init enable_dcache(void) u32 cr; cr = get_cr(); - if (!(cr & CR_C)) - set_cr(cr | CR_C); + set_cr(cr | CR_C); } static void __init __invalidate_icache(void) { int dummy; - __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0\n" : "=r" (dummy)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c5, 0" : "=r" (dummy)); } -static void __init invalidate_and_disable_icache(void) +static int __init invalidate_and_disable_icache(void) { u32 cr; @@ -244,7 +247,9 @@ static void __init invalidate_and_disable_icache(void) if (cr & CR_I) { set_cr(cr & ~CR_I); __invalidate_icache(); + return 1; } + return 0; } static void __init enable_icache(void) @@ -252,8 +257,7 @@ static void __init enable_icache(void) u32 cr; cr = get_cr(); - if (!(cr & CR_I)) - set_cr(cr | CR_I); + set_cr(cr | CR_I); } static inline u32 read_extra_features(void) @@ -291,13 +295,17 @@ static void __init enable_l2(void) u = read_extra_features(); if (!(u & 0x00400000)) { + int i, d; + printk(KERN_INFO "Feroceon L2: Enabling L2\n"); - invalidate_and_disable_dcache(); - invalidate_and_disable_icache(); + d = flush_and_disable_dcache(); + i = invalidate_and_disable_icache(); write_extra_features(u | 0x00400000); - enable_icache(); - enable_dcache(); + if (i) + enable_icache(); + if (d) + enable_dcache(); } } diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 76b800a9519..b480f1d3591 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -18,9 +18,9 @@ */ #include <linux/init.h> #include <linux/spinlock.h> +#include <linux/io.h> #include <asm/cacheflush.h> -#include <asm/io.h> #include <asm/hardware/cache-l2x0.h> #define CACHE_LINE_SIZE 32 diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 35ffc4d9599..d19c2bec2b1 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -66,6 +66,7 @@ finished: mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr isb mov pc, lr +ENDPROC(v7_flush_dcache_all) /* * v7_flush_cache_all() @@ -85,6 +86,7 @@ ENTRY(v7_flush_kern_cache_all) mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate ldmfd sp!, {r4-r5, r7, r9-r11, lr} mov pc, lr +ENDPROC(v7_flush_kern_cache_all) /* * v7_flush_cache_all() @@ -110,6 +112,8 @@ ENTRY(v7_flush_user_cache_all) */ ENTRY(v7_flush_user_cache_range) mov pc, lr +ENDPROC(v7_flush_user_cache_all) +ENDPROC(v7_flush_user_cache_range) /* * v7_coherent_kern_range(start,end) @@ -155,6 +159,8 @@ ENTRY(v7_coherent_user_range) dsb isb mov pc, lr +ENDPROC(v7_coherent_kern_range) +ENDPROC(v7_coherent_user_range) /* * v7_flush_kern_dcache_page(kaddr) @@ -174,6 +180,7 @@ ENTRY(v7_flush_kern_dcache_page) blo 1b dsb mov pc, lr +ENDPROC(v7_flush_kern_dcache_page) /* * v7_dma_inv_range(start,end) @@ -202,6 +209,7 @@ ENTRY(v7_dma_inv_range) blo 1b dsb mov pc, lr +ENDPROC(v7_dma_inv_range) /* * v7_dma_clean_range(start,end) @@ -219,6 +227,7 @@ ENTRY(v7_dma_clean_range) blo 1b dsb mov pc, lr +ENDPROC(v7_dma_clean_range) /* * v7_dma_flush_range(start,end) @@ -236,6 +245,7 @@ ENTRY(v7_dma_flush_range) blo 1b dsb mov pc, lr +ENDPROC(v7_dma_flush_range) __INITDATA diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c index 158bd96763d..10b1bae1a25 100644 --- a/arch/arm/mm/cache-xsc3l2.c +++ b/arch/arm/mm/cache-xsc3l2.c @@ -18,10 +18,11 @@ */ #include <linux/init.h> #include <linux/spinlock.h> +#include <linux/io.h> #include <asm/system.h> +#include <asm/cputype.h> #include <asm/cacheflush.h> -#include <asm/io.h> #define CR_L2 (1 << 26) diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index ded0e96d069..8d33e254934 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -28,7 +28,7 @@ * specific hacks for copying pages efficiently. */ #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ - L_PTE_CACHEABLE) + L_PTE_MT_MINICACHE) static DEFINE_SPINLOCK(minicache_lock); diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c index 3adb79257f4..0e21c076758 100644 --- a/arch/arm/mm/copypage-v6.c +++ b/arch/arm/mm/copypage-v6.c @@ -16,6 +16,7 @@ #include <asm/shmparam.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> +#include <asm/cachetype.h> #include "mm.h" diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c index 2e455f82a4d..bad49331bbf 100644 --- a/arch/arm/mm/copypage-xscale.c +++ b/arch/arm/mm/copypage-xscale.c @@ -30,7 +30,7 @@ #define COPYPAGE_MINICACHE 0xffff8000 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \ - L_PTE_CACHEABLE) + L_PTE_MT_MINICACHE) static DEFINE_SPINLOCK(minicache_lock); diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/dma-mapping.c index db7b3e38ef1..67960017dc8 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/dma-mapping.c @@ -1,5 +1,5 @@ /* - * linux/arch/arm/mm/consistent.c + * linux/arch/arm/mm/dma-mapping.c * * Copyright (C) 2000-2004 Russell King * @@ -512,3 +512,105 @@ void dma_cache_maint(const void *start, size_t size, int direction) } } EXPORT_SYMBOL(dma_cache_maint); + +/** + * dma_map_sg - map a set of SG buffers for streaming mode DMA + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map + * @dir: DMA transfer direction + * + * Map a set of buffers described by scatterlist in streaming mode for DMA. + * This is the scatter-gather version of the dma_map_single interface. + * Here the scatter gather list elements are each tagged with the + * appropriate dma address and length. They are obtained via + * sg_dma_{address,length}. + * + * Device ownership issues as mentioned for dma_map_single are the same + * here. + */ +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + struct scatterlist *s; + int i, j; + + for_each_sg(sg, s, nents, i) { + s->dma_address = dma_map_page(dev, sg_page(s), s->offset, + s->length, dir); + if (dma_mapping_error(dev, s->dma_address)) + goto bad_mapping; + } + return nents; + + bad_mapping: + for_each_sg(sg, s, i, j) + dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); + return 0; +} +EXPORT_SYMBOL(dma_map_sg); + +/** + * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to unmap (returned from dma_map_sg) + * @dir: DMA transfer direction (same as was passed to dma_map_sg) + * + * Unmap a set of streaming mode DMA translations. Again, CPU access + * rules concerning calls here are the same as for dma_unmap_single(). + */ +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + struct scatterlist *s; + int i; + + for_each_sg(sg, s, nents, i) + dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); +} +EXPORT_SYMBOL(dma_unmap_sg); + +/** + * dma_sync_sg_for_cpu + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map (returned from dma_map_sg) + * @dir: DMA transfer direction (same as was passed to dma_map_sg) + */ +void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) +{ + struct scatterlist *s; + int i; + + for_each_sg(sg, s, nents, i) { + dmabounce_sync_for_cpu(dev, sg_dma_address(s), 0, + sg_dma_len(s), dir); + } +} +EXPORT_SYMBOL(dma_sync_sg_for_cpu); + +/** + * dma_sync_sg_for_device + * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices + * @sg: list of buffers + * @nents: number of buffers to map (returned from dma_map_sg) + * @dir: DMA transfer direction (same as was passed to dma_map_sg) + */ +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) +{ + struct scatterlist *s; + int i; + + for_each_sg(sg, s, nents, i) { + if (!dmabounce_sync_for_device(dev, sg_dma_address(s), 0, + sg_dma_len(s), dir)) + continue; + + if (!arch_is_coherent()) + dma_cache_maint(sg_virt(s), s->length, dir); + } +} +EXPORT_SYMBOL(dma_sync_sg_for_device); diff --git a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c index 9592c3ee4cb..9d285626bc7 100644 --- a/arch/arm/mm/extable.c +++ b/arch/arm/mm/extable.c @@ -2,7 +2,7 @@ * linux/arch/arm/mm/extable.c */ #include <linux/module.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> int fixup_exception(struct pt_regs *regs) { diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index a8ec97b4752..81d0b8772de 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -17,11 +17,13 @@ #include <linux/init.h> #include <linux/pagemap.h> +#include <asm/bugs.h> #include <asm/cacheflush.h> +#include <asm/cachetype.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> -static unsigned long shared_pte_mask = L_PTE_CACHEABLE; +static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE; /* * We take the easy way out of this problem - we make the @@ -63,9 +65,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address) * If this page isn't present, or is already setup to * fault (ie, is old), we can safely ignore any issues. */ - if (ret && pte_val(entry) & shared_pte_mask) { + if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) { flush_cache_page(vma, address, pte_pfn(entry)); - pte_val(entry) &= ~shared_pte_mask; + pte_val(entry) &= ~L_PTE_MT_MASK; + pte_val(entry) |= shared_pte_mask; set_pte_at(vma->vm_mm, address, pte, entry); flush_tlb_page(vma, address); } @@ -197,7 +200,7 @@ void __init check_writebuffer_bugs(void) unsigned long *p1, *p2; pgprot_t prot = __pgprot(L_PTE_PRESENT|L_PTE_YOUNG| L_PTE_DIRTY|L_PTE_WRITE| - L_PTE_BUFFERABLE); + L_PTE_MT_BUFFERABLE); p1 = vmap(&page, 1, VM_IOREMAP, prot); p2 = vmap(&page, 1, VM_IOREMAP, prot); @@ -218,7 +221,7 @@ void __init check_writebuffer_bugs(void) if (v) { printk("failed, %s\n", reason); - shared_pte_mask |= L_PTE_BUFFERABLE; + shared_pte_mask = L_PTE_MT_UNCACHED; } else { printk("ok\n"); } diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 28ad7ab1c0c..2df8d9facf5 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -13,11 +13,11 @@ #include <linux/mm.h> #include <linux/init.h> #include <linux/kprobes.h> +#include <linux/uaccess.h> #include <asm/system.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> -#include <asm/uaccess.h> #include "fault.h" @@ -72,9 +72,8 @@ void show_pte(struct mm_struct *mm, unsigned long addr) } pmd = pmd_offset(pgd, addr); -#if PTRS_PER_PMD != 1 - printk(", *pmd=%08lx", pmd_val(*pmd)); -#endif + if (PTRS_PER_PMD != 1) + printk(", *pmd=%08lx", pmd_val(*pmd)); if (pmd_none(*pmd)) break; diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 029ee65fda2..0fa9bf388f0 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -12,6 +12,7 @@ #include <linux/pagemap.h> #include <asm/cacheflush.h> +#include <asm/cachetype.h> #include <asm/system.h> #include <asm/tlbflush.h> diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 30a69d67d67..82c4b421798 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -26,9 +26,42 @@ #include "mm.h" -extern void _text, _etext, __data_start, _end, __init_begin, __init_end; -extern unsigned long phys_initrd_start; -extern unsigned long phys_initrd_size; +static unsigned long phys_initrd_start __initdata = 0; +static unsigned long phys_initrd_size __initdata = 0; + +static void __init early_initrd(char **p) +{ + unsigned long start, size; + + start = memparse(*p, p); + if (**p == ',') { + size = memparse((*p) + 1, p); + + phys_initrd_start = start; + phys_initrd_size = size; + } +} +__early_param("initrd=", early_initrd); + +static int __init parse_tag_initrd(const struct tag *tag) +{ + printk(KERN_WARNING "ATAG_INITRD is deprecated; " + "please update your bootloader.\n"); + phys_initrd_start = __virt_to_phys(tag->u.initrd.start); + phys_initrd_size = tag->u.initrd.size; + return 0; +} + +__tagtable(ATAG_INITRD, parse_tag_initrd); + +static int __init parse_tag_initrd2(const struct tag *tag) +{ + phys_initrd_start = tag->u.initrd.start; + phys_initrd_size = tag->u.initrd.size; + return 0; +} + +__tagtable(ATAG_INITRD2, parse_tag_initrd2); /* * This is used to pass memory configuration data from paging_init @@ -36,10 +69,6 @@ extern unsigned long phys_initrd_size; */ static struct meminfo meminfo = { 0, }; -#define for_each_nodebank(iter,mi,no) \ - for (iter = 0; iter < mi->nr_banks; iter++) \ - if (mi->bank[iter].node == no) - void show_mem(void) { int free = 0, total = 0, reserved = 0; @@ -50,14 +79,15 @@ void show_mem(void) show_free_areas(); for_each_online_node(node) { pg_data_t *n = NODE_DATA(node); - struct page *map = n->node_mem_map - n->node_start_pfn; + struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn; for_each_nodebank (i,mi,node) { + struct membank *bank = &mi->bank[i]; unsigned int pfn1, pfn2; struct page *page, *end; - pfn1 = __phys_to_pfn(mi->bank[i].start); - pfn2 = __phys_to_pfn(mi->bank[i].size + mi->bank[i].start); + pfn1 = bank_pfn_start(bank); + pfn2 = bank_pfn_end(bank); page = map + pfn1; end = map + pfn2; @@ -96,17 +126,17 @@ void show_mem(void) static unsigned int __init find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages) { - unsigned int start_pfn, bank, bootmap_pfn; + unsigned int start_pfn, i, bootmap_pfn; start_pfn = PAGE_ALIGN(__pa(&_end)) >> PAGE_SHIFT; bootmap_pfn = 0; - for_each_nodebank(bank, mi, node) { + for_each_nodebank(i, mi, node) { + struct membank *bank = &mi->bank[i]; unsigned int start, end; - start = mi->bank[bank].start >> PAGE_SHIFT; - end = (mi->bank[bank].size + - mi->bank[bank].start) >> PAGE_SHIFT; + start = bank_pfn_start(bank); + end = bank_pfn_end(bank); if (end < start_pfn) continue; @@ -145,13 +175,10 @@ static int __init check_initrd(struct meminfo *mi) initrd_node = -1; for (i = 0; i < mi->nr_banks; i++) { - unsigned long bank_end; - - bank_end = mi->bank[i].start + mi->bank[i].size; - - if (mi->bank[i].start <= phys_initrd_start && - end <= bank_end) - initrd_node = mi->bank[i].node; + struct membank *bank = &mi->bank[i]; + if (bank_phys_start(bank) <= phys_initrd_start && + end <= bank_phys_end(bank)) + initrd_node = bank->node; } } @@ -171,19 +198,17 @@ static inline void map_memory_bank(struct membank *bank) #ifdef CONFIG_MMU struct map_desc map; - map.pfn = __phys_to_pfn(bank->start); - map.virtual = __phys_to_virt(bank->start); - map.length = bank->size; + map.pfn = bank_pfn_start(bank); + map.virtual = __phys_to_virt(bank_phys_start(bank)); + map.length = bank_phys_size(bank); map.type = MT_MEMORY; create_mapping(&map); #endif } -static unsigned long __init -bootmem_init_node(int node, int initrd_node, struct meminfo *mi) +static unsigned long __init bootmem_init_node(int node, struct meminfo *mi) { - unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; unsigned long start_pfn, end_pfn, boot_pfn; unsigned int boot_pages; pg_data_t *pgdat; @@ -199,8 +224,8 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) struct membank *bank = &mi->bank[i]; unsigned long start, end; - start = bank->start >> PAGE_SHIFT; - end = (bank->start + bank->size) >> PAGE_SHIFT; + start = bank_pfn_start(bank); + end = bank_pfn_end(bank); if (start_pfn > start) start_pfn = start; @@ -230,8 +255,11 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) pgdat = NODE_DATA(node); init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn); - for_each_nodebank(i, mi, node) - free_bootmem_node(pgdat, mi->bank[i].start, mi->bank[i].size); + for_each_nodebank(i, mi, node) { + struct membank *bank = &mi->bank[i]; + free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank)); + memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank)); + } /* * Reserve the bootmem bitmap for this node. @@ -239,31 +267,39 @@ bootmem_init_node(int node, int initrd_node, struct meminfo *mi) reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); - /* - * Reserve any special node zero regions. - */ - if (node == 0) - reserve_node_zero(pgdat); + return end_pfn; +} +static void __init bootmem_reserve_initrd(int node) +{ #ifdef CONFIG_BLK_DEV_INITRD - /* - * If the initrd is in this node, reserve it |