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