[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.