aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-03-26 14:42:39 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2007-03-26 14:43:46 -0400
commitafbc1e994ddcf3b6fe2dc928ee8dc31a5d0c3118 (patch)
tree95ccefc1b49aa275d06c39f9bd386a7d2ceb7d6a
parent04439694ea82fed62a97fd474147966381201954 (diff)
[S390] Fix TCP/UDP pseudo header checksum computation.
git commit f994aae1bd8e4813d59a2ed64d17585fe42d03fc changed the function declaration of csum_tcpudp_nofold. Argument types were changed from unsigned long to __be32 (unsigned int). Therefore we lost the implicit type conversion that zeroed the upper half of the registers that are used to pass parameters. Since the inline assembly relied on this we ended up adding random values and wrong checksums were created. Showed only up on machines with more than 4GB since gcc produced code where the registers that are used to pass 'saddr' and 'daddr' previously contained addresses before calling this function. Fix this by using 32 bit arithmetics and convert code to C, since gcc produces better code than these hand-optimized versions. Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
-rw-r--r--include/asm-s390/checksum.h59
1 files changed, 15 insertions, 44 deletions
diff --git a/include/asm-s390/checksum.h b/include/asm-s390/checksum.h
index 0a3cd7ec845..d5a8e7c1477 100644
--- a/include/asm-s390/checksum.h
+++ b/include/asm-s390/checksum.h
@@ -121,50 +121,21 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
121 unsigned short len, unsigned short proto, 121 unsigned short len, unsigned short proto,
122 __wsum sum) 122 __wsum sum)
123{ 123{
124#ifndef __s390x__ 124 __u32 csum = (__force __u32)sum;
125 asm volatile( 125
126 " alr %0,%1\n" /* sum += saddr */ 126 csum += (__force __u32)saddr;
127 " brc 12,0f\n" 127 if (csum < (__force __u32)saddr)
128 " ahi %0,1\n" /* add carry */ 128 csum++;
129 "0:" 129
130 : "+&d" (sum) : "d" (saddr) : "cc"); 130 csum += (__force __u32)daddr;
131 asm volatile( 131 if (csum < (__force __u32)daddr)
132 " alr %0,%1\n" /* sum += daddr */ 132 csum++;
133 " brc 12,1f\n" 133
134 " ahi %0,1\n" /* add carry */ 134 csum += len + proto;
135 "1:" 135 if (csum < len + proto)
136 : "+&d" (sum) : "d" (daddr) : "cc"); 136 csum++;
137 asm volatile( 137
138 " alr %0,%1\n" /* sum += len + proto */ 138 return (__force __wsum)csum;
139 " brc 12,2f\n"
140 " ahi %0,1\n" /* add carry */
141 "2:"
142 : "+&d" (sum)
143 : "d" (len + proto)
144 : "cc");
145#else /* __s390x__ */
146 asm volatile(
147 " lgfr %0,%0\n"
148 " algr %0,%1\n" /* sum += saddr */
149 " brc 12,0f\n"
150 " aghi %0,1\n" /* add carry */
151 "0: algr %0,%2\n" /* sum += daddr */
152 " brc 12,1f\n"
153 " aghi %0,1\n" /* add carry */
154 "1: algfr %0,%3\n" /* sum += len + proto */
155 " brc 12,2f\n"
156 " aghi %0,1\n" /* add carry */
157 "2: srlg 0,%0,32\n"
158 " alr %0,0\n" /* fold to 32 bits */
159 " brc 12,3f\n"
160 " ahi %0,1\n" /* add carry */
161 "3: llgfr %0,%0"
162 : "+&d" (sum)
163 : "d" (saddr), "d" (daddr),
164 "d" (len + proto)
165 : "cc", "0");
166#endif /* __s390x__ */
167 return sum;
168} 139}
169 140
170/* 141/*