Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / arch / blackfin / include / asm / checksum.h
1 /*
2  * Copyright 2004-2009 Analog Devices Inc.
3  *                     akbar.hussain@lineo.com
4  *
5  * Licensed under the GPL-2 or later.
6  */
7
8 #ifndef _BFIN_CHECKSUM_H
9 #define _BFIN_CHECKSUM_H
10
11 /*
12  * computes the checksum of a memory block at buff, length len,
13  * and adds in "sum" (32-bit)
14  *
15  * returns a 32-bit number suitable for feeding into itself
16  * or csum_tcpudp_magic
17  *
18  * this function must be called with even lengths, except
19  * for the last fragment, which may be odd
20  *
21  * it's best to have buff aligned on a 32-bit boundary
22  */
23 __wsum csum_partial(const void *buff, int len, __wsum sum);
24
25 /*
26  * the same as csum_partial, but copies from src while it
27  * checksums
28  *
29  * here even more important to align src and dst on a 32-bit (or even
30  * better 64-bit) boundary
31  */
32
33 __wsum csum_partial_copy(const void *src, void *dst,
34                                int len, __wsum sum);
35
36 /*
37  * the same as csum_partial_copy, but copies from user space.
38  *
39  * here even more important to align src and dst on a 32-bit (or even
40  * better 64-bit) boundary
41  */
42
43 extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
44                                           int len, __wsum sum, int *csum_err);
45
46 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
47         csum_partial_copy((src), (dst), (len), (sum))
48
49 __sum16 ip_fast_csum(unsigned char *iph, unsigned int ihl);
50
51 /*
52  *      Fold a partial checksum
53  */
54
55 static inline __sum16 csum_fold(__wsum sum)
56 {
57         while (sum >> 16)
58                 sum = (sum & 0xffff) + (sum >> 16);
59         return ((~(sum << 16)) >> 16);
60 }
61
62 /*
63  * computes the checksum of the TCP/UDP pseudo-header
64  * returns a 16-bit checksum, already complemented
65  */
66
67 static inline __wsum
68 csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
69                    unsigned short proto, __wsum sum)
70 {
71         unsigned int carry;
72
73         __asm__ ("%0 = %0 + %2;\n\t"
74                 "CC = AC0;\n\t"
75                 "%1 = CC;\n\t"
76                 "%0 = %0 + %1;\n\t"
77                 "%0 = %0 + %3;\n\t"
78                 "CC = AC0;\n\t"
79                 "%1 = CC;\n\t"
80                 "%0 = %0 + %1;\n\t"
81                 "%0 = %0 + %4;\n\t"
82                 "CC = AC0;\n\t"
83                 "%1 = CC;\n\t"
84                 "%0 = %0 + %1;\n\t"
85                 : "=d" (sum), "=&d" (carry)
86                 : "d" (daddr), "d" (saddr), "d" ((len + proto) << 8), "0"(sum)
87                 : "CC");
88
89         return (sum);
90 }
91
92 static inline __sum16
93 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
94                   unsigned short proto, __wsum sum)
95 {
96         return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
97 }
98
99 /*
100  * this routine is used for miscellaneous IP-like checksums, mainly
101  * in icmp.c
102  */
103
104 extern __sum16 ip_compute_csum(const void *buff, int len);
105
106 #endif                          /* _BFIN_CHECKSUM_H */