X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fparisc%2Flib%2Fchecksum.c;h=9866c93f1e6f9c705f9c03b6cee119a7506b98d7;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=abd29ac69f46b473f7aba1be299924c74abc7d37;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c index abd29ac69..9866c93f1 100644 --- a/arch/parisc/lib/checksum.c +++ b/arch/parisc/lib/checksum.c @@ -24,6 +24,13 @@ #include #include +#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) { /* 32 bits --> 16 bits + carry */ @@ -56,16 +63,25 @@ static inline unsigned int do_csum(const unsigned char * buff, int len) } count >>= 1; /* nr of 32-bit words.. */ if (count) { - unsigned int carry = 0; - do { + while (count >= 4) { + 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; count--; buff += 4; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; + addc(result, w); + } result = (result & 0xffff) + (result >> 16); } if (len & 2) { @@ -77,7 +93,7 @@ static inline unsigned int do_csum(const unsigned char * buff, int len) result += le16_to_cpu(*buff); result = from32to16(result); if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + result = swab16(result); out: return result; } @@ -88,12 +104,8 @@ out: unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum) { unsigned int result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += sum; - if(sum > result) - result += 1; - return result; + addc(result, sum); + return from32to16(result); } EXPORT_SYMBOL(csum_partial); @@ -101,7 +113,7 @@ EXPORT_SYMBOL(csum_partial); /* * copy while checksumming, otherwise like csum_partial */ -unsigned int csum_partial_copy_nocheck(const char *src, char *dst, +unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, int len, unsigned int sum) { /* @@ -119,7 +131,7 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck); * Copy from userspace and compute checksum. If we catch an exception * then zero the rest of the buffer. */ -unsigned int csum_partial_copy_from_user (const char *src, char *dst, +unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst, int len, unsigned int sum, int *err_ptr) {