Commit 32e9518005c8dd9ed668f40f98632c8186df4909
1 parent
e022e7eb90
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
intel_idle: export both C1 and C1E
Here we disable HW promotion of C1 to C1E and export both C1 and C1E and distinct C-states. This allows a cpuidle governor to choose a lower latency C-state than C1E when necessary to satisfy performance and QOS constraints -- and still save power versus polling. This also corrects the erroneous latency previously reported for C1E -- it is 10usec, not 1usec. Note that if you use "intel_idle.max_cstate=N", then you must increment N by 1 to get the same behavior after this change. Signed-off-by: Len Brown <len.brown@intel.com>
Showing 1 changed file with 49 additions and 5 deletions Side-by-side Diff
drivers/idle/intel_idle.c
... | ... | @@ -90,6 +90,7 @@ |
90 | 90 | * Indicate which enable bits to clear here. |
91 | 91 | */ |
92 | 92 | unsigned long auto_demotion_disable_flags; |
93 | + bool disable_promotion_to_c1e; | |
93 | 94 | }; |
94 | 95 | |
95 | 96 | static const struct idle_cpu *icpu; |
... | ... | @@ -132,6 +133,13 @@ |
132 | 133 | .target_residency = 6, |
133 | 134 | .enter = &intel_idle }, |
134 | 135 | { |
136 | + .name = "C1E-NHM", | |
137 | + .desc = "MWAIT 0x01", | |
138 | + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | |
139 | + .exit_latency = 10, | |
140 | + .target_residency = 20, | |
141 | + .enter = &intel_idle }, | |
142 | + { | |
135 | 143 | .name = "C3-NHM", |
136 | 144 | .desc = "MWAIT 0x10", |
137 | 145 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
138 | 146 | |
... | ... | @@ -154,10 +162,17 @@ |
154 | 162 | .name = "C1-SNB", |
155 | 163 | .desc = "MWAIT 0x00", |
156 | 164 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, |
157 | - .exit_latency = 1, | |
158 | - .target_residency = 1, | |
165 | + .exit_latency = 2, | |
166 | + .target_residency = 2, | |
159 | 167 | .enter = &intel_idle }, |
160 | 168 | { |
169 | + .name = "C1E-SNB", | |
170 | + .desc = "MWAIT 0x01", | |
171 | + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | |
172 | + .exit_latency = 10, | |
173 | + .target_residency = 20, | |
174 | + .enter = &intel_idle }, | |
175 | + { | |
161 | 176 | .name = "C3-SNB", |
162 | 177 | .desc = "MWAIT 0x10", |
163 | 178 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
... | ... | @@ -191,6 +206,13 @@ |
191 | 206 | .target_residency = 1, |
192 | 207 | .enter = &intel_idle }, |
193 | 208 | { |
209 | + .name = "C1E-IVB", | |
210 | + .desc = "MWAIT 0x01", | |
211 | + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | |
212 | + .exit_latency = 10, | |
213 | + .target_residency = 20, | |
214 | + .enter = &intel_idle }, | |
215 | + { | |
194 | 216 | .name = "C3-IVB", |
195 | 217 | .desc = "MWAIT 0x10", |
196 | 218 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
... | ... | @@ -224,6 +246,13 @@ |
224 | 246 | .target_residency = 2, |
225 | 247 | .enter = &intel_idle }, |
226 | 248 | { |
249 | + .name = "C1E-HSW", | |
250 | + .desc = "MWAIT 0x01", | |
251 | + .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | |
252 | + .exit_latency = 10, | |
253 | + .target_residency = 20, | |
254 | + .enter = &intel_idle }, | |
255 | + { | |
227 | 256 | .name = "C3-HSW", |
228 | 257 | .desc = "MWAIT 0x10", |
229 | 258 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
230 | 259 | |
... | ... | @@ -250,11 +279,11 @@ |
250 | 279 | |
251 | 280 | static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = { |
252 | 281 | { |
253 | - .name = "C1-ATM", | |
282 | + .name = "C1E-ATM", | |
254 | 283 | .desc = "MWAIT 0x00", |
255 | 284 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, |
256 | - .exit_latency = 1, | |
257 | - .target_residency = 4, | |
285 | + .exit_latency = 10, | |
286 | + .target_residency = 20, | |
258 | 287 | .enter = &intel_idle }, |
259 | 288 | { |
260 | 289 | .name = "C2-ATM", |
261 | 290 | |
262 | 291 | |
... | ... | @@ -377,10 +406,19 @@ |
377 | 406 | msr_bits &= ~(icpu->auto_demotion_disable_flags); |
378 | 407 | wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); |
379 | 408 | } |
409 | +static void c1e_promotion_disable(void *dummy) | |
410 | +{ | |
411 | + unsigned long long msr_bits; | |
380 | 412 | |
413 | + rdmsrl(MSR_IA32_POWER_CTL, msr_bits); | |
414 | + msr_bits &= ~0x2; | |
415 | + wrmsrl(MSR_IA32_POWER_CTL, msr_bits); | |
416 | +} | |
417 | + | |
381 | 418 | static const struct idle_cpu idle_cpu_nehalem = { |
382 | 419 | .state_table = nehalem_cstates, |
383 | 420 | .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, |
421 | + .disable_promotion_to_c1e = true, | |
384 | 422 | }; |
385 | 423 | |
386 | 424 | static const struct idle_cpu idle_cpu_atom = { |
387 | 425 | |
388 | 426 | |
... | ... | @@ -394,14 +432,17 @@ |
394 | 432 | |
395 | 433 | static const struct idle_cpu idle_cpu_snb = { |
396 | 434 | .state_table = snb_cstates, |
435 | + .disable_promotion_to_c1e = true, | |
397 | 436 | }; |
398 | 437 | |
399 | 438 | static const struct idle_cpu idle_cpu_ivb = { |
400 | 439 | .state_table = ivb_cstates, |
440 | + .disable_promotion_to_c1e = true, | |
401 | 441 | }; |
402 | 442 | |
403 | 443 | static const struct idle_cpu idle_cpu_hsw = { |
404 | 444 | .state_table = hsw_cstates, |
445 | + .disable_promotion_to_c1e = true, | |
405 | 446 | }; |
406 | 447 | |
407 | 448 | #define ICPU(model, cpu) \ |
... | ... | @@ -543,6 +584,9 @@ |
543 | 584 | |
544 | 585 | if (icpu->auto_demotion_disable_flags) |
545 | 586 | on_each_cpu(auto_demotion_disable, NULL, 1); |
587 | + | |
588 | + if (icpu->disable_promotion_to_c1e) /* each-cpu is redundant */ | |
589 | + on_each_cpu(c1e_promotion_disable, NULL, 1); | |
546 | 590 | |
547 | 591 | return 0; |
548 | 592 | } |