~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/include/asm/checksum.h

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * This file is subject to the terms and conditions of the GNU General Public
  3  * License.  See the file "COPYING" in the main directory of this archive
  4  * for more details.
  5  *
  6  * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle
  7  * Copyright (C) 1999 Silicon Graphics, Inc.
  8  * Copyright (C) 2001 Thiemo Seufer.
  9  * Copyright (C) 2002 Maciej W. Rozycki
 10  * Copyright (C) 2014 Imagination Technologies Ltd.
 11  */
 12 #ifndef _ASM_CHECKSUM_H
 13 #define _ASM_CHECKSUM_H
 14 
 15 #ifdef CONFIG_GENERIC_CSUM
 16 #include <asm-generic/checksum.h>
 17 #else
 18 
 19 #include <linux/in6.h>
 20 
 21 #include <asm/uaccess.h>
 22 
 23 /*
 24  * computes the checksum of a memory block at buff, length len,
 25  * and adds in "sum" (32-bit)
 26  *
 27  * returns a 32-bit number suitable for feeding into itself
 28  * or csum_tcpudp_magic
 29  *
 30  * this function must be called with even lengths, except
 31  * for the last fragment, which may be odd
 32  *
 33  * it's best to have buff aligned on a 32-bit boundary
 34  */
 35 __wsum csum_partial(const void *buff, int len, __wsum sum);
 36 
 37 __wsum __csum_partial_copy_kernel(const void *src, void *dst,
 38                                   int len, __wsum sum, int *err_ptr);
 39 
 40 __wsum __csum_partial_copy_from_user(const void *src, void *dst,
 41                                      int len, __wsum sum, int *err_ptr);
 42 __wsum __csum_partial_copy_to_user(const void *src, void *dst,
 43                                    int len, __wsum sum, int *err_ptr);
 44 /*
 45  * this is a new version of the above that records errors it finds in *errp,
 46  * but continues and zeros the rest of the buffer.
 47  */
 48 static inline
 49 __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
 50                                    __wsum sum, int *err_ptr)
 51 {
 52         might_fault();
 53         if (segment_eq(get_fs(), get_ds()))
 54                 return __csum_partial_copy_kernel((__force void *)src, dst,
 55                                                   len, sum, err_ptr);
 56         else
 57                 return __csum_partial_copy_from_user((__force void *)src, dst,
 58                                                      len, sum, err_ptr);
 59 }
 60 
 61 #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
 62 static inline
 63 __wsum csum_and_copy_from_user(const void __user *src, void *dst,
 64                                int len, __wsum sum, int *err_ptr)
 65 {
 66         if (access_ok(VERIFY_READ, src, len))
 67                 return csum_partial_copy_from_user(src, dst, len, sum,
 68                                                    err_ptr);
 69         if (len)
 70                 *err_ptr = -EFAULT;
 71 
 72         return sum;
 73 }
 74 
 75 /*
 76  * Copy and checksum to user
 77  */
 78 #define HAVE_CSUM_COPY_USER
 79 static inline
 80 __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
 81                              __wsum sum, int *err_ptr)
 82 {
 83         might_fault();
 84         if (access_ok(VERIFY_WRITE, dst, len)) {
 85                 if (segment_eq(get_fs(), get_ds()))
 86                         return __csum_partial_copy_kernel(src,
 87                                                           (__force void *)dst,
 88                                                           len, sum, err_ptr);
 89                 else
 90                         return __csum_partial_copy_to_user(src,
 91                                                            (__force void *)dst,
 92                                                            len, sum, err_ptr);
 93         }
 94         if (len)
 95                 *err_ptr = -EFAULT;
 96 
 97         return (__force __wsum)-1; /* invalid checksum */
 98 }
 99 
100 /*
101  * the same as csum_partial, but copies from user space (but on MIPS
102  * we have just one address space, so this is identical to the above)
103  */
104 __wsum csum_partial_copy_nocheck(const void *src, void *dst,
105                                        int len, __wsum sum);
106 #define csum_partial_copy_nocheck csum_partial_copy_nocheck
107 
108 /*
109  *      Fold a partial checksum without adding pseudo headers
110  */
111 static inline __sum16 csum_fold(__wsum csum)
112 {
113         u32 sum = (__force u32)csum;;
114 
115         sum += (sum << 16);
116         csum = (sum < csum);
117         sum >>= 16;
118         sum += csum;
119 
120         return (__force __sum16)~sum;
121 }
122 #define csum_fold csum_fold
123 
124 /*
125  *      This is a version of ip_compute_csum() optimized for IP headers,
126  *      which always checksum on 4 octet boundaries.
127  *
128  *      By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
129  *      Arnt Gulbrandsen.
130  */
131 static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
132 {
133         const unsigned int *word = iph;
134         const unsigned int *stop = word + ihl;
135         unsigned int csum;
136         int carry;
137 
138         csum = word[0];
139         csum += word[1];
140         carry = (csum < word[1]);
141         csum += carry;
142 
143         csum += word[2];
144         carry = (csum < word[2]);
145         csum += carry;
146 
147         csum += word[3];
148         carry = (csum < word[3]);
149         csum += carry;
150 
151         word += 4;
152         do {
153                 csum += *word;
154                 carry = (csum < *word);
155                 csum += carry;
156                 word++;
157         } while (word != stop);
158 
159         return csum_fold(csum);
160 }
161 #define ip_fast_csum ip_fast_csum
162 
163 static inline __wsum csum_tcpudp_nofold(__be32 saddr,
164         __be32 daddr, unsigned short len, unsigned short proto,
165         __wsum sum)
166 {
167         __asm__(
168         "       .set    push            # csum_tcpudp_nofold\n"
169         "       .set    noat            \n"
170 #ifdef CONFIG_32BIT
171         "       addu    %0, %2          \n"
172         "       sltu    $1, %0, %2      \n"
173         "       addu    %0, $1          \n"
174 
175         "       addu    %0, %3          \n"
176         "       sltu    $1, %0, %3      \n"
177         "       addu    %0, $1          \n"
178 
179         "       addu    %0, %4          \n"
180         "       sltu    $1, %0, %4      \n"
181         "       addu    %0, $1          \n"
182 #endif
183 #ifdef CONFIG_64BIT
184         "       daddu   %0, %2          \n"
185         "       daddu   %0, %3          \n"
186         "       daddu   %0, %4          \n"
187         "       dsll32  $1, %0, 0       \n"
188         "       daddu   %0, $1          \n"
189         "       dsra32  %0, %0, 0       \n"
190 #endif
191         "       .set    pop"
192         : "=r" (sum)
193         : "" ((__force unsigned long)daddr),
194           "r" ((__force unsigned long)saddr),
195 #ifdef __MIPSEL__
196           "r" ((proto + len) << 8),
197 #else
198           "r" (proto + len),
199 #endif
200           "r" ((__force unsigned long)sum));
201 
202         return sum;
203 }
204 #define csum_tcpudp_nofold csum_tcpudp_nofold
205 
206 /*
207  * this routine is used for miscellaneous IP-like checksums, mainly
208  * in icmp.c
209  */
210 static inline __sum16 ip_compute_csum(const void *buff, int len)
211 {
212         return csum_fold(csum_partial(buff, len, 0));
213 }
214 
215 #define _HAVE_ARCH_IPV6_CSUM
216 static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
217                                           const struct in6_addr *daddr,
218                                           __u32 len, unsigned short proto,
219                                           __wsum sum)
220 {
221         __wsum tmp;
222 
223         __asm__(
224         "       .set    push            # csum_ipv6_magic\n"
225         "       .set    noreorder       \n"
226         "       .set    noat            \n"
227         "       addu    %0, %5          # proto (long in network byte order)\n"
228         "       sltu    $1, %0, %5      \n"
229         "       addu    %0, $1          \n"
230 
231         "       addu    %0, %6          # csum\n"
232         "       sltu    $1, %0, %6      \n"
233         "       lw      %1, 0(%2)       # four words source address\n"
234         "       addu    %0, $1          \n"
235         "       addu    %0, %1          \n"
236         "       sltu    $1, %0, %1      \n"
237 
238         "       lw      %1, 4(%2)       \n"
239         "       addu    %0, $1          \n"
240         "       addu    %0, %1          \n"
241         "       sltu    $1, %0, %1      \n"
242 
243         "       lw      %1, 8(%2)       \n"
244         "       addu    %0, $1          \n"
245         "       addu    %0, %1          \n"
246         "       sltu    $1, %0, %1      \n"
247 
248         "       lw      %1, 12(%2)      \n"
249         "       addu    %0, $1          \n"
250         "       addu    %0, %1          \n"
251         "       sltu    $1, %0, %1      \n"
252 
253         "       lw      %1, 0(%3)       \n"
254         "       addu    %0, $1          \n"
255         "       addu    %0, %1          \n"
256         "       sltu    $1, %0, %1      \n"
257 
258         "       lw      %1, 4(%3)       \n"
259         "       addu    %0, $1          \n"
260         "       addu    %0, %1          \n"
261         "       sltu    $1, %0, %1      \n"
262 
263         "       lw      %1, 8(%3)       \n"
264         "       addu    %0, $1          \n"
265         "       addu    %0, %1          \n"
266         "       sltu    $1, %0, %1      \n"
267 
268         "       lw      %1, 12(%3)      \n"
269         "       addu    %0, $1          \n"
270         "       addu    %0, %1          \n"
271         "       sltu    $1, %0, %1      \n"
272 
273         "       addu    %0, $1          # Add final carry\n"
274         "       .set    pop"
275         : "=&r" (sum), "=&r" (tmp)
276         : "r" (saddr), "r" (daddr),
277           "" (htonl(len)), "r" (htonl(proto)), "r" (sum));
278 
279         return csum_fold(sum);
280 }
281 
282 #include <asm-generic/checksum.h>
283 #endif /* CONFIG_GENERIC_CSUM */
284 
285 #endif /* _ASM_CHECKSUM_H */
286 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp