Commit 54465502 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86_64: Fix ioremap attribute restoration on i386 and x86-64

We need to save the access flags to properly restore the direct mapping on
unmap.  For that we use some upper bits in vm_flags

Also add a comment for that to the header file.
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 82a71519
......@@ -157,7 +157,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/*
* Ok, go for it..
*/
area = get_vm_area(size, VM_IOREMAP);
area = get_vm_area(size, VM_IOREMAP | (flags << 20));
if (!area)
return NULL;
area->phys_addr = phys_addr;
......@@ -235,9 +235,9 @@ void iounmap(volatile void __iomem *addr)
if (!p) {
printk("__iounmap: bad address %p\n", addr);
return;
}
}
if (p->flags && p->phys_addr < virt_to_phys(high_memory) - 1) {
if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
PAGE_KERNEL);
......
......@@ -175,11 +175,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
if (phys_addr >= 0xA0000 && last_addr < 0x100000)
return (__force void __iomem *)phys_to_virt(phys_addr);
#ifndef CONFIG_DISCONTIGMEM
/*
* Don't allow anybody to remap normal RAM that we're using..
*/
if (phys_addr < virt_to_phys(high_memory)) {
#ifndef CONFIG_DISCONTIGMEM
if (last_addr < virt_to_phys(high_memory)) {
char *t_addr, *t_end;
struct page *page;
......@@ -189,8 +189,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
if(!PageReserved(page))
return NULL;
#endif
}
#endif
/*
* Mappings have to be page-aligned
......@@ -202,7 +202,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
/*
* Ok, go for it..
*/
area = get_vm_area(size, VM_IOREMAP | (flags << 24));
area = get_vm_area(size, VM_IOREMAP | (flags << 20));
if (!area)
return NULL;
area->phys_addr = phys_addr;
......@@ -263,7 +263,7 @@ void iounmap(volatile void __iomem *addr)
}
*pprev = p->next;
unmap_vm_area(p);
if ((p->flags >> 24) &&
if ((p->flags >> 20) &&
p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
......
......@@ -8,6 +8,7 @@
#define VM_IOREMAP 0x00000001 /* ioremap() and friends */
#define VM_ALLOC 0x00000002 /* vmalloc() */
#define VM_MAP 0x00000004 /* vmap()ed pages */
/* bits [20..32] reserved for arch specific ioremap internals */
struct vm_struct {
void *addr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment