diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-08-04 11:10:20 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:06 -0400 |
commit | 3117a77370b6cb902191568e4e647cdcba083d0a (patch) | |
tree | 89fecdbfda66d1e0c5e7442b52a9892fbdbbfe8e /fs | |
parent | 6dab81574346c831ded96ae3ab0e8f9ca72c37ae (diff) |
Btrfs: Add support for HW assisted crc32c
Intel doesn't yet ship hardware to the public with this enabled, but when they
do, they will be ready. Original code from:
Austin Zhang <austin_zhang@linux.intel.com>
It is currently disabled, but edit crc32c.h to turn it on.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/crc32c.h | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/fs/btrfs/crc32c.h b/fs/btrfs/crc32c.h index a93255b4ee27..bf6c12e85730 100644 --- a/fs/btrfs/crc32c.h +++ b/fs/btrfs/crc32c.h | |||
@@ -1,7 +1,95 @@ | |||
1 | #ifndef __BTRFS_CRC32C__ | ||
2 | #define __BTRFS_CRC32C__ | ||
1 | #include <asm/byteorder.h> | 3 | #include <asm/byteorder.h> |
2 | #include <linux/crc32c.h> | 4 | #include <linux/crc32c.h> |
3 | #include <linux/version.h> | 5 | #include <linux/version.h> |
4 | 6 | ||
7 | /* #define CONFIG_BTRFS_HW_SUM 1 */ | ||
8 | |||
9 | #ifdef CONFIG_BTRFS_HW_SUM | ||
10 | #ifdef CONFIG_X86 | ||
11 | /* | ||
12 | * Using hardware provided CRC32 instruction to accelerate the CRC32 disposal. | ||
13 | * CRC32C polynomial:0x1EDC6F41(BE)/0x82F63B78(LE) | ||
14 | * CRC32 is a new instruction in Intel SSE4.2, the reference can be found at: | ||
15 | * http://www.intel.com/products/processor/manuals/ | ||
16 | * Intel(R) 64 and IA-32 Architectures Software Developer's Manual | ||
17 | * Volume 2A: Instruction Set Reference, A-M | ||
18 | */ | ||
19 | |||
20 | #include <asm/cpufeature.h> | ||
21 | #include <asm/processor.h> | ||
22 | |||
23 | #define X86_FEATURE_XMM4_2 (4*32+20) /* Streaming SIMD Extensions-4.2 */ | ||
24 | #define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2) | ||
25 | |||
26 | #ifdef CONFIG_X86_64 | ||
27 | #define REX_PRE "0x48, " | ||
28 | #define SCALE_F 8 | ||
29 | #else | ||
30 | #define REX_PRE | ||
31 | #define SCALE_F 4 | ||
32 | #endif | ||
33 | |||
34 | static inline u32 btrfs_crc32c_le_hw_byte(u32 crc, unsigned char const *data, | ||
35 | size_t length) | ||
36 | { | ||
37 | while (length--) { | ||
38 | __asm__ __volatile__( | ||
39 | ".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1" | ||
40 | :"=S"(crc) | ||
41 | :"0"(crc), "c"(*data) | ||
42 | ); | ||
43 | data++; | ||
44 | } | ||
45 | |||
46 | return crc; | ||
47 | } | ||
48 | |||
49 | static inline u32 __pure btrfs_crc32c_le_hw(u32 crc, unsigned char const *p, | ||
50 | size_t len) | ||
51 | { | ||
52 | unsigned int iquotient = len / SCALE_F; | ||
53 | unsigned int iremainder = len % SCALE_F; | ||
54 | #ifdef CONFIG_X86_64 | ||
55 | u64 *ptmp = (u64 *)p; | ||
56 | #else | ||
57 | u32 *ptmp = (u32 *)p; | ||
58 | #endif | ||
59 | |||
60 | while (iquotient--) { | ||
61 | __asm__ __volatile__( | ||
62 | ".byte 0xf2, " REX_PRE "0xf, 0x38, 0xf1, 0xf1;" | ||
63 | :"=S"(crc) | ||
64 | :"0"(crc), "c"(*ptmp) | ||
65 | ); | ||
66 | ptmp++; | ||
67 | } | ||
68 | |||
69 | if (iremainder) | ||
70 | crc = btrfs_crc32c_le_hw_byte(crc, (unsigned char *)ptmp, | ||
71 | iremainder); | ||
72 | |||
73 | return crc; | ||
74 | } | ||
75 | #endif /* CONFIG_BTRFS_HW_SUM */ | ||
76 | |||
77 | static inline u32 __btrfs_crc32c(u32 crc, unsigned char const *address, | ||
78 | size_t len) | ||
79 | { | ||
80 | #ifdef CONFIG_BTRFS_HW_SUM | ||
81 | if (cpu_has_xmm4_2) | ||
82 | return btrfs_crc32c_le_hw(crc, address, len); | ||
83 | #endif | ||
84 | return crc32c_le(crc, address, len); | ||
85 | } | ||
86 | |||
87 | #else | ||
88 | |||
89 | #define __btrfs_crc32c(seed, data, length) crc32c(seed, data, length) | ||
90 | |||
91 | #endif /* CONFIG_X86 */ | ||
92 | |||
5 | /** | 93 | /** |
6 | * implementation of crc32c_le() changed in linux-2.6.23, | 94 | * implementation of crc32c_le() changed in linux-2.6.23, |
7 | * has of v0.13 btrfs-progs is using the latest version. | 95 | * has of v0.13 btrfs-progs is using the latest version. |
@@ -10,8 +98,11 @@ | |||
10 | */ | 98 | */ |
11 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) | 99 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) |
12 | #define btrfs_crc32c(seed, data, length) \ | 100 | #define btrfs_crc32c(seed, data, length) \ |
13 | __cpu_to_le32( crc32c( __le32_to_cpu(seed), data, length) ) | 101 | __cpu_to_le32( __btrfs_crc32c( __le32_to_cpu(seed), \ |
102 | (unsigned char const *)data, length) ) | ||
14 | #else | 103 | #else |
15 | #define btrfs_crc32c(seed, data, length) \ | 104 | #define btrfs_crc32c(seed, data, length) \ |
16 | crc32c(seed, data, length) | 105 | __btrfs_crc32c(seed, (unsigned char const *)data, length) |
106 | #endif | ||
17 | #endif | 107 | #endif |
108 | |||