--- zzzz-none-000/linux-2.6.28.10/arch/mips/include/asm/checksum.h 2009-05-02 18:54:43.000000000 +0000 +++ fusiv-7390-686/linux-2.6.28.10/arch/mips/include/asm/checksum.h 2012-02-14 14:37:49.000000000 +0000 @@ -27,10 +27,10 @@ * * it's best to have buff aligned on a 32-bit boundary */ -__wsum csum_partial(const void *buff, int len, __wsum sum); +__wsum csum_partial(const void *buff, int len, __wsum sum) __attribute__ ((hot)); __wsum __csum_partial_copy_user(const void *src, void *dst, - int len, __wsum sum, int *err_ptr); + int len, __wsum sum, int *err_ptr) __attribute__ ((hot)); /* * this is a new version of the above that records errors it finds in *errp, @@ -68,11 +68,12 @@ * we have just one address space, so this is identical to the above) */ __wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum); + int len, __wsum sum) __attribute__ ((hot)); /* * Fold a partial checksum without adding pseudo headers */ +static inline __sum16 csum_fold(__wsum sum) __attribute__ ((hot)); static inline __sum16 csum_fold(__wsum sum) { __asm__( @@ -98,6 +99,7 @@ * By Jorge Cwik , adapted for linux by * Arnt Gulbrandsen. */ +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) __attribute__ ((hot)); static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) { const unsigned int *word = iph; @@ -105,6 +107,43 @@ unsigned int csum; int carry; +#if defined(CONFIG_FUSIV_VX185) && defined(CONFIG_FUSIV_ALIGNMENT_FIXUPS) + const unsigned short *halfword = (const unsigned short *)word; + unsigned int last_csum; + + if (likely(((unsigned int)iph & 3) == 2)) { + /* Handle 2 byte mis-aligned IP header */ + word = (const unsigned int *)(halfword + 1); + stop = (const unsigned int *)((unsigned int)stop & ~2); + csum = halfword[0]; + csum += word[0]; + carry = (csum < word[0]); + csum += carry; + + csum += word[1]; + carry = (csum < word[1]); + csum += carry; + + csum += word[2]; + carry = (csum < word[2]); + csum += carry; + + word += 3; + do { + csum += *word; + carry = (csum < *word); + csum += carry; + word++; + } while (word != stop); + + last_csum = csum; + csum += *(unsigned short *)word; + carry = (csum < last_csum); + csum += carry; + + return csum_fold(csum); + } +#endif csum = word[0]; csum += word[1]; carry = (csum < word[1]);