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