xref: /linux/arch/x86/um/asm/checksum_32.h (revision c0c914eca7f251c70facc37dfebeaf176601918d)
1 /*
2  * Licensed under the GPL
3  */
4 
5 #ifndef __UM_SYSDEP_CHECKSUM_H
6 #define __UM_SYSDEP_CHECKSUM_H
7 
8 static inline __sum16 ip_compute_csum(const void *buff, int len)
9 {
10     return csum_fold (csum_partial(buff, len, 0));
11 }
12 
13 #define _HAVE_ARCH_IPV6_CSUM
14 static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
15 					  const struct in6_addr *daddr,
16 					  __u32 len, unsigned short proto,
17 					  __wsum sum)
18 {
19 	__asm__(
20 		"addl 0(%1), %0		;\n"
21 		"adcl 4(%1), %0		;\n"
22 		"adcl 8(%1), %0		;\n"
23 		"adcl 12(%1), %0	;\n"
24 		"adcl 0(%2), %0		;\n"
25 		"adcl 4(%2), %0		;\n"
26 		"adcl 8(%2), %0		;\n"
27 		"adcl 12(%2), %0	;\n"
28 		"adcl %3, %0		;\n"
29 		"adcl %4, %0		;\n"
30 		"adcl $0, %0		;\n"
31 		: "=&r" (sum)
32 		: "r" (saddr), "r" (daddr),
33 		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
34 
35 	return csum_fold(sum);
36 }
37 
38 /*
39  *	Copy and checksum to user
40  */
41 #define HAVE_CSUM_COPY_USER
42 static __inline__ __wsum csum_and_copy_to_user(const void *src,
43 						     void __user *dst,
44 						     int len, __wsum sum, int *err_ptr)
45 {
46 	if (access_ok(VERIFY_WRITE, dst, len)) {
47 		if (copy_to_user(dst, src, len)) {
48 			*err_ptr = -EFAULT;
49 			return (__force __wsum)-1;
50 		}
51 
52 		return csum_partial(src, len, sum);
53 	}
54 
55 	if (len)
56 		*err_ptr = -EFAULT;
57 
58 	return (__force __wsum)-1; /* invalid checksum */
59 }
60 
61 #endif
62