aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86/checksum_64.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-x86/checksum_64.h')
-rw-r--r--include/asm-x86/checksum_64.h118
1 files changed, 57 insertions, 61 deletions
diff --git a/include/asm-x86/checksum_64.h b/include/asm-x86/checksum_64.h
index e5f79997decc..8bd861cc5267 100644
--- a/include/asm-x86/checksum_64.h
+++ b/include/asm-x86/checksum_64.h
@@ -1,33 +1,31 @@
1#ifndef _X86_64_CHECKSUM_H 1#ifndef _X86_64_CHECKSUM_H
2#define _X86_64_CHECKSUM_H 2#define _X86_64_CHECKSUM_H
3 3
4/* 4/*
5 * Checksums for x86-64 5 * Checksums for x86-64
6 * Copyright 2002 by Andi Kleen, SuSE Labs 6 * Copyright 2002 by Andi Kleen, SuSE Labs
7 * with some code from asm-x86/checksum.h 7 * with some code from asm-x86/checksum.h
8 */ 8 */
9 9
10#include <linux/compiler.h> 10#include <linux/compiler.h>
11#include <asm/uaccess.h> 11#include <asm/uaccess.h>
12#include <asm/byteorder.h> 12#include <asm/byteorder.h>
13 13
14/** 14/**
15 * csum_fold - Fold and invert a 32bit checksum. 15 * csum_fold - Fold and invert a 32bit checksum.
16 * sum: 32bit unfolded sum 16 * sum: 32bit unfolded sum
17 * 17 *
18 * Fold a 32bit running checksum to 16bit and invert it. This is usually 18 * Fold a 32bit running checksum to 16bit and invert it. This is usually
19 * the last step before putting a checksum into a packet. 19 * the last step before putting a checksum into a packet.
20 * Make sure not to mix with 64bit checksums. 20 * Make sure not to mix with 64bit checksums.
21 */ 21 */
22static inline __sum16 csum_fold(__wsum sum) 22static inline __sum16 csum_fold(__wsum sum)
23{ 23{
24 __asm__( 24 asm(" addl %1,%0\n"
25 " addl %1,%0\n" 25 " adcl $0xffff,%0"
26 " adcl $0xffff,%0" 26 : "=r" (sum)
27 : "=r" (sum) 27 : "r" ((__force u32)sum << 16),
28 : "r" ((__force u32)sum << 16), 28 "0" ((__force u32)sum & 0xffff0000));
29 "0" ((__force u32)sum & 0xffff0000)
30 );
31 return (__force __sum16)(~(__force u32)sum >> 16); 29 return (__force __sum16)(~(__force u32)sum >> 16);
32} 30}
33 31
@@ -43,46 +41,46 @@ static inline __sum16 csum_fold(__wsum sum)
43 * ip_fast_csum - Compute the IPv4 header checksum efficiently. 41 * ip_fast_csum - Compute the IPv4 header checksum efficiently.
44 * iph: ipv4 header 42 * iph: ipv4 header
45 * ihl: length of header / 4 43 * ihl: length of header / 4
46 */ 44 */
47static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) 45static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
48{ 46{
49 unsigned int sum; 47 unsigned int sum;
50 48
51 asm( " movl (%1), %0\n" 49 asm(" movl (%1), %0\n"
52 " subl $4, %2\n" 50 " subl $4, %2\n"
53 " jbe 2f\n" 51 " jbe 2f\n"
54 " addl 4(%1), %0\n" 52 " addl 4(%1), %0\n"
55 " adcl 8(%1), %0\n" 53 " adcl 8(%1), %0\n"
56 " adcl 12(%1), %0\n" 54 " adcl 12(%1), %0\n"
57 "1: adcl 16(%1), %0\n" 55 "1: adcl 16(%1), %0\n"
58 " lea 4(%1), %1\n" 56 " lea 4(%1), %1\n"
59 " decl %2\n" 57 " decl %2\n"
60 " jne 1b\n" 58 " jne 1b\n"
61 " adcl $0, %0\n" 59 " adcl $0, %0\n"
62 " movl %0, %2\n" 60 " movl %0, %2\n"
63 " shrl $16, %0\n" 61 " shrl $16, %0\n"
64 " addw %w2, %w0\n" 62 " addw %w2, %w0\n"
65 " adcl $0, %0\n" 63 " adcl $0, %0\n"
66 " notl %0\n" 64 " notl %0\n"
67 "2:" 65 "2:"
68 /* Since the input registers which are loaded with iph and ihl 66 /* Since the input registers which are loaded with iph and ihl
69 are modified, we must also specify them as outputs, or gcc 67 are modified, we must also specify them as outputs, or gcc
70 will assume they contain their original values. */ 68 will assume they contain their original values. */
71 : "=r" (sum), "=r" (iph), "=r" (ihl) 69 : "=r" (sum), "=r" (iph), "=r" (ihl)
72 : "1" (iph), "2" (ihl) 70 : "1" (iph), "2" (ihl)
73 : "memory"); 71 : "memory");
74 return (__force __sum16)sum; 72 return (__force __sum16)sum;
75} 73}
76 74
77/** 75/**
78 * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum. 76 * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
79 * @saddr: source address 77 * @saddr: source address
80 * @daddr: destination address 78 * @daddr: destination address
81 * @len: length of packet 79 * @len: length of packet
82 * @proto: ip protocol of packet 80 * @proto: ip protocol of packet
83 * @sum: initial sum to be added in (32bit unfolded) 81 * @sum: initial sum to be added in (32bit unfolded)
84 * 82 *
85 * Returns the pseudo header checksum the input data. Result is 83 * Returns the pseudo header checksum the input data. Result is
86 * 32bit unfolded. 84 * 32bit unfolded.
87 */ 85 */
88static inline __wsum 86static inline __wsum
@@ -93,32 +91,32 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
93 " adcl %2, %0\n" 91 " adcl %2, %0\n"
94 " adcl %3, %0\n" 92 " adcl %3, %0\n"
95 " adcl $0, %0\n" 93 " adcl $0, %0\n"
96 : "=r" (sum) 94 : "=r" (sum)
97 : "g" (daddr), "g" (saddr), 95 : "g" (daddr), "g" (saddr),
98 "g" ((len + proto)<<8), "0" (sum)); 96 "g" ((len + proto)<<8), "0" (sum));
99 return sum; 97 return sum;
100} 98}
101 99
102 100
103/** 101/**
104 * csum_tcpup_magic - Compute an IPv4 pseudo header checksum. 102 * csum_tcpup_magic - Compute an IPv4 pseudo header checksum.
105 * @saddr: source address 103 * @saddr: source address
106 * @daddr: destination address 104 * @daddr: destination address
107 * @len: length of packet 105 * @len: length of packet
108 * @proto: ip protocol of packet 106 * @proto: ip protocol of packet
109 * @sum: initial sum to be added in (32bit unfolded) 107 * @sum: initial sum to be added in (32bit unfolded)
110 * 108 *
111 * Returns the 16bit pseudo header checksum the input data already 109 * Returns the 16bit pseudo header checksum the input data already
112 * complemented and ready to be filled in. 110 * complemented and ready to be filled in.
113 */ 111 */
114static inline __sum16 112static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
115csum_tcpudp_magic(__be32 saddr, __be32 daddr, 113 unsigned short len,
116 unsigned short len, unsigned short proto, __wsum sum) 114 unsigned short proto, __wsum sum)
117{ 115{
118 return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); 116 return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
119} 117}
120 118
121/** 119/**
122 * csum_partial - Compute an internet checksum. 120 * csum_partial - Compute an internet checksum.
123 * @buff: buffer to be checksummed 121 * @buff: buffer to be checksummed
124 * @len: length of buffer. 122 * @len: length of buffer.
@@ -127,7 +125,7 @@ csum_tcpudp_magic(__be32 saddr, __be32 daddr,
127 * Returns the 32bit unfolded internet checksum of the buffer. 125 * Returns the 32bit unfolded internet checksum of the buffer.
128 * Before filling it in it needs to be csum_fold()'ed. 126 * Before filling it in it needs to be csum_fold()'ed.
129 * buff should be aligned to a 64bit boundary if possible. 127 * buff should be aligned to a 64bit boundary if possible.
130 */ 128 */
131extern __wsum csum_partial(const void *buff, int len, __wsum sum); 129extern __wsum csum_partial(const void *buff, int len, __wsum sum);
132 130
133#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1 131#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
@@ -136,23 +134,22 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
136 134
137/* Do not call this directly. Use the wrappers below */ 135/* Do not call this directly. Use the wrappers below */
138extern __wsum csum_partial_copy_generic(const void *src, const void *dst, 136extern __wsum csum_partial_copy_generic(const void *src, const void *dst,
139 int len, 137 int len, __wsum sum,
140 __wsum sum, 138 int *src_err_ptr, int *dst_err_ptr);
141 int *src_err_ptr, int *dst_err_ptr);
142 139
143 140
144extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, 141extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
145 int len, __wsum isum, int *errp); 142 int len, __wsum isum, int *errp);
146extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst, 143extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst,
147 int len, __wsum isum, int *errp); 144 int len, __wsum isum, int *errp);
148extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, 145extern __wsum csum_partial_copy_nocheck(const void *src, void *dst,
149 __wsum sum); 146 int len, __wsum sum);
150 147
151/* Old names. To be removed. */ 148/* Old names. To be removed. */
152#define csum_and_copy_to_user csum_partial_copy_to_user 149#define csum_and_copy_to_user csum_partial_copy_to_user
153#define csum_and_copy_from_user csum_partial_copy_from_user 150#define csum_and_copy_from_user csum_partial_copy_from_user
154 151
155/** 152/**
156 * ip_compute_csum - Compute an 16bit IP checksum. 153 * ip_compute_csum - Compute an 16bit IP checksum.
157 * @buff: buffer address. 154 * @buff: buffer address.
158 * @len: length of buffer. 155 * @len: length of buffer.
@@ -170,7 +167,7 @@ extern __sum16 ip_compute_csum(const void *buff, int len);
170 * @proto: protocol of packet 167 * @proto: protocol of packet
171 * @sum: initial sum (32bit unfolded) to be added in 168 * @sum: initial sum (32bit unfolded) to be added in
172 * 169 *
173 * Computes an IPv6 pseudo header checksum. This sum is added the checksum 170 * Computes an IPv6 pseudo header checksum. This sum is added the checksum
174 * into UDP/TCP packets and contains some link layer information. 171 * into UDP/TCP packets and contains some link layer information.
175 * Returns the unfolded 32bit checksum. 172 * Returns the unfolded 32bit checksum.
176 */ 173 */
@@ -185,11 +182,10 @@ csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr,
185static inline unsigned add32_with_carry(unsigned a, unsigned b) 182static inline unsigned add32_with_carry(unsigned a, unsigned b)
186{ 183{
187 asm("addl %2,%0\n\t" 184 asm("addl %2,%0\n\t"
188 "adcl $0,%0" 185 "adcl $0,%0"
189 : "=r" (a) 186 : "=r" (a)
190 : "0" (a), "r" (b)); 187 : "0" (a), "r" (b));
191 return a; 188 return a;
192} 189}
193 190
194#endif 191#endif
195