Commit 32a9ff9cc55b42543a84bca90b070df92af72671

Authored by Arnd Bergmann
1 parent fcec9bf124

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>

Showing 1 changed file with 9 additions and 1 deletions Side-by-side Diff

... ... @@ -55,7 +55,11 @@
55 55 goto out;
56 56 odd = 1 & (unsigned long) buff;
57 57 if (odd) {
  58 +#ifdef __LITTLE_ENDIAN
58 59 result = *buff;
  60 +#else
  61 + result += (*buff << 8);
  62 +#endif
59 63 len--;
60 64 buff++;
61 65 }
... ... @@ -71,7 +75,7 @@
71 75 if (count) {
72 76 unsigned long carry = 0;
73 77 do {
74   - unsigned long w = *(unsigned long *) buff;
  78 + unsigned long w = *(unsigned int *) buff;
75 79 count--;
76 80 buff += 4;
77 81 result += carry;
78 82  
... ... @@ -87,7 +91,11 @@
87 91 }
88 92 }
89 93 if (len & 1)
  94 +#ifdef __LITTLE_ENDIAN
  95 + result += *buff;
  96 +#else
90 97 result += (*buff << 8);
  98 +#endif
91 99 result = from32to16(result);
92 100 if (odd)
93 101 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);