Commit cea79535 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] PA-RISC: Sort out io accessors

 - sparse annotations for ioremap/iounmap (Randolph Chung)
 - Turn gsc_readb, __raw_readb and readb functions into static inline
   functions (Matthew Wilcox)
 - Document the difference between the gsc_readb, __raw_readb and readb
   families of functions (Matthew Wilcox)
 - Add a debugging option to determine when they are being used incorrectly
   (Matthew Wilcox)
 - Make memcpy_fromio's second argument const (Matthew Wilcox)
Signed-off-by: default avatarMatthew Wilcox <willy@parisc-linux.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ad548e8b
...@@ -87,9 +87,9 @@ EXPORT_SYMBOL($global$); ...@@ -87,9 +87,9 @@ EXPORT_SYMBOL($global$);
#include <asm/io.h> #include <asm/io.h>
EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(__memcpy_toio); EXPORT_SYMBOL(memcpy_toio);
EXPORT_SYMBOL(__memcpy_fromio); EXPORT_SYMBOL(memcpy_fromio);
EXPORT_SYMBOL(__memset_io); EXPORT_SYMBOL(memset_io);
#include <asm/unistd.h> #include <asm/unistd.h>
EXPORT_SYMBOL(sys_open); EXPORT_SYMBOL(sys_open);
......
...@@ -15,24 +15,24 @@ ...@@ -15,24 +15,24 @@
* Assumes the device can cope with 32-bit transfers. If it can't, * Assumes the device can cope with 32-bit transfers. If it can't,
* don't use this function. * don't use this function.
*/ */
void __memcpy_toio(unsigned long dest, unsigned long src, int count) void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
{ {
if ((dest & 3) != (src & 3)) if (((unsigned long)dst & 3) != ((unsigned long)src & 3))
goto bytecopy; goto bytecopy;
while (dest & 3) { while ((unsigned long)dst & 3) {
writeb(*(char *)src, dest++); writeb(*(char *)src, dst++);
src++; src++;
count--; count--;
} }
while (count > 3) { while (count > 3) {
__raw_writel(*(u32 *)src, dest); __raw_writel(*(u32 *)src, dst);
src += 4; src += 4;
dest += 4; dst += 4;
count -= 4; count -= 4;
} }
bytecopy: bytecopy:
while (count--) { while (count--) {
writeb(*(char *)src, dest++); writeb(*(char *)src, dst++);
src++; src++;
} }
} }
...@@ -50,51 +50,51 @@ void __memcpy_toio(unsigned long dest, unsigned long src, int count) ...@@ -50,51 +50,51 @@ void __memcpy_toio(unsigned long dest, unsigned long src, int count)
** Minimize total number of transfers at cost of CPU cycles. ** Minimize total number of transfers at cost of CPU cycles.
** TODO: only look at src alignment and adjust the stores to dest. ** TODO: only look at src alignment and adjust the stores to dest.
*/ */
void __memcpy_fromio(unsigned long dest, unsigned long src, int count) void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
{ {
/* first compare alignment of src/dst */ /* first compare alignment of src/dst */
if ( ((dest ^ src) & 1) || (count < 2) ) if ( (((unsigned long)dst ^ (unsigned long)src) & 1) || (count < 2) )
goto bytecopy; goto bytecopy;
if ( ((dest ^ src) & 2) || (count < 4) ) if ( (((unsigned long)dst ^ (unsigned long)src) & 2) || (count < 4) )
goto shortcopy; goto shortcopy;
/* Then check for misaligned start address */ /* Then check for misaligned start address */
if (src & 1) { if ((unsigned long)src & 1) {
*(u8 *)dest = readb(src); *(u8 *)dst = readb(src);
src++; src++;
dest++; dst++;
count--; count--;
if (count < 2) goto bytecopy; if (count < 2) goto bytecopy;
} }
if (src & 2) { if ((unsigned long)src & 2) {
*(u16 *)dest = __raw_readw(src); *(u16 *)dst = __raw_readw(src);
src += 2; src += 2;
dest += 2; dst += 2;
count -= 2; count -= 2;
} }
while (count > 3) { while (count > 3) {
*(u32 *)dest = __raw_readl(src); *(u32 *)dst = __raw_readl(src);
dest += 4; dst += 4;
src += 4; src += 4;
count -= 4; count -= 4;
} }
shortcopy: shortcopy:
while (count > 1) { while (count > 1) {
*(u16 *)dest = __raw_readw(src); *(u16 *)dst = __raw_readw(src);
src += 2; src += 2;
dest += 2; dst += 2;
count -= 2; count -= 2;
} }
bytecopy: bytecopy:
while (count--) { while (count--) {
*(char *)dest = readb(src); *(char *)dst = readb(src);
src++; src++;
dest++; dst++;
} }
} }
...@@ -102,20 +102,20 @@ void __memcpy_fromio(unsigned long dest, unsigned long src, int count) ...@@ -102,20 +102,20 @@ void __memcpy_fromio(unsigned long dest, unsigned long src, int count)
* Assumes the device can cope with 32-bit transfers. If it can't, * Assumes the device can cope with 32-bit transfers. If it can't,
* don't use this function. * don't use this function.
*/ */
void __memset_io(unsigned long dest, char fill, int count) void memset_io(volatile void __iomem *addr, unsigned char val, int count)
{ {
u32 fill32 = (fill << 24) | (fill << 16) | (fill << 8) | fill; u32 val32 = (val << 24) | (val << 16) | (val << 8) | val;
while (dest & 3) { while ((unsigned long)addr & 3) {
writeb(fill, dest++); writeb(val, addr++);
count--; count--;
} }
while (count > 3) { while (count > 3) {
__raw_writel(fill32, dest); __raw_writel(val32, addr);
dest += 4; addr += 4;
count -= 4; count -= 4;
} }
while (count--) { while (count--) {
writeb(fill, dest++); writeb(val, addr++);
} }
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/module.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -94,6 +95,30 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr, ...@@ -94,6 +95,30 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
} }
#endif /* USE_HPPA_IOREMAP */ #endif /* USE_HPPA_IOREMAP */
#ifdef CONFIG_DEBUG_IOREMAP
static unsigned long last = 0;
void gsc_bad_addr(unsigned long addr)
{
if (time_after(jiffies, last + HZ*10)) {
printk("gsc_foo() called with bad address 0x%lx\n", addr);
dump_stack();
last = jiffies;
}
}
EXPORT_SYMBOL(gsc_bad_addr);
void __raw_bad_addr(const volatile void __iomem *addr)
{
if (time_after(jiffies, last + HZ*10)) {
printk("__raw_foo() called with bad address 0x%p\n", addr);
dump_stack();
last = jiffies;
}
}
EXPORT_SYMBOL(__raw_bad_addr);
#endif
/* /*
* Generic mapping function (not visible outside): * Generic mapping function (not visible outside):
*/ */
...@@ -107,7 +132,7 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr, ...@@ -107,7 +132,7 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
* have to convert them into an offset in a page-aligned mapping, but the * have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail. * caller shouldn't need to know that small detail.
*/ */
void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
{ {
#if !(USE_HPPA_IOREMAP) #if !(USE_HPPA_IOREMAP)
...@@ -118,7 +143,11 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag ...@@ -118,7 +143,11 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
phys_addr |= 0xfc000000; phys_addr |= 0xfc000000;
} }
return (void *)phys_addr; #ifdef CONFIG_DEBUG_IOREMAP
return (void __iomem *)(phys_addr - (0x1UL << NYBBLE_SHIFT));
#else
return (void __iomem *)phys_addr;
#endif
#else #else
void * addr; void * addr;
...@@ -163,16 +192,16 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag ...@@ -163,16 +192,16 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
vfree(addr); vfree(addr);
return NULL; return NULL;
} }
return (void *) (offset + (char *)addr); return (void __iomem *) (offset + (char *)addr);
#endif #endif
} }
void iounmap(void *addr) void iounmap(void __iomem *addr)
{ {
#if !(USE_HPPA_IOREMAP) #if !(USE_HPPA_IOREMAP)
return; return;
#else #else
if (addr > high_memory) if (addr > high_memory)
return vfree((void *) (PAGE_MASK & (unsigned long) addr)); return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
#endif #endif
} }
This diff is collapsed.
...@@ -117,6 +117,19 @@ config DEBUG_INFO ...@@ -117,6 +117,19 @@ config DEBUG_INFO
If you're truly short on disk space or don't expect to report any If you're truly short on disk space or don't expect to report any
bugs back to the UML developers, say N, otherwise say Y. bugs back to the UML developers, say N, otherwise say Y.
config DEBUG_IOREMAP
bool "Enable ioremap() debugging"
depends on DEBUG_KERNEL && PARISC
help
Enabling this option will cause the kernel to distinguish between
ioremapped and physical addresses. It will print a backtrace (at
most one every 10 seconds), hopefully allowing you to see which
drivers need work. Fixing all these problems is a prerequisite
for turning on USE_HPPA_IOREMAP. The warnings are harmless;
the kernel has enough information to fix the broken drivers
automatically, but we'd like to make it more efficient by not
having to do that.
config DEBUG_FS config DEBUG_FS
bool "Debug Filesystem" bool "Debug Filesystem"
depends on DEBUG_KERNEL depends on DEBUG_KERNEL
......
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