1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <linux/crc32.h>
4 #include <linux/linkage.h>
6 #include <asm/alternative.h>
7 #include <asm/cpufeature.h>
11 #include <crypto/internal/simd.h>
13 // The minimum input length to consider the 4-way interleaved code path
14 static const size_t min_len
= 1024;
16 asmlinkage u32
crc32_le_arm64(u32 crc
, unsigned char const *p
, size_t len
);
17 asmlinkage u32
crc32c_le_arm64(u32 crc
, unsigned char const *p
, size_t len
);
18 asmlinkage u32
crc32_be_arm64(u32 crc
, unsigned char const *p
, size_t len
);
20 asmlinkage u32
crc32_le_arm64_4way(u32 crc
, unsigned char const *p
, size_t len
);
21 asmlinkage u32
crc32c_le_arm64_4way(u32 crc
, unsigned char const *p
, size_t len
);
22 asmlinkage u32
crc32_be_arm64_4way(u32 crc
, unsigned char const *p
, size_t len
);
24 u32 __pure
crc32_le(u32 crc
, unsigned char const *p
, size_t len
)
26 if (!alternative_has_cap_likely(ARM64_HAS_CRC32
))
27 return crc32_le_base(crc
, p
, len
);
29 if (len
>= min_len
&& cpu_have_named_feature(PMULL
) && crypto_simd_usable()) {
31 crc
= crc32_le_arm64_4way(crc
, p
, len
);
34 p
+= round_down(len
, 64);
41 return crc32_le_arm64(crc
, p
, len
);
44 u32 __pure
__crc32c_le(u32 crc
, unsigned char const *p
, size_t len
)
46 if (!alternative_has_cap_likely(ARM64_HAS_CRC32
))
47 return __crc32c_le_base(crc
, p
, len
);
49 if (len
>= min_len
&& cpu_have_named_feature(PMULL
) && crypto_simd_usable()) {
51 crc
= crc32c_le_arm64_4way(crc
, p
, len
);
54 p
+= round_down(len
, 64);
61 return crc32c_le_arm64(crc
, p
, len
);
64 u32 __pure
crc32_be(u32 crc
, unsigned char const *p
, size_t len
)
66 if (!alternative_has_cap_likely(ARM64_HAS_CRC32
))
67 return crc32_be_base(crc
, p
, len
);
69 if (len
>= min_len
&& cpu_have_named_feature(PMULL
) && crypto_simd_usable()) {
71 crc
= crc32_be_arm64_4way(crc
, p
, len
);
74 p
+= round_down(len
, 64);
81 return crc32_be_arm64(crc
, p
, len
);