summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2009-06-19 10:41:19 +0200
committerArnd Bergmann <arnd@arndb.de>2009-06-19 14:58:13 +0200
commit32a9ff9cc55b42543a84bca90b070df92af72671 (patch)
treece4d38741f8b78f5e4f193f5032846743e76b183
parentfcec9bf12442d0cd50d6cee125d168cfc3f37c5e (diff)
lib/checksum.c: fix endianess bug
The new generic checksum code has a small dependency on endianess and worked only on big-endian systems. I could not find a nice efficient way to express this, so I added an #ifdef. Using 'result += le16_to_cpu(*buff);' would have worked as well, but would be slightly less efficient on big-endian systems and IMHO would not be clearer. Also fix a bug that prevents this from working on 64-bit machines. If you have a 64-bit CPU and want to use the generic checksum code, you should probably do some more optimizations anyway, but at least the code should not break. Reported-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--lib/checksum.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/lib/checksum.c b/lib/checksum.c
index 12e5a1c91cd..b2e2fd46846 100644
--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -55,7 +55,11 @@ static unsigned int do_csum(const unsigned char *buff, int len)
goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
+#ifdef __LITTLE_ENDIAN
result = *buff;
+#else
+ result += (*buff << 8);
+#endif
len--;
buff++;
}
@@ -71,7 +75,7 @@ static unsigned int do_csum(const unsigned char *buff, int len)
if (count) {
unsigned long carry = 0;
do {
- unsigned long w = *(unsigned long *) buff;
+ unsigned long w = *(unsigned int *) buff;
count--;
buff += 4;
result += carry;
@@ -87,7 +91,11 @@ static unsigned int do_csum(const unsigned char *buff, int len)
}
}
if (len & 1)
+#ifdef __LITTLE_ENDIAN
+ result += *buff;
+#else
result += (*buff << 8);
+#endif
result = from32to16(result);
if (odd)
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);