1
2
3
4
5
6
7
8
9
10
11#ifndef _XTENSA_CHECKSUM_H
12#define _XTENSA_CHECKSUM_H
13
14#include <linux/in6.h>
15#include <asm/uaccess.h>
16#include <variant/core.h>
17
18
19
20
21
22
23
24
25
26
27
28
29
30asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum);
31
32
33
34
35
36
37
38
39
40asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst,
41 int len, __wsum sum,
42 int *src_err_ptr, int *dst_err_ptr);
43
44
45
46
47
48
49
50static inline
51__wsum csum_partial_copy_nocheck(const void *src, void *dst,
52 int len, __wsum sum)
53{
54 return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL);
55}
56
57static inline
58__wsum csum_partial_copy_from_user(const void __user *src, void *dst,
59 int len, __wsum sum, int *err_ptr)
60{
61 return csum_partial_copy_generic((__force const void *)src, dst,
62 len, sum, err_ptr, NULL);
63}
64
65
66
67
68
69static __inline__ __sum16 csum_fold(__wsum sum)
70{
71 unsigned int __dummy;
72 __asm__("extui %1, %0, 16, 16\n\t"
73 "extui %0 ,%0, 0, 16\n\t"
74 "add %0, %0, %1\n\t"
75 "slli %1, %0, 16\n\t"
76 "add %0, %0, %1\n\t"
77 "extui %0, %0, 16, 16\n\t"
78 "neg %0, %0\n\t"
79 "addi %0, %0, -1\n\t"
80 "extui %0, %0, 0, 16\n\t"
81 : "=r" (sum), "=&r" (__dummy)
82 : "0" (sum));
83 return (__force __sum16)sum;
84}
85
86
87
88
89
90static __inline__ __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
91{
92 unsigned int sum, tmp, endaddr;
93
94 __asm__ __volatile__(
95 "sub %0, %0, %0\n\t"
96#if XCHAL_HAVE_LOOPS
97 "loopgtz %2, 2f\n\t"
98#else
99 "beqz %2, 2f\n\t"
100 "slli %4, %2, 2\n\t"
101 "add %4, %4, %1\n\t"
102 "0:\t"
103#endif
104 "l32i %3, %1, 0\n\t"
105 "add %0, %0, %3\n\t"
106 "bgeu %0, %3, 1f\n\t"
107 "addi %0, %0, 1\n\t"
108 "1:\t"
109 "addi %1, %1, 4\n\t"
110#if !XCHAL_HAVE_LOOPS
111 "blt %1, %4, 0b\n\t"
112#endif
113 "2:\t"
114
115
116
117 : "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp),
118 "=&r" (endaddr)
119 : "1" (iph), "2" (ihl)
120 : "memory");
121
122 return csum_fold(sum);
123}
124
125static __inline__ __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
126 unsigned short len,
127 unsigned short proto,
128 __wsum sum)
129{
130
131#ifdef __XTENSA_EL__
132 unsigned long len_proto = (len + proto) << 8;
133#elif defined(__XTENSA_EB__)
134 unsigned long len_proto = len + proto;
135#else
136# error processor byte order undefined!
137#endif
138 __asm__("add %0, %0, %1\n\t"
139 "bgeu %0, %1, 1f\n\t"
140 "addi %0, %0, 1\n\t"
141 "1:\t"
142 "add %0, %0, %2\n\t"
143 "bgeu %0, %2, 1f\n\t"
144 "addi %0, %0, 1\n\t"
145 "1:\t"
146 "add %0, %0, %3\n\t"
147 "bgeu %0, %3, 1f\n\t"
148 "addi %0, %0, 1\n\t"
149 "1:\t"
150 : "=r" (sum), "=r" (len_proto)
151 : "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum));
152 return sum;
153}
154
155
156
157
158
159static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
160 unsigned short len,
161 unsigned short proto,
162 __wsum sum)
163{
164 return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
165}
166
167
168
169
170
171
172static __inline__ __sum16 ip_compute_csum(const void *buff, int len)
173{
174 return csum_fold (csum_partial(buff, len, 0));
175}
176
177#define _HAVE_ARCH_IPV6_CSUM
178static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
179 const struct in6_addr *daddr,
180 __u32 len, unsigned short proto,
181 __wsum sum)
182{
183 unsigned int __dummy;
184 __asm__("l32i %1, %2, 0\n\t"
185 "add %0, %0, %1\n\t"
186 "bgeu %0, %1, 1f\n\t"
187 "addi %0, %0, 1\n\t"
188 "1:\t"
189 "l32i %1, %2, 4\n\t"
190 "add %0, %0, %1\n\t"
191 "bgeu %0, %1, 1f\n\t"
192 "addi %0, %0, 1\n\t"
193 "1:\t"
194 "l32i %1, %2, 8\n\t"
195 "add %0, %0, %1\n\t"
196 "bgeu %0, %1, 1f\n\t"
197 "addi %0, %0, 1\n\t"
198 "1:\t"
199 "l32i %1, %2, 12\n\t"
200 "add %0, %0, %1\n\t"
201 "bgeu %0, %1, 1f\n\t"
202 "addi %0, %0, 1\n\t"
203 "1:\t"
204 "l32i %1, %3, 0\n\t"
205 "add %0, %0, %1\n\t"
206 "bgeu %0, %1, 1f\n\t"
207 "addi %0, %0, 1\n\t"
208 "1:\t"
209 "l32i %1, %3, 4\n\t"
210 "add %0, %0, %1\n\t"
211 "bgeu %0, %1, 1f\n\t"
212 "addi %0, %0, 1\n\t"
213 "1:\t"
214 "l32i %1, %3, 8\n\t"
215 "add %0, %0, %1\n\t"
216 "bgeu %0, %1, 1f\n\t"
217 "addi %0, %0, 1\n\t"
218 "1:\t"
219 "l32i %1, %3, 12\n\t"
220 "add %0, %0, %1\n\t"
221 "bgeu %0, %1, 1f\n\t"
222 "addi %0, %0, 1\n\t"
223 "1:\t"
224 "add %0, %0, %4\n\t"
225 "bgeu %0, %4, 1f\n\t"
226 "addi %0, %0, 1\n\t"
227 "1:\t"
228 "add %0, %0, %5\n\t"
229 "bgeu %0, %5, 1f\n\t"
230 "addi %0, %0, 1\n\t"
231 "1:\t"
232 : "=r" (sum), "=&r" (__dummy)
233 : "r" (saddr), "r" (daddr),
234 "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
235 : "memory");
236
237 return csum_fold(sum);
238}
239
240
241
242
243#define HAVE_CSUM_COPY_USER
244static __inline__ __wsum csum_and_copy_to_user(const void *src,
245 void __user *dst, int len,
246 __wsum sum, int *err_ptr)
247{
248 if (access_ok(VERIFY_WRITE, dst, len))
249 return csum_partial_copy_generic(src,dst,len,sum,NULL,err_ptr);
250
251 if (len)
252 *err_ptr = -EFAULT;
253
254 return (__force __wsum)-1;
255}
256#endif
257