Commit 2e74a186 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] parisc: checksum improvements

Small tweaks to the checksumming routines
Fix a corner case in csum_partial
Committed-by: default avatarRandolph Chung <tausq@parisc-linux.org>
parent a63bb96f
...@@ -24,6 +24,13 @@ ...@@ -24,6 +24,13 @@
#include <asm/string.h> #include <asm/string.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define addc(_t,_r) \
__asm__ __volatile__ ( \
" add %0, %1, %0\n" \
" addc %0, %%r0, %0\n" \
: "=r"(_t) \
: "r"(_r), "0"(_t));
static inline unsigned short from32to16(unsigned int x) static inline unsigned short from32to16(unsigned int x)
{ {
/* 32 bits --> 16 bits + carry */ /* 32 bits --> 16 bits + carry */
...@@ -56,16 +63,25 @@ static inline unsigned int do_csum(const unsigned char * buff, int len) ...@@ -56,16 +63,25 @@ static inline unsigned int do_csum(const unsigned char * buff, int len)
} }
count >>= 1; /* nr of 32-bit words.. */ count >>= 1; /* nr of 32-bit words.. */
if (count) { if (count) {
unsigned int carry = 0; while (count >= 4) {
do { unsigned int r1, r2, r3, r4;
r1 = *(unsigned int *)(buff + 0);
r2 = *(unsigned int *)(buff + 4);
r3 = *(unsigned int *)(buff + 8);
r4 = *(unsigned int *)(buff + 12);
addc(result, r1);
addc(result, r2);
addc(result, r3);
addc(result, r4);
count -= 4;
buff += 16;
}
while (count) {
unsigned int w = *(unsigned int *) buff; unsigned int w = *(unsigned int *) buff;
count--; count--;
buff += 4; buff += 4;
result += carry; addc(result, w);
result += w; }
carry = (w > result);
} while (count);
result += carry;
result = (result & 0xffff) + (result >> 16); result = (result & 0xffff) + (result >> 16);
} }
if (len & 2) { if (len & 2) {
...@@ -77,7 +93,7 @@ static inline unsigned int do_csum(const unsigned char * buff, int len) ...@@ -77,7 +93,7 @@ static inline unsigned int do_csum(const unsigned char * buff, int len)
result += le16_to_cpu(*buff); result += le16_to_cpu(*buff);
result = from32to16(result); result = from32to16(result);
if (odd) if (odd)
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); result = swab16(result);
out: out:
return result; return result;
} }
...@@ -88,12 +104,8 @@ static inline unsigned int do_csum(const unsigned char * buff, int len) ...@@ -88,12 +104,8 @@ static inline unsigned int do_csum(const unsigned char * buff, int len)
unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum) unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
{ {
unsigned int result = do_csum(buff, len); unsigned int result = do_csum(buff, len);
addc(result, sum);
/* add in old sum, and carry.. */ return from32to16(result);
result += sum;
if(sum > result)
result += 1;
return result;
} }
EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment