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 <linux/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 __u32 len, __u8 proto,
127 __wsum sum)
128{
129
130#ifdef __XTENSA_EL__
131 unsigned long len_proto = (len + proto) << 8;
132#elif defined(__XTENSA_EB__)
133 unsigned long len_proto = len + proto;
134#else
135# error processor byte order undefined!
136#endif
137 __asm__("add %0, %0, %1\n\t"
138 "bgeu %0, %1, 1f\n\t"
139 "addi %0, %0, 1\n\t"
140 "1:\t"
141 "add %0, %0, %2\n\t"
142 "bgeu %0, %2, 1f\n\t"
143 "addi %0, %0, 1\n\t"
144 "1:\t"
145 "add %0, %0, %3\n\t"
146 "bgeu %0, %3, 1f\n\t"
147 "addi %0, %0, 1\n\t"
148 "1:\t"
149 : "=r" (sum), "=r" (len_proto)
150 : "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum));
151 return sum;
152}
153
154
155
156
157
158static __inline__ __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
159 __u32 len, __u8 proto,
160 __wsum sum)
161{
162 return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
163}
164
165
166
167
168
169
170static __inline__ __sum16 ip_compute_csum(const void *buff, int len)
171{
172 return csum_fold (csum_partial(buff, len, 0));
173}
174
175#define _HAVE_ARCH_IPV6_CSUM
176static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
177 const struct in6_addr *daddr,
178 __u32 len, __u8 proto,
179 __wsum sum)
180{
181 unsigned int __dummy;
182 __asm__("l32i %1, %2, 0\n\t"
183 "add %0, %0, %1\n\t"
184 "bgeu %0, %1, 1f\n\t"
185 "addi %0, %0, 1\n\t"
186 "1:\t"
187 "l32i %1, %2, 4\n\t"
188 "add %0, %0, %1\n\t"
189 "bgeu %0, %1, 1f\n\t"
190 "addi %0, %0, 1\n\t"
191 "1:\t"
192 "l32i %1, %2, 8\n\t"
193 "add %0, %0, %1\n\t"
194 "bgeu %0, %1, 1f\n\t"
195 "addi %0, %0, 1\n\t"
196 "1:\t"
197 "l32i %1, %2, 12\n\t"
198 "add %0, %0, %1\n\t"
199 "bgeu %0, %1, 1f\n\t"
200 "addi %0, %0, 1\n\t"
201 "1:\t"
202 "l32i %1, %3, 0\n\t"
203 "add %0, %0, %1\n\t"
204 "bgeu %0, %1, 1f\n\t"
205 "addi %0, %0, 1\n\t"
206 "1:\t"
207 "l32i %1, %3, 4\n\t"
208 "add %0, %0, %1\n\t"
209 "bgeu %0, %1, 1f\n\t"
210 "addi %0, %0, 1\n\t"
211 "1:\t"
212 "l32i %1, %3, 8\n\t"
213 "add %0, %0, %1\n\t"
214 "bgeu %0, %1, 1f\n\t"
215 "addi %0, %0, 1\n\t"
216 "1:\t"
217 "l32i %1, %3, 12\n\t"
218 "add %0, %0, %1\n\t"
219 "bgeu %0, %1, 1f\n\t"
220 "addi %0, %0, 1\n\t"
221 "1:\t"
222 "add %0, %0, %4\n\t"
223 "bgeu %0, %4, 1f\n\t"
224 "addi %0, %0, 1\n\t"
225 "1:\t"
226 "add %0, %0, %5\n\t"
227 "bgeu %0, %5, 1f\n\t"
228 "addi %0, %0, 1\n\t"
229 "1:\t"
230 : "=r" (sum), "=&r" (__dummy)
231 : "r" (saddr), "r" (daddr),
232 "r" (htonl(len)), "r" (htonl(proto)), "0" (sum)
233 : "memory");
234
235 return csum_fold(sum);
236}
237
238
239
240
241#define HAVE_CSUM_COPY_USER
242static __inline__ __wsum csum_and_copy_to_user(const void *src,
243 void __user *dst, int len,
244 __wsum sum, int *err_ptr)
245{
246 if (access_ok(VERIFY_WRITE, dst, len))
247 return csum_partial_copy_generic(src,dst,len,sum,NULL,err_ptr);
248
249 if (len)
250 *err_ptr = -EFAULT;
251
252 return (__force __wsum)-1;
253}
254#endif
255