1#ifndef _ASM_POWERPC_CHECKSUM_H
2#define _ASM_POWERPC_CHECKSUM_H
3#ifdef __KERNEL__
4
5
6
7
8
9
10
11
12
13
14
15
16
17#ifdef CONFIG_GENERIC_CSUM
18#include <asm-generic/checksum.h>
19#else
20extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
21
22
23
24
25
26
27
28
29
30
31
32
33
34extern __wsum csum_partial(const void *buff, int len, __wsum sum);
35
36
37
38
39
40
41
42
43
44
45
46extern __wsum csum_partial_copy_generic(const void *src, void *dst,
47 int len, __wsum sum,
48 int *src_err, int *dst_err);
49
50#ifdef __powerpc64__
51#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
52extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
53 int len, __wsum sum, int *err_ptr);
54#define HAVE_CSUM_COPY_USER
55extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
56 int len, __wsum sum, int *err_ptr);
57#else
58
59
60
61
62#define csum_partial_copy_from_user(src, dst, len, sum, errp) \
63 csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL)
64#endif
65
66#define csum_partial_copy_nocheck(src, dst, len, sum) \
67 csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
68
69
70
71
72
73
74static inline __sum16 csum_fold(__wsum sum)
75{
76 unsigned int tmp;
77
78
79 __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum));
80
81
82
83 return (__force __sum16)(~((__force u32)sum + tmp) >> 16);
84}
85
86
87
88
89
90static inline __sum16 ip_compute_csum(const void *buff, int len)
91{
92 return csum_fold(csum_partial(buff, len, 0));
93}
94
95static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
96 unsigned short len,
97 unsigned short proto,
98 __wsum sum)
99{
100#ifdef __powerpc64__
101 unsigned long s = (__force u32)sum;
102
103 s += (__force u32)saddr;
104 s += (__force u32)daddr;
105 s += proto + len;
106 s += (s >> 32);
107 return (__force __wsum) s;
108#else
109 __asm__("\n\
110 addc %0,%0,%1 \n\
111 adde %0,%0,%2 \n\
112 adde %0,%0,%3 \n\
113 addze %0,%0 \n\
114 "
115 : "=r" (sum)
116 : "r" (daddr), "r"(saddr), "r"(proto + len), "0"(sum));
117 return sum;
118#endif
119}
120
121
122
123
124
125static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
126 unsigned short len,
127 unsigned short proto,
128 __wsum sum)
129{
130 return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
131}
132
133#define HAVE_ARCH_CSUM_ADD
134static inline __wsum csum_add(__wsum csum, __wsum addend)
135{
136#ifdef __powerpc64__
137 u64 res = (__force u64)csum;
138
139 res += (__force u64)addend;
140 return (__force __wsum)((u32)res + (res >> 32));
141#else
142 asm("addc %0,%0,%1;"
143 "addze %0,%0;"
144 : "+r" (csum) : "r" (addend));
145 return csum;
146#endif
147}
148
149#endif
150#endif
151#endif
152