diff options
Diffstat (limited to 'lib/crc32.c')
-rw-r--r-- | lib/crc32.c | 121 |
1 files changed, 44 insertions, 77 deletions
diff --git a/lib/crc32.c b/lib/crc32.c index 49d1c9e3ce38..02e3b31b3a79 100644 --- a/lib/crc32.c +++ b/lib/crc32.c | |||
@@ -42,6 +42,48 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>"); | |||
42 | MODULE_DESCRIPTION("Ethernet CRC32 calculations"); | 42 | MODULE_DESCRIPTION("Ethernet CRC32 calculations"); |
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
45 | #if CRC_LE_BITS == 8 || CRC_BE_BITS == 8 | ||
46 | |||
47 | static inline u32 | ||
48 | crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 *tab) | ||
49 | { | ||
50 | # ifdef __LITTLE_ENDIAN | ||
51 | # define DO_CRC(x) crc = tab[(crc ^ (x)) & 255 ] ^ (crc >> 8) | ||
52 | # else | ||
53 | # define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8) | ||
54 | # endif | ||
55 | const u32 *b = (const u32 *)buf; | ||
56 | size_t rem_len; | ||
57 | |||
58 | /* Align it */ | ||
59 | if (unlikely((long)b & 3 && len)) { | ||
60 | u8 *p = (u8 *)b; | ||
61 | do { | ||
62 | DO_CRC(*p++); | ||
63 | } while ((--len) && ((long)p)&3); | ||
64 | b = (u32 *)p; | ||
65 | } | ||
66 | rem_len = len & 3; | ||
67 | /* load data 32 bits wide, xor data 32 bits wide. */ | ||
68 | len = len >> 2; | ||
69 | for (--b; len; --len) { | ||
70 | crc ^= *++b; /* use pre increment for speed */ | ||
71 | DO_CRC(0); | ||
72 | DO_CRC(0); | ||
73 | DO_CRC(0); | ||
74 | DO_CRC(0); | ||
75 | } | ||
76 | len = rem_len; | ||
77 | /* And the last few bytes */ | ||
78 | if (len) { | ||
79 | u8 *p = (u8 *)(b + 1) - 1; | ||
80 | do { | ||
81 | DO_CRC(*++p); /* use pre increment for speed */ | ||
82 | } while (--len); | ||
83 | } | ||
84 | return crc; | ||
85 | } | ||
86 | #endif | ||
45 | /** | 87 | /** |
46 | * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 | 88 | * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 |
47 | * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for | 89 | * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for |
@@ -72,48 +114,10 @@ u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | |||
72 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) | 114 | u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) |
73 | { | 115 | { |
74 | # if CRC_LE_BITS == 8 | 116 | # if CRC_LE_BITS == 8 |
75 | const u32 *b =(u32 *)p; | ||
76 | const u32 *tab = crc32table_le; | 117 | const u32 *tab = crc32table_le; |
77 | 118 | ||
78 | # ifdef __LITTLE_ENDIAN | ||
79 | # define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) | ||
80 | # else | ||
81 | # define DO_CRC(x) crc = tab[ ((crc >> 24) ^ (x)) & 255] ^ (crc<<8) | ||
82 | # endif | ||
83 | |||
84 | crc = __cpu_to_le32(crc); | 119 | crc = __cpu_to_le32(crc); |
85 | /* Align it */ | 120 | crc = crc32_body(crc, p, len, tab); |
86 | if(unlikely(((long)b)&3 && len)){ | ||
87 | do { | ||
88 | u8 *p = (u8 *)b; | ||
89 | DO_CRC(*p++); | ||
90 | b = (void *)p; | ||
91 | } while ((--len) && ((long)b)&3 ); | ||
92 | } | ||
93 | if(likely(len >= 4)){ | ||
94 | /* load data 32 bits wide, xor data 32 bits wide. */ | ||
95 | size_t save_len = len & 3; | ||
96 | len = len >> 2; | ||
97 | --b; /* use pre increment below(*++b) for speed */ | ||
98 | do { | ||
99 | crc ^= *++b; | ||
100 | DO_CRC(0); | ||
101 | DO_CRC(0); | ||
102 | DO_CRC(0); | ||
103 | DO_CRC(0); | ||
104 | } while (--len); | ||
105 | b++; /* point to next byte(s) */ | ||
106 | len = save_len; | ||
107 | } | ||
108 | /* And the last few bytes */ | ||
109 | if(len){ | ||
110 | do { | ||
111 | u8 *p = (u8 *)b; | ||
112 | DO_CRC(*p++); | ||
113 | b = (void *)p; | ||
114 | } while (--len); | ||
115 | } | ||
116 | |||
117 | return __le32_to_cpu(crc); | 121 | return __le32_to_cpu(crc); |
118 | #undef ENDIAN_SHIFT | 122 | #undef ENDIAN_SHIFT |
119 | #undef DO_CRC | 123 | #undef DO_CRC |
@@ -170,47 +174,10 @@ u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | |||
170 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) | 174 | u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len) |
171 | { | 175 | { |
172 | # if CRC_BE_BITS == 8 | 176 | # if CRC_BE_BITS == 8 |
173 | const u32 *b =(u32 *)p; | ||
174 | const u32 *tab = crc32table_be; | 177 | const u32 *tab = crc32table_be; |
175 | 178 | ||
176 | # ifdef __LITTLE_ENDIAN | ||
177 | # define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) | ||
178 | # else | ||
179 | # define DO_CRC(x) crc = tab[ ((crc >> 24) ^ (x)) & 255] ^ (crc<<8) | ||
180 | # endif | ||
181 | |||
182 | crc = __cpu_to_be32(crc); | 179 | crc = __cpu_to_be32(crc); |
183 | /* Align it */ | 180 | crc = crc32_body(crc, p, len, tab); |
184 | if(unlikely(((long)b)&3 && len)){ | ||
185 | do { | ||
186 | u8 *p = (u8 *)b; | ||
187 | DO_CRC(*p++); | ||
188 | b = (u32 *)p; | ||
189 | } while ((--len) && ((long)b)&3 ); | ||
190 | } | ||
191 | if(likely(len >= 4)){ | ||
192 | /* load data 32 bits wide, xor data 32 bits wide. */ | ||
193 | size_t save_len = len & 3; | ||
194 | len = len >> 2; | ||
195 | --b; /* use pre increment below(*++b) for speed */ | ||
196 | do { | ||
197 | crc ^= *++b; | ||
198 | DO_CRC(0); | ||
199 | DO_CRC(0); | ||
200 | DO_CRC(0); | ||
201 | DO_CRC(0); | ||
202 | } while (--len); | ||
203 | b++; /* point to next byte(s) */ | ||
204 | len = save_len; | ||
205 | } | ||
206 | /* And the last few bytes */ | ||
207 | if(len){ | ||
208 | do { | ||
209 | u8 *p = (u8 *)b; | ||
210 | DO_CRC(*p++); | ||
211 | b = (void *)p; | ||
212 | } while (--len); | ||
213 | } | ||
214 | return __be32_to_cpu(crc); | 181 | return __be32_to_cpu(crc); |
215 | #undef ENDIAN_SHIFT | 182 | #undef ENDIAN_SHIFT |
216 | #undef DO_CRC | 183 | #undef DO_CRC |