[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <201106171045.01928.ptesarik@suse.cz>
Date: Fri, 17 Jun 2011 10:45:01 +0200
From: Petr Tesarik <ptesarik@...e.cz>
To: Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>,
"H. Peter Anvin" <hpa@...or.com>
Cc: x86@...nel.org, linux-kernel@...r.kernel.org
Subject: [PATCH 03/10] x86: translate highmem /dev/mem pointers
On 32-bit x86, it is necessary to kmap/kunmap /dev/mem pointers in
the high memory area.
Signed-off-by: Petr Tesarik <ptesarik@...e.cz>
---
arch/x86/include/asm/io.h | 4 ++--
arch/x86/mm/ioremap.c | 24 ++++++++++++++++++------
2 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index d02804d..9b994dd 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -311,8 +311,8 @@ BUILDIO(b, b, char)
BUILDIO(w, w, short)
BUILDIO(l, , int)
-extern void *xlate_dev_mem_ptr(unsigned long phys);
-extern void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
+extern void *xlate_dev_mem_ptr(phys_addr_t phys);
+extern void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
extern int ioremap_change_attr(unsigned long vaddr, unsigned long size,
unsigned long prot_val);
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index be1ef57..fb566d7 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -308,26 +308,38 @@ EXPORT_SYMBOL(iounmap);
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
* access
*/
-void *xlate_dev_mem_ptr(unsigned long phys)
+void *xlate_dev_mem_ptr(phys_addr_t phys)
{
void *addr;
- unsigned long start = phys & PAGE_MASK;
+ unsigned long pfn = phys >> PAGE_SHIFT;
+ phys_addr_t start = phys & ~((phys_addr_t)PAGE_SIZE-1);
/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
- if (page_is_ram(start >> PAGE_SHIFT))
+ if (page_is_ram(pfn)) {
+ if (phys >= __pa(high_memory))
+ return pfn_valid(pfn)
+ ? kmap(pfn_to_page(pfn))
+ : NULL;
return __va(phys);
+ }
addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
if (addr)
- addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+ addr = (void *)((unsigned long)addr |
+ ((unsigned long)phys & ~PAGE_MASK));
return addr;
}
-void unxlate_dev_mem_ptr(unsigned long phys, void *addr)
+void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
{
- if (page_is_ram(phys >> PAGE_SHIFT))
+ unsigned long pfn = phys >> PAGE_SHIFT;
+
+ if (page_is_ram(pfn)) {
+ if (phys >= __pa(high_memory))
+ kunmap(pfn_to_page(pfn));
return;
+ }
iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
return;
--
1.7.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists