Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Accelerated CRC-T10DIF using ARM NEON and Crypto Extensions instructions
0004  *
0005  * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
0006  */
0007 
0008 #include <linux/crc-t10dif.h>
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/string.h>
0013 
0014 #include <crypto/internal/hash.h>
0015 #include <crypto/internal/simd.h>
0016 
0017 #include <asm/neon.h>
0018 #include <asm/simd.h>
0019 
0020 #define CRC_T10DIF_PMULL_CHUNK_SIZE 16U
0021 
0022 asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 *buf, size_t len);
0023 
0024 static int crct10dif_init(struct shash_desc *desc)
0025 {
0026     u16 *crc = shash_desc_ctx(desc);
0027 
0028     *crc = 0;
0029     return 0;
0030 }
0031 
0032 static int crct10dif_update(struct shash_desc *desc, const u8 *data,
0033                 unsigned int length)
0034 {
0035     u16 *crc = shash_desc_ctx(desc);
0036 
0037     if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && crypto_simd_usable()) {
0038         kernel_neon_begin();
0039         *crc = crc_t10dif_pmull(*crc, data, length);
0040         kernel_neon_end();
0041     } else {
0042         *crc = crc_t10dif_generic(*crc, data, length);
0043     }
0044 
0045     return 0;
0046 }
0047 
0048 static int crct10dif_final(struct shash_desc *desc, u8 *out)
0049 {
0050     u16 *crc = shash_desc_ctx(desc);
0051 
0052     *(u16 *)out = *crc;
0053     return 0;
0054 }
0055 
0056 static struct shash_alg crc_t10dif_alg = {
0057     .digestsize     = CRC_T10DIF_DIGEST_SIZE,
0058     .init           = crct10dif_init,
0059     .update         = crct10dif_update,
0060     .final          = crct10dif_final,
0061     .descsize       = CRC_T10DIF_DIGEST_SIZE,
0062 
0063     .base.cra_name      = "crct10dif",
0064     .base.cra_driver_name   = "crct10dif-arm-ce",
0065     .base.cra_priority  = 200,
0066     .base.cra_blocksize = CRC_T10DIF_BLOCK_SIZE,
0067     .base.cra_module    = THIS_MODULE,
0068 };
0069 
0070 static int __init crc_t10dif_mod_init(void)
0071 {
0072     if (!(elf_hwcap2 & HWCAP2_PMULL))
0073         return -ENODEV;
0074 
0075     return crypto_register_shash(&crc_t10dif_alg);
0076 }
0077 
0078 static void __exit crc_t10dif_mod_exit(void)
0079 {
0080     crypto_unregister_shash(&crc_t10dif_alg);
0081 }
0082 
0083 module_init(crc_t10dif_mod_init);
0084 module_exit(crc_t10dif_mod_exit);
0085 
0086 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
0087 MODULE_LICENSE("GPL v2");
0088 MODULE_ALIAS_CRYPTO("crct10dif");