diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/include/sysdep-x86_64/checksum.h |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/um/include/sysdep-x86_64/checksum.h')
-rw-r--r-- | arch/um/include/sysdep-x86_64/checksum.h | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h new file mode 100644 index 000000000000..572c6c19be33 --- /dev/null +++ b/arch/um/include/sysdep-x86_64/checksum.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * Licensed under the GPL | ||
3 | */ | ||
4 | |||
5 | #ifndef __UM_SYSDEP_CHECKSUM_H | ||
6 | #define __UM_SYSDEP_CHECKSUM_H | ||
7 | |||
8 | #include "linux/string.h" | ||
9 | #include "linux/in6.h" | ||
10 | #include "asm/uaccess.h" | ||
11 | |||
12 | extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len, | ||
13 | int sum, int *err_ptr); | ||
14 | extern unsigned csum_partial(const unsigned char *buff, unsigned len, | ||
15 | unsigned sum); | ||
16 | |||
17 | /* | ||
18 | * Note: when you get a NULL pointer exception here this means someone | ||
19 | * passed in an incorrect kernel address to one of these functions. | ||
20 | * | ||
21 | * If you use these functions directly please don't forget the | ||
22 | * access_ok(). | ||
23 | */ | ||
24 | |||
25 | static __inline__ | ||
26 | unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, | ||
27 | int len, int sum) | ||
28 | { | ||
29 | memcpy(dst, src, len); | ||
30 | return(csum_partial(dst, len, sum)); | ||
31 | } | ||
32 | |||
33 | static __inline__ | ||
34 | unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, | ||
35 | int len, int sum, int *err_ptr) | ||
36 | { | ||
37 | return csum_partial_copy_from(src, dst, len, sum, err_ptr); | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * csum_fold - Fold and invert a 32bit checksum. | ||
42 | * sum: 32bit unfolded sum | ||
43 | * | ||
44 | * Fold a 32bit running checksum to 16bit and invert it. This is usually | ||
45 | * the last step before putting a checksum into a packet. | ||
46 | * Make sure not to mix with 64bit checksums. | ||
47 | */ | ||
48 | static inline unsigned int csum_fold(unsigned int sum) | ||
49 | { | ||
50 | __asm__( | ||
51 | " addl %1,%0\n" | ||
52 | " adcl $0xffff,%0" | ||
53 | : "=r" (sum) | ||
54 | : "r" (sum << 16), "0" (sum & 0xffff0000) | ||
55 | ); | ||
56 | return (~sum) >> 16; | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum. | ||
61 | * @saddr: source address | ||
62 | * @daddr: destination address | ||
63 | * @len: length of packet | ||
64 | * @proto: ip protocol of packet | ||
65 | * @sum: initial sum to be added in (32bit unfolded) | ||
66 | * | ||
67 | * Returns the pseudo header checksum the input data. Result is | ||
68 | * 32bit unfolded. | ||
69 | */ | ||
70 | static inline unsigned long | ||
71 | csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len, | ||
72 | unsigned short proto, unsigned int sum) | ||
73 | { | ||
74 | asm(" addl %1, %0\n" | ||
75 | " adcl %2, %0\n" | ||
76 | " adcl %3, %0\n" | ||
77 | " adcl $0, %0\n" | ||
78 | : "=r" (sum) | ||
79 | : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum)); | ||
80 | return sum; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * computes the checksum of the TCP/UDP pseudo-header | ||
85 | * returns a 16-bit checksum, already complemented | ||
86 | */ | ||
87 | static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, | ||
88 | unsigned long daddr, | ||
89 | unsigned short len, | ||
90 | unsigned short proto, | ||
91 | unsigned int sum) | ||
92 | { | ||
93 | return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * ip_fast_csum - Compute the IPv4 header checksum efficiently. | ||
98 | * iph: ipv4 header | ||
99 | * ihl: length of header / 4 | ||
100 | */ | ||
101 | static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) | ||
102 | { | ||
103 | unsigned int sum; | ||
104 | |||
105 | asm( " movl (%1), %0\n" | ||
106 | " subl $4, %2\n" | ||
107 | " jbe 2f\n" | ||
108 | " addl 4(%1), %0\n" | ||
109 | " adcl 8(%1), %0\n" | ||
110 | " adcl 12(%1), %0\n" | ||
111 | "1: adcl 16(%1), %0\n" | ||
112 | " lea 4(%1), %1\n" | ||
113 | " decl %2\n" | ||
114 | " jne 1b\n" | ||
115 | " adcl $0, %0\n" | ||
116 | " movl %0, %2\n" | ||
117 | " shrl $16, %0\n" | ||
118 | " addw %w2, %w0\n" | ||
119 | " adcl $0, %0\n" | ||
120 | " notl %0\n" | ||
121 | "2:" | ||
122 | /* Since the input registers which are loaded with iph and ipl | ||
123 | are modified, we must also specify them as outputs, or gcc | ||
124 | will assume they contain their original values. */ | ||
125 | : "=r" (sum), "=r" (iph), "=r" (ihl) | ||
126 | : "1" (iph), "2" (ihl) | ||
127 | : "memory"); | ||
128 | return(sum); | ||
129 | } | ||
130 | |||
131 | static inline unsigned add32_with_carry(unsigned a, unsigned b) | ||
132 | { | ||
133 | asm("addl %2,%0\n\t" | ||
134 | "adcl $0,%0" | ||
135 | : "=r" (a) | ||
136 | : "0" (a), "r" (b)); | ||
137 | return a; | ||
138 | } | ||
139 | |||
140 | #endif | ||
141 | |||
142 | /* | ||
143 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
144 | * Emacs will notice this stuff at the end of the file and automatically | ||
145 | * adjust the settings for this buffer only. This must remain at the end | ||
146 | * of the file. | ||
147 | * --------------------------------------------------------------------------- | ||
148 | * Local variables: | ||
149 | * c-file-style: "linux" | ||
150 | * End: | ||
151 | */ | ||