mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
[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