[ARM] 3017/1: Add support for 36-bit addresses to create_mapping()
Patch from Deepak Saxena This patch adds support for 36-bit static mapped I/O. While there are no platforms in the tree ATM that use it, it has been tested tested on the IXP2350 NPU and I would like to get the support for that chipset upstream one piece at a time. There are also other Intel chipset ports in development that are waiting on this to go upstream. The patch replaces the print formats for physical addresses with %016llx which will create a bit extraneous output on 32-bit systems, but I think that is cleaner than having #ifdefs, specially since users will only see the output in error cases. Depends on 3016/1. Signed-off-by: Deepak Saxena <dsaxena@plexity.net> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									9769c2468d
								
							
						
					
					
						commit
						0b7cd62ecd
					
				| @ -478,20 +478,20 @@ void __init create_mapping(struct map_desc *md) | ||||
| 	unsigned long virt, length; | ||||
| 	int prot_sect, prot_l1, domain; | ||||
| 	pgprot_t prot_pte; | ||||
| 	long off; | ||||
| 	unsigned long off = (u32)__pfn_to_phys(md->pfn); | ||||
| 
 | ||||
| 	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) { | ||||
| 		printk(KERN_WARNING "BUG: not creating mapping for " | ||||
| 		       "0x%08lx at 0x%08lx in user region\n", | ||||
| 		       __pfn_to_phys(md->pfn), md->virtual); | ||||
| 		       "0x%016llx at 0x%08lx in user region\n", | ||||
| 		       __pfn_to_phys((u64)md->pfn), md->virtual); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if ((md->type == MT_DEVICE || md->type == MT_ROM) && | ||||
| 	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) { | ||||
| 		printk(KERN_WARNING "BUG: mapping for 0x%08lx at 0x%08lx " | ||||
| 		printk(KERN_WARNING "BUG: mapping for 0x%016llx at 0x%08lx " | ||||
| 		       "overlaps vmalloc space\n", | ||||
| 		       __pfn_to_phys(md->pfn), md->virtual); | ||||
| 		       __pfn_to_phys((u64)md->pfn), md->virtual); | ||||
| 	} | ||||
| 
 | ||||
| 	domain	  = mem_types[md->type].domain; | ||||
| @ -499,8 +499,33 @@ void __init create_mapping(struct map_desc *md) | ||||
| 	prot_l1   = mem_types[md->type].prot_l1 | PMD_DOMAIN(domain); | ||||
| 	prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Catch 36-bit addresses | ||||
| 	 */ | ||||
| 	if(md->pfn >= 0x100000) { | ||||
| 		if(domain) { | ||||
| 			printk(KERN_ERR "MM: invalid domain in supersection " | ||||
| 				"mapping for 0x%016llx at 0x%08lx\n", | ||||
| 				__pfn_to_phys((u64)md->pfn), md->virtual); | ||||
| 			return; | ||||
| 		} | ||||
| 		if((md->virtual | md->length | __pfn_to_phys(md->pfn)) | ||||
| 			& ~SUPERSECTION_MASK) { | ||||
| 			printk(KERN_ERR "MM: cannot create mapping for " | ||||
| 				"0x%016llx at 0x%08lx invalid alignment\n", | ||||
| 				__pfn_to_phys((u64)md->pfn), md->virtual); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Shift bits [35:32] of address into bits [23:20] of PMD | ||||
| 		 * (See ARMv6 spec). | ||||
| 		 */ | ||||
| 		off |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20); | ||||
| 	} | ||||
| 
 | ||||
| 	virt   = md->virtual; | ||||
| 	off    = __pfn_to_phys(md->pfn) - virt; | ||||
| 	off   -= virt; | ||||
| 	length = md->length; | ||||
| 
 | ||||
| 	if (mem_types[md->type].prot_l1 == 0 && | ||||
| @ -525,13 +550,22 @@ void __init create_mapping(struct map_desc *md) | ||||
| 	 *	of the actual domain assignments in use. | ||||
| 	 */ | ||||
| 	if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) { | ||||
| 		/* Align to supersection boundary */ | ||||
| 		while ((virt & ~SUPERSECTION_MASK || (virt + off) & | ||||
| 			~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) { | ||||
| 			alloc_init_section(virt, virt + off, prot_sect); | ||||
| 		/*
 | ||||
| 		 * Align to supersection boundary if !high pages. | ||||
| 		 * High pages have already been checked for proper | ||||
| 		 * alignment above and they will fail the SUPSERSECTION_MASK | ||||
| 		 * check because of the way the address is encoded into | ||||
| 		 * offset. | ||||
| 		 */ | ||||
| 		if (md->pfn <= 0x100000) { | ||||
| 			while ((virt & ~SUPERSECTION_MASK || | ||||
| 			        (virt + off) & ~SUPERSECTION_MASK) && | ||||
| 				length >= (PGDIR_SIZE / 2)) { | ||||
| 				alloc_init_section(virt, virt + off, prot_sect); | ||||
| 
 | ||||
| 			virt   += (PGDIR_SIZE / 2); | ||||
| 			length -= (PGDIR_SIZE / 2); | ||||
| 				virt   += (PGDIR_SIZE / 2); | ||||
| 				length -= (PGDIR_SIZE / 2); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		while (length >= SUPERSECTION_SIZE) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user