diff options
Diffstat (limited to 'include/asm-ppc/checksum.h')
-rw-r--r-- | include/asm-ppc/checksum.h | 93 |
1 files changed, 55 insertions, 38 deletions
diff --git a/include/asm-ppc/checksum.h b/include/asm-ppc/checksum.h index 7b55f0032..1395cb0aa 100644 --- a/include/asm-ppc/checksum.h +++ b/include/asm-ppc/checksum.h @@ -3,22 +3,6 @@ /* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -extern unsigned short int csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum); - -/* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) * @@ -30,43 +14,76 @@ extern unsigned short int csum_tcpudp_magic(unsigned long saddr, * * it's best to have buff aligned on a 32-bit boundary */ -extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); +extern unsigned int csum_partial(const unsigned char * buff, int len, + unsigned int sum); /* - * the same as csum_partial, but copies from src while it - * checksums + * Computes the checksum of a memory block at src, length len, + * and adds in "sum" (32-bit), while copying the block to dst. + * If an access exception occurs on src or dst, it stores -EFAULT + * to *src_err or *dst_err respectively (if that pointer is not + * NULL), and, for an error on src, zeroes the rest of dst. * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary + * Like csum_partial, this must be called with even lengths, + * except for the last fragment. */ -unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum); +extern unsigned int csum_partial_copy_generic(const char *src, char *dst, + int len, unsigned int sum, + int *src_err, int *dst_err); + +#define csum_partial_copy_from_user(src, dst, len, sum, errp) \ + csum_partial_copy_generic((src), (dst), (len), (sum), (errp), 0) /* - * the same as csum_partial, but copies from user space (but on the alpha - * we have just one address space, so this is identical to the above) + * Old versions which ignore errors. */ -#define csum_partial_copy_fromuser csum_partial_copy +#define csum_partial_copy(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0) +#define csum_partial_copy_fromuser(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0) + /* - * this is a new version of the above that records errors it finds in *errp, - * but continues and zeros the rest of the buffer. - * - * right now - it just calls csum_partial_copy() - * -- Cort + * turns a 32-bit partial checksum (e.g. from csum_partial) into a + * 1's complement 16-bit checksum. */ -extern __inline__ -unsigned int csum_partial_copy_from_user ( const char *src, char *dst, - int len, int sum, int *err_ptr) +static inline unsigned int csum_fold(unsigned int sum) { - int *dst_err_ptr=NULL; - return csum_partial_copy( src, dst, len, sum); + unsigned int tmp; + + /* swap the two 16-bit halves of sum */ + __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); + /* if there is a carry from adding the two 16-bit halves, + it will carry from the lower half into the upper half, + giving us the correct sum in the upper half. */ + sum = ~(sum + tmp) >> 16; + return sum; } /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c -A */ + */ +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. ihl is the number + * of 32-bit words and is always >= 5. + */ +extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +extern unsigned short csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum); -extern unsigned short ip_compute_csum(unsigned char * buff, int len); -extern unsigned int csum_fold(unsigned int sum); #endif |