lkml.org 
[lkml]   [2011]   [Jun]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 03/10] x86: translate highmem /dev/mem pointers
Date
On 32-bit x86, it is necessary to kmap/kunmap /dev/mem pointers in
the high memory area.

Signed-off-by: Petr Tesarik <ptesarik@suse.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

\
 
 \ /
  Last update: 2011-06-17 11:01    [W:0.110 / U:7.364 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site