Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
10static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
11static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_pmull);
12
13#define CRC_T10DIF_PMULL_CHUNK_SIZE 16U
14
15asmlinkage u16 crc_t10dif_pmull64(u16 init_crc, const u8 *buf, size_t len);
16asmlinkage void crc_t10dif_pmull8(u16 init_crc, const u8 *buf, size_t len,
17 u8 out[16]);
18
19static 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
39static 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}