[parisc-linux-cvs] linux grundler

Grant Grundler grundler@puffin.external.hp.com
Wed, 11 Jul 2001 23:11:18 -0600


Grant Grundler wrote:
> Modified files:
> 	.              : Makefile 
> 	arch/parisc/lib: io.c 
> 	include/asm-parisc: io.h 
> 
> Log message:
> Can't say yet if this fixes Helge's problems with memcpy_fromio() but it
> removes some questionable things and one incorrect usage of "const".

Sorry! I realized I forgot to post the patch after I had logged out
and was busy with other things (brother here from japan for dinner).

Change to io.h was just to remove const from the prototype.
appended is the diff for io.c.

grant

Index: arch/parisc/lib/io.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/lib/io.c,v
retrieving revision 1.2
diff -u -p -r1.2 io.c
--- io.c	2001/04/12 14:09:49	1.2
+++ io.c	2001/07/11 21:38:20
@@ -34,28 +34,63 @@ void memcpy_toio(unsigned long dest, con
 	}
 }
 
-/* Copies a block of memory from a device in an efficient manner.
- * Assumes the device can cope with 32-bit transfers.  If it can't,
- * don't use this function.
- */
-void memcpy_fromio(const void *dest, unsigned long src, int count)
+/*
+** Copies a block of memory from a device in an efficient manner.
+** Assumes the device can cope with 32-bit transfers.  If it can't,
+** don't use this function.
+**
+** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM:
+**	27341/64    = 427 cyc per int
+**	61311/128   = 478 cyc per short
+**	122637/256  = 479 cyc per byte
+** Ergo bus latencies dominant (not transfer size).
+**      Minimize total number of transfers at cost of CPU cycles.
+**	TODO: only look at src alignment and adjust the stores to dest.
+*/
+void memcpy_fromio(void *dest, unsigned long src, int count)
 {
-	if (((unsigned long)dest & 3) != (src & 3))
+	/* first compare alignment of src/dst */ 
+	if ( (((unsigned long)dest ^ src) & 1) || (count < 2) )
 		goto bytecopy;
-	while (src & 3) {
-		*(char *)dest = readb(src++);
-		((char *)dest)++;
+
+	if ( (((unsigned long)dest ^ src) & 2) || (count < 4) )
+		goto shortcopy;
+
+	/* Then check for misaligned start address */
+	if (src & 1) {
+		*(u8 *)dest = readb(src);
+		((u8 *)src)++;
+		((u8 *)dest)++;
 		count--;
+		if (count < 2) goto bytecopy;
 	}
+
+	if (src & 2) {
+		*(u16 *)dest = readw(src);
+		((u16 *)src)++;
+		((u16 *)dest)++;
+		count-=2;
+	}
+
 	while (count > 3) {
 		*(u32 *)dest = readl(src);
 		dest += 4;
 		src += 4;
 		count -= 4;
 	}
+
+ shortcopy:
+	while (count > 1) {
+		*(u16 *)dest = readw(src);
+		((u16 *)src)++;
+		((u16 *)dest)++;
+		count-=2;
+	}
+
  bytecopy:
 	while (count--) {
-		*(char *)dest = readb(src++);
+		*(char *)dest = readb(src);
+		((char *)src)++;
 		((char *)dest)++;
 	}
 }