1
2#ifndef _ASM_X86_CHECKSUM_32_H
3#define _ASM_X86_CHECKSUM_32_H
4
5#include <linux/in6.h>
6#include <linux/uaccess.h>
7
8
9
10
11
12
13
14
15
16
17
18
19
20asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
21
22
23
24
25
26
27
28
29
30asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
31 int len, __wsum sum,
32 int *src_err_ptr, int *dst_err_ptr);
33
34
35
36
37
38
39
40
41static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst,
42 int len, __wsum sum)
43{
44 return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
45}
46
47static inline __wsum csum_and_copy_from_user(const void __user *src,
48 void *dst, int len,
49 __wsum sum, int *err_ptr)
50{
51 __wsum ret;
52
53 might_sleep();
54 if (!user_access_begin(src, len)) {
55 if (len)
56 *err_ptr = -EFAULT;
57 return sum;
58 }
59 ret = csum_partial_copy_generic((__force void *)src, dst,
60 len, sum, err_ptr, NULL);
61 user_access_end();
62
63 return ret;
64}
65
66
67
68
69
70
71
72
73static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
74{
75 unsigned int sum;
76
77 asm volatile("movl (%1), %0 ;\n"
78 "subl $4, %2 ;\n"
79 "jbe 2f ;\n"
80 "addl 4(%1), %0 ;\n"
81 "adcl 8(%1), %0 ;\n"
82 "adcl 12(%1), %0;\n"
83 "1: adcl 16(%1), %0 ;\n"
84 "lea 4(%1), %1 ;\n"
85 "decl %2 ;\n"
86 "jne 1b ;\n"
87 "adcl $0, %0 ;\n"
88 "movl %0, %2 ;\n"
89 "shrl $16, %0 ;\n"
90 "addw %w2, %w0 ;\n"
91 "adcl $0, %0 ;\n"
92 "notl %0 ;\n"
93 "2: ;\n"
94
95
96
97 : "=r" (sum), "=r" (iph), "=r" (ihl)
98 : "1" (iph), "2" (ihl)
99 : "memory");
100 return (__force __sum16)sum;
101}
102
103
104
105
106
107static inline __sum16 csum_fold(__wsum sum)
108{
109 asm("addl %1, %0 ;\n"
110 "adcl $0xffff, %0 ;\n"
111 : "=r" (sum)
112 : "r" ((__force u32)sum << 16),
113 "0" ((__force u32)sum & 0xffff0000));
114 return (__force __sum16)(~(__force u32)sum >> 16);
115}
116
117static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
118 __u32 len, __u8 proto,
119 __wsum sum)
120{
121 asm("addl %1, %0 ;\n"
122 "adcl %2, %0 ;\n"
123 "adcl %3, %0 ;\n"
124 "adcl $0, %0 ;\n"
125 : "=r" (sum)
126 : "g" (daddr), "g"(saddr),
127 "g" ((len + proto) << 8), "0" (sum));
128 return sum;
129}
130
131
132
133
134
135static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
136 __u32 len, __u8 proto,
137 __wsum sum)
138{
139 return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
140}
141
142
143
144
145
146
147static inline __sum16 ip_compute_csum(const void *buff, int len)
148{
149 return csum_fold(csum_partial(buff, len, 0));
150}
151
152#define _HAVE_ARCH_IPV6_CSUM
153static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
154 const struct in6_addr *daddr,
155 __u32 len, __u8 proto, __wsum sum)
156{
157 asm("addl 0(%1), %0 ;\n"
158 "adcl 4(%1), %0 ;\n"
159 "adcl 8(%1), %0 ;\n"
160 "adcl 12(%1), %0 ;\n"
161 "adcl 0(%2), %0 ;\n"
162 "adcl 4(%2), %0 ;\n"
163 "adcl 8(%2), %0 ;\n"
164 "adcl 12(%2), %0 ;\n"
165 "adcl %3, %0 ;\n"
166 "adcl %4, %0 ;\n"
167 "adcl $0, %0 ;\n"
168 : "=&r" (sum)
169 : "r" (saddr), "r" (daddr),
170 "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
171 : "memory");
172
173 return csum_fold(sum);
174}
175
176
177
178
179static inline __wsum csum_and_copy_to_user(const void *src,
180 void __user *dst,
181 int len, __wsum sum,
182 int *err_ptr)
183{
184 __wsum ret;
185
186 might_sleep();
187 if (user_access_begin(dst, len)) {
188 ret = csum_partial_copy_generic(src, (__force void *)dst,
189 len, sum, NULL, err_ptr);
190 user_access_end();
191 return ret;
192 }
193
194 if (len)
195 *err_ptr = -EFAULT;
196
197 return (__force __wsum)-1;
198}
199
200#endif
201