[parisc-linux] memcpy_fromio() seems partially broken [with patch]

Matthew Wilcox matthew@wil.cx
Sat, 9 Jun 2001 02:39:17 +0100


On Fri, Jun 08, 2001 at 11:37:31PM +0200, Helge Deller wrote:
> while I was playing with a few network-cards in the c3k I found a strange 
> behaviour when copying unaligned data with memcpy_fromio() off the PCI bus.
> 
> Background: 
> I wanted to copy data off the network-card (HP J2585A) from an 4-byte aligned 
> PCI address to an 2-byte aligned (b/c of skb_reserve(skb, 2)) memory-address 
> with memcpy_fromio().
> The current code in CVS for memcpy_fromio() copied byteswapped and/or 
> completely wrong data for all copied values, while the following 
> memcpy_fromio() worked without problems:

This is very bizarre.  Following the codepaths, the current code does:

	if (((unsigned long)dest & 3) != (src & 3))
		goto bytecopy;

 bytecopy:
	while (count--) {
		*(char *)dest = readb(src++);
		((char *)dest)++;
	}

and i don't see how that can possibly do byteswapping.  unless byteswapping
is necessary and this code is failing to do that?  Your code is doing:

         if (((unsigned long)dest & 3) != (src & 3))
                 goto wordcopy;

  wordcopy:
         if (src & 3)
                 goto bytecopy;
  wordcopy_loop:
         value = readl(src);
         *((char*)dest) = (char) (value >> 24);  dest++;
         if (--count == 0) return;
         *((char*)dest) = (char) (value >> 16);  dest++;
         if (--count == 0) return;
         *((char*)dest) = (char) (value >> 8);   dest++;
         if (--count == 0) return;
         *((char*)dest) = (char) (value);  dest++;
         if (count) goto wordcopy_loop;
         return;

which is doing a byteswap on the  value returned from readl!  This seems
pretty grotesque to me.  I want to hear from someone (eg grant) who can
say what's actually going on here..

-- 
Revolutions do not require corporate support.