1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
From fd1f55138c242bd9aeec374ff611064bdc89b359 Mon Sep 17 00:00:00 2001
From: Jim Kukunas <james.t.kukunas@linux.intel.com>
Date: Fri, 27 May 2016 09:26:51 -0400
Subject: [PATCH 117/124] raid6: add Kconfig option to skip raid6 benchmarking
Adds CONFIG_RAID6_FORCE_ALGO, which causes the kernel to not benchmark
each raid recovery and syndrome generation algorithm, and instead use
the version selected via Kconfig (CONFIG_RAID6_FORCE_{INT,SSSE3,AVX2}).
In the case, the selected algorithm is not supported by the processor at
runtime, a fallback is used.
Signed-off-by: Jim Kukunas <james.t.kukunas@linux.intel.com>
---
lib/Kconfig | 3 +--
lib/raid6/Kconfig | 38 ++++++++++++++++++++++++++++++++++++
lib/raid6/algos.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 97 insertions(+), 2 deletions(-)
create mode 100644 lib/raid6/Kconfig
diff --git a/lib/Kconfig b/lib/Kconfig
index 260a80e313b9..b3efd21db2fd 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -7,8 +7,7 @@ config BINARY_PRINTF
menu "Library routines"
-config RAID6_PQ
- tristate
+source "lib/raid6/Kconfig"
config BITREVERSE
tristate
diff --git a/lib/raid6/Kconfig b/lib/raid6/Kconfig
new file mode 100644
index 000000000000..d881d6be89bb
--- /dev/null
+++ b/lib/raid6/Kconfig
@@ -0,0 +1,38 @@
+menu "RAID 6"
+
+config RAID6_PQ
+ tristate
+
+config RAID6_FORCE_ALGO
+ bool "Always use specified recovery algorithm"
+ default n
+ depends on RAID6_PQ
+ help
+ If this option is not set, on every boot the kernel will
+ benchmark each optimized version of the RAID6 recovery and
+ syndrome generation algorithms and will select the one that
+ performs best. Microbenchmarking each version negatively
+ affects boot time.
+
+ Enabling this option skips the benchmark at boot, and
+ instead always uses the algorithm selected. The only exception
+ is if the selected algorithm relies on a cpu feature not
+ supported at runtime. In this case, one of the lower performance
+ fallbacks are used.
+
+choice
+ prompt "RAID6 Recovery Algorithm"
+ default RAID6_FORCE_INT
+ depends on RAID6_FORCE_ALGO
+ ---help---
+ Select the RAID6 recovery algorithm to unconditionally use
+
+ config RAID6_FORCE_INT
+ bool "Reference Implementation"
+ config RAID6_FORCE_SSSE3
+ bool "SSSE3"
+ config RAID6_FORCE_AVX2
+ bool "AVX2"
+endchoice
+
+endmenu
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 7857049fd7d3..29332d2a04a5 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -125,6 +125,63 @@ const struct raid6_recov_calls *const raid6_recov_algos[] = {
#define time_before(x, y) ((x) < (y))
#endif
+#ifdef CONFIG_RAID6_FORCE_ALGO
+/* TODO don't compile in algos that will never be used */
+int __init raid6_select_algo(void)
+{
+ const struct raid6_recov_calls *recov_fallback = &raid6_recov_intx1;
+ const struct raid6_recov_calls *recov_algo;
+ const struct raid6_calls *gen_fallback;
+ const struct raid6_calls *gen_algo;
+
+#if defined(__i386__)
+ gen_fallback = &raid6_intx32;
+#elif defined(__x86_64__)
+ gen_fallback = &raid6_sse2x2;
+#else
+# error "TODO"
+#endif
+
+#if defined(CONFIG_RAID6_FORCE_INT)
+ recov_algo = &raid6_recov_intx1;
+ gen_algo = &raid6_intx32;
+
+#elif defined(CONFIG_RAID6_FORCE_SSSE3)
+ recov_algo = &raid6_recov_ssse3;
+#if defined(__i386__)
+ gen_algo = &raid6_sse2x2;
+#else
+ gen_algo = &raid6_sse2x4;
+#endif
+
+#elif defined(CONFIG_RAID6_FORCE_AVX2)
+ recov_algo = &raid6_recov_avx2;
+
+#if defined(__i386__)
+ gen_algo = &raid6_avx2x2;
+#else
+ gen_algo = &raid6_avx2x4;
+#endif
+
+#else
+#error "RAID6 Forced Recov Algo: Unsupported selection"
+#endif
+
+ if (recov_algo->valid != NULL && recov_algo->valid() == 0)
+ recov_algo = recov_fallback;
+
+ pr_info("raid6: Forced to use recovery algorithm %s\n", recov_algo->name);
+
+ raid6_2data_recov = recov_algo->data2;
+ raid6_datap_recov = recov_algo->datap;
+
+ pr_info("raid6: Forced gen() algo %s\n", gen_algo->name);
+
+ raid6_call = *gen_algo;
+
+ return gen_algo && recov_algo ? 0 : -EINVAL;
+}
+#else
static inline const struct raid6_recov_calls *raid6_choose_recov(void)
{
const struct raid6_recov_calls *const *algo;
@@ -256,6 +313,7 @@ int __init raid6_select_algo(void)
return gen_best && rec_best ? 0 : -EINVAL;
}
+#endif
static void raid6_exit(void)
{
--
2.11.1
|