diff options
| -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 |
