xref: /linux/lib/crc/arm/crc-t10dif.h (revision 7fc2cd2e4b398c57c9cf961cfea05eadbf34c05c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Accelerated CRC-T10DIF using ARM NEON and Crypto Extensions instructions
4  *
5  * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.org>
6  */
7 
8 #include <asm/simd.h>
9 
10 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
11 static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_pmull);
12 
13 #define CRC_T10DIF_PMULL_CHUNK_SIZE	16U
14 
15 asmlinkage u16 crc_t10dif_pmull64(u16 init_crc, const u8 *buf, size_t len);
16 asmlinkage void crc_t10dif_pmull8(u16 init_crc, const u8 *buf, size_t len,
17 				  u8 out[16]);
18 
19 static inline u16 crc_t10dif_arch(u16 crc, const u8 *data, size_t length)
20 {
21 	if (length >= CRC_T10DIF_PMULL_CHUNK_SIZE && likely(may_use_simd())) {
22 		if (static_branch_likely(&have_pmull)) {
23 			scoped_ksimd()
24 				return crc_t10dif_pmull64(crc, data, length);
25 		} else if (length > CRC_T10DIF_PMULL_CHUNK_SIZE &&
26 			   static_branch_likely(&have_neon)) {
27 			u8 buf[16] __aligned(16);
28 
29 			scoped_ksimd()
30 				crc_t10dif_pmull8(crc, data, length, buf);
31 
32 			return crc_t10dif_generic(0, buf, sizeof(buf));
33 		}
34 	}
35 	return crc_t10dif_generic(crc, data, length);
36 }
37 
38 #define crc_t10dif_mod_init_arch crc_t10dif_mod_init_arch
39 static void crc_t10dif_mod_init_arch(void)
40 {
41 	if (elf_hwcap & HWCAP_NEON) {
42 		static_branch_enable(&have_neon);
43 		if (elf_hwcap2 & HWCAP2_PMULL)
44 			static_branch_enable(&have_pmull);
45 	}
46 }
47