diff options
Diffstat (limited to 'arch/arm/mm/mmu.c')
| -rw-r--r-- | arch/arm/mm/mmu.c | 60 | 
1 files changed, 46 insertions, 14 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4c2d0451e84..18144e6a311 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -31,6 +31,7 @@  #include <asm/mach/arch.h>  #include <asm/mach/map.h> +#include <asm/mach/pci.h>  #include "mm.h" @@ -216,7 +217,7 @@ static struct mem_type mem_types[] = {  		.prot_l1	= PMD_TYPE_TABLE,  		.prot_sect	= PROT_SECT_DEVICE | PMD_SECT_WB,  		.domain		= DOMAIN_IO, -	},	 +	},  	[MT_DEVICE_WC] = {	/* ioremap_wc */  		.prot_pte	= PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,  		.prot_l1	= PMD_TYPE_TABLE, @@ -777,14 +778,27 @@ void __init iotable_init(struct map_desc *io_desc, int nr)  		create_mapping(md);  		vm->addr = (void *)(md->virtual & PAGE_MASK);  		vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK)); -		vm->phys_addr = __pfn_to_phys(md->pfn);  -		vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;  +		vm->phys_addr = __pfn_to_phys(md->pfn); +		vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;  		vm->flags |= VM_ARM_MTYPE(md->type);  		vm->caller = iotable_init;  		vm_area_add_early(vm++);  	}  } +void __init vm_reserve_area_early(unsigned long addr, unsigned long size, +				  void *caller) +{ +	struct vm_struct *vm; + +	vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); +	vm->addr = (void *)addr; +	vm->size = size; +	vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING; +	vm->caller = caller; +	vm_area_add_early(vm); +} +  #ifndef CONFIG_ARM_LPAE  /* @@ -802,14 +816,7 @@ void __init iotable_init(struct map_desc *io_desc, int nr)  static void __init pmd_empty_section_gap(unsigned long addr)  { -	struct vm_struct *vm; - -	vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); -	vm->addr = (void *)addr; -	vm->size = SECTION_SIZE; -	vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; -	vm->caller = pmd_empty_section_gap; -	vm_area_add_early(vm); +	vm_reserve_area_early(addr, SECTION_SIZE, pmd_empty_section_gap);  }  static void __init fill_pmd_gaps(void) @@ -820,7 +827,7 @@ static void __init fill_pmd_gaps(void)  	/* we're still single threaded hence no lock needed here */  	for (vm = vmlist; vm; vm = vm->next) { -		if (!(vm->flags & VM_ARM_STATIC_MAPPING)) +		if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING)))  			continue;  		addr = (unsigned long)vm->addr;  		if (addr < next) @@ -858,6 +865,28 @@ static void __init fill_pmd_gaps(void)  #define fill_pmd_gaps() do { } while (0)  #endif +#if defined(CONFIG_PCI) && !defined(CONFIG_NEED_MACH_IO_H) +static void __init pci_reserve_io(void) +{ +	struct vm_struct *vm; +	unsigned long addr; + +	/* we're still single threaded hence no lock needed here */ +	for (vm = vmlist; vm; vm = vm->next) { +		if (!(vm->flags & VM_ARM_STATIC_MAPPING)) +			continue; +		addr = (unsigned long)vm->addr; +		addr &= ~(SZ_2M - 1); +		if (addr == PCI_IO_VIRT_BASE) +			return; + +	} +	vm_reserve_area_early(PCI_IO_VIRT_BASE, SZ_2M, pci_reserve_io); +} +#else +#define pci_reserve_io() do { } while (0) +#endif +  static void * __initdata vmalloc_min =  	(void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); @@ -961,8 +990,8 @@ void __init sanity_check_meminfo(void)  		 * Check whether this memory bank would partially overlap  		 * the vmalloc area.  		 */ -		if (__va(bank->start + bank->size) > vmalloc_min || -		    __va(bank->start + bank->size) < __va(bank->start)) { +		if (__va(bank->start + bank->size - 1) >= vmalloc_min || +		    __va(bank->start + bank->size - 1) <= __va(bank->start)) {  			unsigned long newsize = vmalloc_min - __va(bank->start);  			printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "  			       "to -%.8llx (vmalloc region overlap).\n", @@ -1141,6 +1170,9 @@ static void __init devicemaps_init(struct machine_desc *mdesc)  		mdesc->map_io();  	fill_pmd_gaps(); +	/* Reserve fixed i/o space in VMALLOC region */ +	pci_reserve_io(); +  	/*  	 * Finally flush the caches and tlb to ensure that we're in a  	 * consistent state wrt the writebuffer.  This also ensures that  |