diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2012-03-23 18:02:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 19:58:38 -0400 |
commit | 46c5801eaf86e83cb3a4142ad35188db5011fff0 (patch) | |
tree | 2b8a8f7709aa7dadafdf13f823488cf51e2e2fed /lib | |
parent | 78dff4189708d07cdcaf7bfd1b04ebe78ac9c041 (diff) |
crc32: bolt on crc32c
Reuse the existing crc32 code to stamp out a crc32c implementation.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Bob Pearson <rpearson@systemfabricworks.com>
Cc: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 8 | ||||
-rw-r--r-- | lib/crc32.c | 79 | ||||
-rw-r--r-- | lib/crc32defs.h | 7 | ||||
-rw-r--r-- | lib/gen_crc32table.c | 35 |
4 files changed, 95 insertions, 34 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index d5a86aa441ac..6d7ce4b138c4 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -61,14 +61,14 @@ config CRC_ITU_T | |||
61 | functions require M here. | 61 | functions require M here. |
62 | 62 | ||
63 | config CRC32 | 63 | config CRC32 |
64 | tristate "CRC32 functions" | 64 | tristate "CRC32/CRC32c functions" |
65 | default y | 65 | default y |
66 | select BITREVERSE | 66 | select BITREVERSE |
67 | help | 67 | help |
68 | This option is provided for the case where no in-kernel-tree | 68 | This option is provided for the case where no in-kernel-tree |
69 | modules require CRC32 functions, but a module built outside the | 69 | modules require CRC32/CRC32c functions, but a module built outside |
70 | kernel tree does. Such modules that use library CRC32 functions | 70 | the kernel tree does. Such modules that use library CRC32/CRC32c |
71 | require M here. | 71 | functions require M here. |
72 | 72 | ||
73 | config CRC32_SELFTEST | 73 | config CRC32_SELFTEST |
74 | bool "CRC32 perform self test on init" | 74 | bool "CRC32 perform self test on init" |
diff --git a/lib/crc32.c b/lib/crc32.c index a1a5145a93ba..87678dd1141e 100644 --- a/lib/crc32.c +++ b/lib/crc32.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include "crc32table.h" | 46 | #include "crc32table.h" |
47 | 47 | ||
48 | MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>"); | 48 | MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>"); |
49 | MODULE_DESCRIPTION("Ethernet CRC32 calculations"); | 49 | MODULE_DESCRIPTION("Various CRC32 calculations"); |
50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
51 | 51 | ||
52 | #if CRC_LE_BITS > 8 || CRC_BE_BITS > 8 | 52 | #if CRC_LE_BITS > 8 || CRC_BE_BITS > 8 |
@@ -135,45 +135,66 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256]) | |||
135 | * @p: pointer to buffer over which CRC is run | 135 | * @p: pointer to buffer over which CRC is run |
136 | * @len: length of buffer @p | 136 | * @len: length of buffer @p |
137 | */ | 137 | */ |
138 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | 138 | static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p, |
139 | size_t len, const u32 (*tab)[256], | ||
140 | u32 polynomial) | ||
139 | { | 141 | { |
140 | #if CRC_LE_BITS == 1 | 142 | #if CRC_LE_BITS == 1 |
141 | int i; | 143 | int i; |
142 | while (len--) { | 144 | while (len--) { |
143 | crc ^= *p++; | 145 | crc ^= *p++; |
144 | for (i = 0; i < 8; i++) | 146 | for (i = 0; i < 8; i++) |
145 | crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); | 147 | crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0); |
146 | } | 148 | } |
147 | # elif CRC_LE_BITS == 2 | 149 | # elif CRC_LE_BITS == 2 |
148 | while (len--) { | 150 | while (len--) { |
149 | crc ^= *p++; | 151 | crc ^= *p++; |
150 | crc = (crc >> 2) ^ crc32table_le[0][crc & 3]; | 152 | crc = (crc >> 2) ^ tab[0][crc & 3]; |
151 | crc = (crc >> 2) ^ crc32table_le[0][crc & 3]; | 153 | crc = (crc >> 2) ^ tab[0][crc & 3]; |
152 | crc = (crc >> 2) ^ crc32table_le[0][crc & 3]; | 154 | crc = (crc >> 2) ^ tab[0][crc & 3]; |
153 | crc = (crc >> 2) ^ crc32table_le[0][crc & 3]; | 155 | crc = (crc >> 2) ^ tab[0][crc & 3]; |
154 | } | 156 | } |
155 | # elif CRC_LE_BITS == 4 | 157 | # elif CRC_LE_BITS == 4 |
156 | while (len--) { | 158 | while (len--) { |
157 | crc ^= *p++; | 159 | crc ^= *p++; |
158 | crc = (crc >> 4) ^ crc32table_le[0][crc & 15]; | 160 | crc = (crc >> 4) ^ tab[0][crc & 15]; |
159 | crc = (crc >> 4) ^ crc32table_le[0][crc & 15]; | 161 | crc = (crc >> 4) ^ tab[0][crc & 15]; |
160 | } | 162 | } |
161 | # elif CRC_LE_BITS == 8 | 163 | # elif CRC_LE_BITS == 8 |
162 | /* aka Sarwate algorithm */ | 164 | /* aka Sarwate algorithm */ |
163 | while (len--) { | 165 | while (len--) { |
164 | crc ^= *p++; | 166 | crc ^= *p++; |
165 | crc = (crc >> 8) ^ crc32table_le[0][crc & 255]; | 167 | crc = (crc >> 8) ^ tab[0][crc & 255]; |
166 | } | 168 | } |
167 | # else | 169 | # else |
168 | const u32 (*tab)[] = crc32table_le; | ||
169 | |||
170 | crc = (__force u32) __cpu_to_le32(crc); | 170 | crc = (__force u32) __cpu_to_le32(crc); |
171 | crc = crc32_body(crc, p, len, tab); | 171 | crc = crc32_body(crc, p, len, tab); |
172 | crc = __le32_to_cpu((__force __le32)crc); | 172 | crc = __le32_to_cpu((__force __le32)crc); |
173 | #endif | 173 | #endif |
174 | return crc; | 174 | return crc; |
175 | } | 175 | } |
176 | |||
177 | #if CRC_LE_BITS == 1 | ||
178 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | ||
179 | { | ||
180 | return crc32_le_generic(crc, p, len, NULL, CRCPOLY_LE); | ||
181 | } | ||
182 | u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len) | ||
183 | { | ||
184 | return crc32_le_generic(crc, p, len, NULL, CRC32C_POLY_LE); | ||
185 | } | ||
186 | #else | ||
187 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | ||
188 | { | ||
189 | return crc32_le_generic(crc, p, len, crc32table_le, CRCPOLY_LE); | ||
190 | } | ||
191 | u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len) | ||
192 | { | ||
193 | return crc32_le_generic(crc, p, len, crc32ctable_le, CRC32C_POLY_LE); | ||
194 | } | ||
195 | #endif | ||
176 | EXPORT_SYMBOL(crc32_le); | 196 | EXPORT_SYMBOL(crc32_le); |
197 | EXPORT_SYMBOL(__crc32c_le); | ||
177 | 198 | ||
178 | /** | 199 | /** |
179 | * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32 | 200 | * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32 |
@@ -182,7 +203,9 @@ EXPORT_SYMBOL(crc32_le); | |||
182 | * @p: pointer to buffer over which CRC is run | 203 | * @p: pointer to buffer over which CRC is run |
183 | * @len: length of buffer @p | 204 | * @len: length of buffer @p |
184 | */ | 205 | */ |
185 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | 206 | static inline u32 __pure crc32_be_generic(u32 crc, unsigned char const *p, |
207 | size_t len, const u32 (*tab)[256], | ||
208 | u32 polynomial) | ||
186 | { | 209 | { |
187 | #if CRC_BE_BITS == 1 | 210 | #if CRC_BE_BITS == 1 |
188 | int i; | 211 | int i; |
@@ -190,37 +213,47 @@ u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | |||
190 | crc ^= *p++ << 24; | 213 | crc ^= *p++ << 24; |
191 | for (i = 0; i < 8; i++) | 214 | for (i = 0; i < 8; i++) |
192 | crc = | 215 | crc = |
193 | (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : | 216 | (crc << 1) ^ ((crc & 0x80000000) ? polynomial : |
194 | 0); | 217 | 0); |
195 | } | 218 | } |
196 | # elif CRC_BE_BITS == 2 | 219 | # elif CRC_BE_BITS == 2 |
197 | while (len--) { | 220 | while (len--) { |
198 | crc ^= *p++ << 24; | 221 | crc ^= *p++ << 24; |
199 | crc = (crc << 2) ^ crc32table_be[0][crc >> 30]; | 222 | crc = (crc << 2) ^ tab[0][crc >> 30]; |
200 | crc = (crc << 2) ^ crc32table_be[0][crc >> 30]; | 223 | crc = (crc << 2) ^ tab[0][crc >> 30]; |
201 | crc = (crc << 2) ^ crc32table_be[0][crc >> 30]; | 224 | crc = (crc << 2) ^ tab[0][crc >> 30]; |
202 | crc = (crc << 2) ^ crc32table_be[0][crc >> 30]; | 225 | crc = (crc << 2) ^ tab[0][crc >> 30]; |
203 | } | 226 | } |
204 | # elif CRC_BE_BITS == 4 | 227 | # elif CRC_BE_BITS == 4 |
205 | while (len--) { | 228 | while (len--) { |
206 | crc ^= *p++ << 24; | 229 | crc ^= *p++ << 24; |
207 | crc = (crc << 4) ^ crc32table_be[0][crc >> 28]; | 230 | crc = (crc << 4) ^ tab[0][crc >> 28]; |
208 | crc = (crc << 4) ^ crc32table_be[0][crc >> 28]; | 231 | crc = (crc << 4) ^ tab[0][crc >> 28]; |
209 | } | 232 | } |
210 | # elif CRC_BE_BITS == 8 | 233 | # elif CRC_BE_BITS == 8 |
211 | while (len--) { | 234 | while (len--) { |
212 | crc ^= *p++ << 24; | 235 | crc ^= *p++ << 24; |
213 | crc = (crc << 8) ^ crc32table_be[0][crc >> 24]; | 236 | crc = (crc << 8) ^ tab[0][crc >> 24]; |
214 | } | 237 | } |
215 | # else | 238 | # else |
216 | const u32 (*tab)[] = crc32table_be; | ||
217 | |||
218 | crc = (__force u32) __cpu_to_be32(crc); | 239 | crc = (__force u32) __cpu_to_be32(crc); |
219 | crc = crc32_body(crc, p, len, tab); | 240 | crc = crc32_body(crc, p, len, tab); |
220 | crc = __be32_to_cpu((__force __be32)crc); | 241 | crc = __be32_to_cpu((__force __be32)crc); |
221 | # endif | 242 | # endif |
222 | return crc; | 243 | return crc; |
223 | } | 244 | } |
245 | |||
246 | #if CRC_LE_BITS == 1 | ||
247 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | ||
248 | { | ||
249 | return crc32_be_generic(crc, p, len, NULL, CRCPOLY_BE); | ||
250 | } | ||
251 | #else | ||
252 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | ||
253 | { | ||
254 | return crc32_be_generic(crc, p, len, crc32table_be, CRCPOLY_BE); | ||
255 | } | ||
256 | #endif | ||
224 | EXPORT_SYMBOL(crc32_be); | 257 | EXPORT_SYMBOL(crc32_be); |
225 | 258 | ||
226 | #ifdef CONFIG_CRC32_SELFTEST | 259 | #ifdef CONFIG_CRC32_SELFTEST |
diff --git a/lib/crc32defs.h b/lib/crc32defs.h index 818159288489..6fd191732fec 100644 --- a/lib/crc32defs.h +++ b/lib/crc32defs.h | |||
@@ -7,6 +7,13 @@ | |||
7 | #define CRCPOLY_BE 0x04c11db7 | 7 | #define CRCPOLY_BE 0x04c11db7 |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * This is the CRC32c polynomial, as outlined by Castagnoli. | ||
11 | * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+ | ||
12 | * x^8+x^6+x^0 | ||
13 | */ | ||
14 | #define CRC32C_POLY_LE 0x82F63B78 | ||
15 | |||
16 | /* | ||
10 | * How many bits at a time to use. Valid values are 1, 2, 4, 8, 32 and 64. | 17 | * How many bits at a time to use. Valid values are 1, 2, 4, 8, 32 and 64. |
11 | * For less performance-sensitive, use 4 or 8 to save table size. | 18 | * For less performance-sensitive, use 4 or 8 to save table size. |
12 | * For larger systems choose same as CPU architecture as default. | 19 | * For larger systems choose same as CPU architecture as default. |
diff --git a/lib/gen_crc32table.c b/lib/gen_crc32table.c index 0d9edd17ee13..8f8d5439e2d9 100644 --- a/lib/gen_crc32table.c +++ b/lib/gen_crc32table.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | static uint32_t crc32table_le[LE_TABLE_ROWS][256]; | 24 | static uint32_t crc32table_le[LE_TABLE_ROWS][256]; |
25 | static uint32_t crc32table_be[BE_TABLE_ROWS][256]; | 25 | static uint32_t crc32table_be[BE_TABLE_ROWS][256]; |
26 | static uint32_t crc32ctable_le[LE_TABLE_ROWS][256]; | ||
26 | 27 | ||
27 | /** | 28 | /** |
28 | * crc32init_le() - allocate and initialize LE table data | 29 | * crc32init_le() - allocate and initialize LE table data |
@@ -31,27 +32,38 @@ static uint32_t crc32table_be[BE_TABLE_ROWS][256]; | |||
31 | * fact that crctable[i^j] = crctable[i] ^ crctable[j]. | 32 | * fact that crctable[i^j] = crctable[i] ^ crctable[j]. |
32 | * | 33 | * |
33 | */ | 34 | */ |
34 | static void crc32init_le(void) | 35 | static void crc32init_le_generic(const uint32_t polynomial, |
36 | uint32_t (*tab)[256]) | ||
35 | { | 37 | { |
36 | unsigned i, j; | 38 | unsigned i, j; |
37 | uint32_t crc = 1; | 39 | uint32_t crc = 1; |
38 | 40 | ||
39 | crc32table_le[0][0] = 0; | 41 | tab[0][0] = 0; |
40 | 42 | ||
41 | for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) { | 43 | for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) { |
42 | crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); | 44 | crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0); |
43 | for (j = 0; j < LE_TABLE_SIZE; j += 2 * i) | 45 | for (j = 0; j < LE_TABLE_SIZE; j += 2 * i) |
44 | crc32table_le[0][i + j] = crc ^ crc32table_le[0][j]; | 46 | tab[0][i + j] = crc ^ tab[0][j]; |
45 | } | 47 | } |
46 | for (i = 0; i < LE_TABLE_SIZE; i++) { | 48 | for (i = 0; i < LE_TABLE_SIZE; i++) { |
47 | crc = crc32table_le[0][i]; | 49 | crc = tab[0][i]; |
48 | for (j = 1; j < LE_TABLE_ROWS; j++) { | 50 | for (j = 1; j < LE_TABLE_ROWS; j++) { |
49 | crc = crc32table_le[0][crc & 0xff] ^ (crc >> 8); | 51 | crc = tab[0][crc & 0xff] ^ (crc >> 8); |
50 | crc32table_le[j][i] = crc; | 52 | tab[j][i] = crc; |
51 | } | 53 | } |
52 | } | 54 | } |
53 | } | 55 | } |
54 | 56 | ||
57 | static void crc32init_le(void) | ||
58 | { | ||
59 | crc32init_le_generic(CRCPOLY_LE, crc32table_le); | ||
60 | } | ||
61 | |||
62 | static void crc32cinit_le(void) | ||
63 | { | ||
64 | crc32init_le_generic(CRC32C_POLY_LE, crc32ctable_le); | ||
65 | } | ||
66 | |||
55 | /** | 67 | /** |
56 | * crc32init_be() - allocate and initialize BE table data | 68 | * crc32init_be() - allocate and initialize BE table data |
57 | */ | 69 | */ |
@@ -114,6 +126,15 @@ int main(int argc, char** argv) | |||
114 | BE_TABLE_SIZE, "tobe"); | 126 | BE_TABLE_SIZE, "tobe"); |
115 | printf("};\n"); | 127 | printf("};\n"); |
116 | } | 128 | } |
129 | if (CRC_LE_BITS > 1) { | ||
130 | crc32cinit_le(); | ||
131 | printf("static const u32 __cacheline_aligned " | ||
132 | "crc32ctable_le[%d][%d] = {", | ||
133 | LE_TABLE_ROWS, LE_TABLE_SIZE); | ||
134 | output_table(crc32ctable_le, LE_TABLE_ROWS, | ||
135 | LE_TABLE_SIZE, "tole"); | ||
136 | printf("};\n"); | ||
137 | } | ||
117 | 138 | ||
118 | return 0; | 139 | return 0; |
119 | } | 140 | } |