Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mips/crc32: expose CRC32 functions through lib

Move the mips CRC32 assembly code into the lib directory and wire it up
to the library interface. This allows it to be used without going
through the crypto API. It remains usable via the crypto API too via
the shash algorithms that use the library interface. Thus all the
arch-specific "shash" code becomes unnecessary and is removed.

Note: to see the diff from arch/mips/crypto/crc32-mips.c to
arch/mips/lib/crc32-mips.c, view this commit with 'git show -M10'.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20241202010844.144356-8-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>

+195 -374
+1 -4
arch/mips/Kconfig
··· 1995 1995 config CPU_MIPSR6 1996 1996 bool 1997 1997 default y if CPU_MIPS32_R6 || CPU_MIPS64_R6 1998 + select ARCH_HAS_CRC32 1998 1999 select CPU_HAS_RIXI 1999 2000 select CPU_HAS_DIEI if !CPU_DIEI_BROKEN 2000 2001 select HAVE_ARCH_BITREVERSE 2001 2002 select MIPS_ASID_BITS_VARIABLE 2002 - select MIPS_CRC_SUPPORT 2003 2003 select MIPS_SPRAM 2004 2004 2005 2005 config TARGET_ISA_REV ··· 2473 2473 default 8 2474 2474 2475 2475 config MIPS_ASID_BITS_VARIABLE 2476 - bool 2477 - 2478 - config MIPS_CRC_SUPPORT 2479 2476 bool 2480 2477 2481 2478 # R4600 erratum. Due to the lack of errata information the exact
-1
arch/mips/configs/eyeq5_defconfig
··· 99 99 CONFIG_NFS_V4_1=y 100 100 CONFIG_NFS_V4_2=y 101 101 CONFIG_ROOT_NFS=y 102 - CONFIG_CRYPTO_CRC32_MIPS=y 103 102 CONFIG_FRAME_WARN=1024 104 103 CONFIG_DEBUG_FS=y 105 104 # CONFIG_RCU_TRACE is not set
-1
arch/mips/configs/eyeq6_defconfig
··· 102 102 CONFIG_NFS_V4_1=y 103 103 CONFIG_NFS_V4_2=y 104 104 CONFIG_ROOT_NFS=y 105 - CONFIG_CRYPTO_CRC32_MIPS=y 106 105 CONFIG_FRAME_WARN=1024 107 106 CONFIG_DEBUG_FS=y 108 107 # CONFIG_RCU_TRACE is not set
-2
arch/mips/configs/generic/32r6.config
··· 1 1 CONFIG_CPU_MIPS32_R6=y 2 2 CONFIG_HIGHMEM=y 3 - 4 - CONFIG_CRYPTO_CRC32_MIPS=y
-1
arch/mips/configs/generic/64r6.config
··· 4 4 CONFIG_MIPS32_N32=y 5 5 6 6 CONFIG_CPU_HAS_MSA=y 7 - CONFIG_CRYPTO_CRC32_MIPS=y 8 7 CONFIG_VIRTUALIZATION=y
-9
arch/mips/crypto/Kconfig
··· 2 2 3 3 menu "Accelerated Cryptographic Algorithms for CPU (mips)" 4 4 5 - config CRYPTO_CRC32_MIPS 6 - tristate "CRC32c and CRC32" 7 - depends on MIPS_CRC_SUPPORT 8 - select CRYPTO_HASH 9 - help 10 - CRC32c and CRC32 CRC algorithms 11 - 12 - Architecture: mips 13 - 14 5 config CRYPTO_POLY1305_MIPS 15 6 tristate "Hash functions: Poly1305" 16 7 depends on MIPS
-2
arch/mips/crypto/Makefile
··· 3 3 # Makefile for MIPS crypto files.. 4 4 # 5 5 6 - obj-$(CONFIG_CRYPTO_CRC32_MIPS) += crc32-mips.o 7 - 8 6 obj-$(CONFIG_CRYPTO_CHACHA_MIPS) += chacha-mips.o 9 7 chacha-mips-y := chacha-core.o chacha-glue.o 10 8 AFLAGS_chacha-core.o += -O2 # needed to fill branch delay slots
-354
arch/mips/crypto/crc32-mips.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * crc32-mips.c - CRC32 and CRC32C using optional MIPSr6 instructions 4 - * 5 - * Module based on arm64/crypto/crc32-arm.c 6 - * 7 - * Copyright (C) 2014 Linaro Ltd <yazen.ghannam@linaro.org> 8 - * Copyright (C) 2018 MIPS Tech, LLC 9 - */ 10 - 11 - #include <linux/cpufeature.h> 12 - #include <linux/init.h> 13 - #include <linux/kernel.h> 14 - #include <linux/module.h> 15 - #include <linux/string.h> 16 - #include <asm/mipsregs.h> 17 - #include <linux/unaligned.h> 18 - 19 - #include <crypto/internal/hash.h> 20 - 21 - enum crc_op_size { 22 - b, h, w, d, 23 - }; 24 - 25 - enum crc_type { 26 - crc32, 27 - crc32c, 28 - }; 29 - 30 - #ifndef TOOLCHAIN_SUPPORTS_CRC 31 - #define _ASM_SET_CRC(OP, SZ, TYPE) \ 32 - _ASM_MACRO_3R(OP, rt, rs, rt2, \ 33 - ".ifnc \\rt, \\rt2\n\t" \ 34 - ".error \"invalid operands \\\"" #OP " \\rt,\\rs,\\rt2\\\"\"\n\t" \ 35 - ".endif\n\t" \ 36 - _ASM_INSN_IF_MIPS(0x7c00000f | (__rt << 16) | (__rs << 21) | \ 37 - ((SZ) << 6) | ((TYPE) << 8)) \ 38 - _ASM_INSN32_IF_MM(0x00000030 | (__rs << 16) | (__rt << 21) | \ 39 - ((SZ) << 14) | ((TYPE) << 3))) 40 - #define _ASM_UNSET_CRC(op, SZ, TYPE) ".purgem " #op "\n\t" 41 - #else /* !TOOLCHAIN_SUPPORTS_CRC */ 42 - #define _ASM_SET_CRC(op, SZ, TYPE) ".set\tcrc\n\t" 43 - #define _ASM_UNSET_CRC(op, SZ, TYPE) 44 - #endif 45 - 46 - #define __CRC32(crc, value, op, SZ, TYPE) \ 47 - do { \ 48 - __asm__ __volatile__( \ 49 - ".set push\n\t" \ 50 - _ASM_SET_CRC(op, SZ, TYPE) \ 51 - #op " %0, %1, %0\n\t" \ 52 - _ASM_UNSET_CRC(op, SZ, TYPE) \ 53 - ".set pop" \ 54 - : "+r" (crc) \ 55 - : "r" (value)); \ 56 - } while (0) 57 - 58 - #define _CRC32_crc32b(crc, value) __CRC32(crc, value, crc32b, 0, 0) 59 - #define _CRC32_crc32h(crc, value) __CRC32(crc, value, crc32h, 1, 0) 60 - #define _CRC32_crc32w(crc, value) __CRC32(crc, value, crc32w, 2, 0) 61 - #define _CRC32_crc32d(crc, value) __CRC32(crc, value, crc32d, 3, 0) 62 - #define _CRC32_crc32cb(crc, value) __CRC32(crc, value, crc32cb, 0, 1) 63 - #define _CRC32_crc32ch(crc, value) __CRC32(crc, value, crc32ch, 1, 1) 64 - #define _CRC32_crc32cw(crc, value) __CRC32(crc, value, crc32cw, 2, 1) 65 - #define _CRC32_crc32cd(crc, value) __CRC32(crc, value, crc32cd, 3, 1) 66 - 67 - #define _CRC32(crc, value, size, op) \ 68 - _CRC32_##op##size(crc, value) 69 - 70 - #define CRC32(crc, value, size) \ 71 - _CRC32(crc, value, size, crc32) 72 - 73 - #define CRC32C(crc, value, size) \ 74 - _CRC32(crc, value, size, crc32c) 75 - 76 - static u32 crc32_mips_le_hw(u32 crc_, const u8 *p, unsigned int len) 77 - { 78 - u32 crc = crc_; 79 - 80 - if (IS_ENABLED(CONFIG_64BIT)) { 81 - for (; len >= sizeof(u64); p += sizeof(u64), len -= sizeof(u64)) { 82 - u64 value = get_unaligned_le64(p); 83 - 84 - CRC32(crc, value, d); 85 - } 86 - 87 - if (len & sizeof(u32)) { 88 - u32 value = get_unaligned_le32(p); 89 - 90 - CRC32(crc, value, w); 91 - p += sizeof(u32); 92 - } 93 - } else { 94 - for (; len >= sizeof(u32); len -= sizeof(u32)) { 95 - u32 value = get_unaligned_le32(p); 96 - 97 - CRC32(crc, value, w); 98 - p += sizeof(u32); 99 - } 100 - } 101 - 102 - if (len & sizeof(u16)) { 103 - u16 value = get_unaligned_le16(p); 104 - 105 - CRC32(crc, value, h); 106 - p += sizeof(u16); 107 - } 108 - 109 - if (len & sizeof(u8)) { 110 - u8 value = *p++; 111 - 112 - CRC32(crc, value, b); 113 - } 114 - 115 - return crc; 116 - } 117 - 118 - static u32 crc32c_mips_le_hw(u32 crc_, const u8 *p, unsigned int len) 119 - { 120 - u32 crc = crc_; 121 - 122 - if (IS_ENABLED(CONFIG_64BIT)) { 123 - for (; len >= sizeof(u64); p += sizeof(u64), len -= sizeof(u64)) { 124 - u64 value = get_unaligned_le64(p); 125 - 126 - CRC32C(crc, value, d); 127 - } 128 - 129 - if (len & sizeof(u32)) { 130 - u32 value = get_unaligned_le32(p); 131 - 132 - CRC32C(crc, value, w); 133 - p += sizeof(u32); 134 - } 135 - } else { 136 - for (; len >= sizeof(u32); len -= sizeof(u32)) { 137 - u32 value = get_unaligned_le32(p); 138 - 139 - CRC32C(crc, value, w); 140 - p += sizeof(u32); 141 - } 142 - } 143 - 144 - if (len & sizeof(u16)) { 145 - u16 value = get_unaligned_le16(p); 146 - 147 - CRC32C(crc, value, h); 148 - p += sizeof(u16); 149 - } 150 - 151 - if (len & sizeof(u8)) { 152 - u8 value = *p++; 153 - 154 - CRC32C(crc, value, b); 155 - } 156 - return crc; 157 - } 158 - 159 - #define CHKSUM_BLOCK_SIZE 1 160 - #define CHKSUM_DIGEST_SIZE 4 161 - 162 - struct chksum_ctx { 163 - u32 key; 164 - }; 165 - 166 - struct chksum_desc_ctx { 167 - u32 crc; 168 - }; 169 - 170 - static int chksum_init(struct shash_desc *desc) 171 - { 172 - struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); 173 - struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 174 - 175 - ctx->crc = mctx->key; 176 - 177 - return 0; 178 - } 179 - 180 - /* 181 - * Setting the seed allows arbitrary accumulators and flexible XOR policy 182 - * If your algorithm starts with ~0, then XOR with ~0 before you set 183 - * the seed. 184 - */ 185 - static int chksum_setkey(struct crypto_shash *tfm, const u8 *key, 186 - unsigned int keylen) 187 - { 188 - struct chksum_ctx *mctx = crypto_shash_ctx(tfm); 189 - 190 - if (keylen != sizeof(mctx->key)) 191 - return -EINVAL; 192 - mctx->key = get_unaligned_le32(key); 193 - return 0; 194 - } 195 - 196 - static int chksum_update(struct shash_desc *desc, const u8 *data, 197 - unsigned int length) 198 - { 199 - struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 200 - 201 - ctx->crc = crc32_mips_le_hw(ctx->crc, data, length); 202 - return 0; 203 - } 204 - 205 - static int chksumc_update(struct shash_desc *desc, const u8 *data, 206 - unsigned int length) 207 - { 208 - struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 209 - 210 - ctx->crc = crc32c_mips_le_hw(ctx->crc, data, length); 211 - return 0; 212 - } 213 - 214 - static int chksum_final(struct shash_desc *desc, u8 *out) 215 - { 216 - struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 217 - 218 - put_unaligned_le32(ctx->crc, out); 219 - return 0; 220 - } 221 - 222 - static int chksumc_final(struct shash_desc *desc, u8 *out) 223 - { 224 - struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 225 - 226 - put_unaligned_le32(~ctx->crc, out); 227 - return 0; 228 - } 229 - 230 - static int __chksum_finup(u32 crc, const u8 *data, unsigned int len, u8 *out) 231 - { 232 - put_unaligned_le32(crc32_mips_le_hw(crc, data, len), out); 233 - return 0; 234 - } 235 - 236 - static int __chksumc_finup(u32 crc, const u8 *data, unsigned int len, u8 *out) 237 - { 238 - put_unaligned_le32(~crc32c_mips_le_hw(crc, data, len), out); 239 - return 0; 240 - } 241 - 242 - static int chksum_finup(struct shash_desc *desc, const u8 *data, 243 - unsigned int len, u8 *out) 244 - { 245 - struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 246 - 247 - return __chksum_finup(ctx->crc, data, len, out); 248 - } 249 - 250 - static int chksumc_finup(struct shash_desc *desc, const u8 *data, 251 - unsigned int len, u8 *out) 252 - { 253 - struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); 254 - 255 - return __chksumc_finup(ctx->crc, data, len, out); 256 - } 257 - 258 - static int chksum_digest(struct shash_desc *desc, const u8 *data, 259 - unsigned int length, u8 *out) 260 - { 261 - struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); 262 - 263 - return __chksum_finup(mctx->key, data, length, out); 264 - } 265 - 266 - static int chksumc_digest(struct shash_desc *desc, const u8 *data, 267 - unsigned int length, u8 *out) 268 - { 269 - struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); 270 - 271 - return __chksumc_finup(mctx->key, data, length, out); 272 - } 273 - 274 - static int chksum_cra_init(struct crypto_tfm *tfm) 275 - { 276 - struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 277 - 278 - mctx->key = ~0; 279 - return 0; 280 - } 281 - 282 - static struct shash_alg crc32_alg = { 283 - .digestsize = CHKSUM_DIGEST_SIZE, 284 - .setkey = chksum_setkey, 285 - .init = chksum_init, 286 - .update = chksum_update, 287 - .final = chksum_final, 288 - .finup = chksum_finup, 289 - .digest = chksum_digest, 290 - .descsize = sizeof(struct chksum_desc_ctx), 291 - .base = { 292 - .cra_name = "crc32", 293 - .cra_driver_name = "crc32-mips-hw", 294 - .cra_priority = 300, 295 - .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, 296 - .cra_blocksize = CHKSUM_BLOCK_SIZE, 297 - .cra_ctxsize = sizeof(struct chksum_ctx), 298 - .cra_module = THIS_MODULE, 299 - .cra_init = chksum_cra_init, 300 - } 301 - }; 302 - 303 - static struct shash_alg crc32c_alg = { 304 - .digestsize = CHKSUM_DIGEST_SIZE, 305 - .setkey = chksum_setkey, 306 - .init = chksum_init, 307 - .update = chksumc_update, 308 - .final = chksumc_final, 309 - .finup = chksumc_finup, 310 - .digest = chksumc_digest, 311 - .descsize = sizeof(struct chksum_desc_ctx), 312 - .base = { 313 - .cra_name = "crc32c", 314 - .cra_driver_name = "crc32c-mips-hw", 315 - .cra_priority = 300, 316 - .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, 317 - .cra_blocksize = CHKSUM_BLOCK_SIZE, 318 - .cra_ctxsize = sizeof(struct chksum_ctx), 319 - .cra_module = THIS_MODULE, 320 - .cra_init = chksum_cra_init, 321 - } 322 - }; 323 - 324 - static int __init crc32_mod_init(void) 325 - { 326 - int err; 327 - 328 - err = crypto_register_shash(&crc32_alg); 329 - 330 - if (err) 331 - return err; 332 - 333 - err = crypto_register_shash(&crc32c_alg); 334 - 335 - if (err) { 336 - crypto_unregister_shash(&crc32_alg); 337 - return err; 338 - } 339 - 340 - return 0; 341 - } 342 - 343 - static void __exit crc32_mod_exit(void) 344 - { 345 - crypto_unregister_shash(&crc32_alg); 346 - crypto_unregister_shash(&crc32c_alg); 347 - } 348 - 349 - MODULE_AUTHOR("Marcin Nowakowski <marcin.nowakowski@mips.com"); 350 - MODULE_DESCRIPTION("CRC32 and CRC32C using optional MIPS instructions"); 351 - MODULE_LICENSE("GPL v2"); 352 - 353 - module_cpu_feature_match(MIPS_CRC32, crc32_mod_init); 354 - module_exit(crc32_mod_exit);
+2
arch/mips/lib/Makefile
··· 14 14 obj-$(CONFIG_CPU_GENERIC_DUMP_TLB) += dump_tlb.o 15 15 obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o 16 16 17 + obj-$(CONFIG_CRC32_ARCH) += crc32-mips.o 18 + 17 19 # libgcc-style stuff needed in the kernel 18 20 obj-y += bswapsi.o bswapdi.o multi3.o
+192
arch/mips/lib/crc32-mips.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * crc32-mips.c - CRC32 and CRC32C using optional MIPSr6 instructions 4 + * 5 + * Module based on arm64/crypto/crc32-arm.c 6 + * 7 + * Copyright (C) 2014 Linaro Ltd <yazen.ghannam@linaro.org> 8 + * Copyright (C) 2018 MIPS Tech, LLC 9 + */ 10 + 11 + #include <linux/cpufeature.h> 12 + #include <linux/crc32.h> 13 + #include <linux/init.h> 14 + #include <linux/kernel.h> 15 + #include <linux/module.h> 16 + #include <asm/mipsregs.h> 17 + #include <linux/unaligned.h> 18 + 19 + enum crc_op_size { 20 + b, h, w, d, 21 + }; 22 + 23 + enum crc_type { 24 + crc32, 25 + crc32c, 26 + }; 27 + 28 + #ifndef TOOLCHAIN_SUPPORTS_CRC 29 + #define _ASM_SET_CRC(OP, SZ, TYPE) \ 30 + _ASM_MACRO_3R(OP, rt, rs, rt2, \ 31 + ".ifnc \\rt, \\rt2\n\t" \ 32 + ".error \"invalid operands \\\"" #OP " \\rt,\\rs,\\rt2\\\"\"\n\t" \ 33 + ".endif\n\t" \ 34 + _ASM_INSN_IF_MIPS(0x7c00000f | (__rt << 16) | (__rs << 21) | \ 35 + ((SZ) << 6) | ((TYPE) << 8)) \ 36 + _ASM_INSN32_IF_MM(0x00000030 | (__rs << 16) | (__rt << 21) | \ 37 + ((SZ) << 14) | ((TYPE) << 3))) 38 + #define _ASM_UNSET_CRC(op, SZ, TYPE) ".purgem " #op "\n\t" 39 + #else /* !TOOLCHAIN_SUPPORTS_CRC */ 40 + #define _ASM_SET_CRC(op, SZ, TYPE) ".set\tcrc\n\t" 41 + #define _ASM_UNSET_CRC(op, SZ, TYPE) 42 + #endif 43 + 44 + #define __CRC32(crc, value, op, SZ, TYPE) \ 45 + do { \ 46 + __asm__ __volatile__( \ 47 + ".set push\n\t" \ 48 + _ASM_SET_CRC(op, SZ, TYPE) \ 49 + #op " %0, %1, %0\n\t" \ 50 + _ASM_UNSET_CRC(op, SZ, TYPE) \ 51 + ".set pop" \ 52 + : "+r" (crc) \ 53 + : "r" (value)); \ 54 + } while (0) 55 + 56 + #define _CRC32_crc32b(crc, value) __CRC32(crc, value, crc32b, 0, 0) 57 + #define _CRC32_crc32h(crc, value) __CRC32(crc, value, crc32h, 1, 0) 58 + #define _CRC32_crc32w(crc, value) __CRC32(crc, value, crc32w, 2, 0) 59 + #define _CRC32_crc32d(crc, value) __CRC32(crc, value, crc32d, 3, 0) 60 + #define _CRC32_crc32cb(crc, value) __CRC32(crc, value, crc32cb, 0, 1) 61 + #define _CRC32_crc32ch(crc, value) __CRC32(crc, value, crc32ch, 1, 1) 62 + #define _CRC32_crc32cw(crc, value) __CRC32(crc, value, crc32cw, 2, 1) 63 + #define _CRC32_crc32cd(crc, value) __CRC32(crc, value, crc32cd, 3, 1) 64 + 65 + #define _CRC32(crc, value, size, op) \ 66 + _CRC32_##op##size(crc, value) 67 + 68 + #define CRC32(crc, value, size) \ 69 + _CRC32(crc, value, size, crc32) 70 + 71 + #define CRC32C(crc, value, size) \ 72 + _CRC32(crc, value, size, crc32c) 73 + 74 + static DEFINE_STATIC_KEY_FALSE(have_crc32); 75 + 76 + u32 crc32_le_arch(u32 crc, const u8 *p, size_t len) 77 + { 78 + if (!static_branch_likely(&have_crc32)) 79 + return crc32_le_base(crc, p, len); 80 + 81 + if (IS_ENABLED(CONFIG_64BIT)) { 82 + for (; len >= sizeof(u64); p += sizeof(u64), len -= sizeof(u64)) { 83 + u64 value = get_unaligned_le64(p); 84 + 85 + CRC32(crc, value, d); 86 + } 87 + 88 + if (len & sizeof(u32)) { 89 + u32 value = get_unaligned_le32(p); 90 + 91 + CRC32(crc, value, w); 92 + p += sizeof(u32); 93 + } 94 + } else { 95 + for (; len >= sizeof(u32); len -= sizeof(u32)) { 96 + u32 value = get_unaligned_le32(p); 97 + 98 + CRC32(crc, value, w); 99 + p += sizeof(u32); 100 + } 101 + } 102 + 103 + if (len & sizeof(u16)) { 104 + u16 value = get_unaligned_le16(p); 105 + 106 + CRC32(crc, value, h); 107 + p += sizeof(u16); 108 + } 109 + 110 + if (len & sizeof(u8)) { 111 + u8 value = *p++; 112 + 113 + CRC32(crc, value, b); 114 + } 115 + 116 + return crc; 117 + } 118 + EXPORT_SYMBOL(crc32_le_arch); 119 + 120 + u32 crc32c_le_arch(u32 crc, const u8 *p, size_t len) 121 + { 122 + if (!static_branch_likely(&have_crc32)) 123 + return crc32c_le_base(crc, p, len); 124 + 125 + if (IS_ENABLED(CONFIG_64BIT)) { 126 + for (; len >= sizeof(u64); p += sizeof(u64), len -= sizeof(u64)) { 127 + u64 value = get_unaligned_le64(p); 128 + 129 + CRC32C(crc, value, d); 130 + } 131 + 132 + if (len & sizeof(u32)) { 133 + u32 value = get_unaligned_le32(p); 134 + 135 + CRC32C(crc, value, w); 136 + p += sizeof(u32); 137 + } 138 + } else { 139 + for (; len >= sizeof(u32); len -= sizeof(u32)) { 140 + u32 value = get_unaligned_le32(p); 141 + 142 + CRC32C(crc, value, w); 143 + p += sizeof(u32); 144 + } 145 + } 146 + 147 + if (len & sizeof(u16)) { 148 + u16 value = get_unaligned_le16(p); 149 + 150 + CRC32C(crc, value, h); 151 + p += sizeof(u16); 152 + } 153 + 154 + if (len & sizeof(u8)) { 155 + u8 value = *p++; 156 + 157 + CRC32C(crc, value, b); 158 + } 159 + return crc; 160 + } 161 + EXPORT_SYMBOL(crc32c_le_arch); 162 + 163 + u32 crc32_be_arch(u32 crc, const u8 *p, size_t len) 164 + { 165 + return crc32_be_base(crc, p, len); 166 + } 167 + EXPORT_SYMBOL(crc32_be_arch); 168 + 169 + static int __init crc32_mips_init(void) 170 + { 171 + if (cpu_have_feature(cpu_feature(MIPS_CRC32))) 172 + static_branch_enable(&have_crc32); 173 + return 0; 174 + } 175 + arch_initcall(crc32_mips_init); 176 + 177 + static void __exit crc32_mips_exit(void) 178 + { 179 + } 180 + module_exit(crc32_mips_exit); 181 + 182 + u32 crc32_optimizations(void) 183 + { 184 + if (static_key_enabled(&have_crc32)) 185 + return CRC32_LE_OPTIMIZATION | CRC32C_OPTIMIZATION; 186 + return 0; 187 + } 188 + EXPORT_SYMBOL(crc32_optimizations); 189 + 190 + MODULE_AUTHOR("Marcin Nowakowski <marcin.nowakowski@mips.com"); 191 + MODULE_DESCRIPTION("CRC32 and CRC32C using optional MIPS instructions"); 192 + MODULE_LICENSE("GPL v2");