summaryrefslogtreecommitdiffstats
path: root/include/asm-ppc/checksum.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-ppc/checksum.h')
-rw-r--r--include/asm-ppc/checksum.h93
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