diff options
-rw-r--r-- | drivers/idle/intel_idle.c | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 927cfb4d66f4..5d6675013864 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -90,6 +90,7 @@ struct idle_cpu { | |||
90 | * Indicate which enable bits to clear here. | 90 | * Indicate which enable bits to clear here. |
91 | */ | 91 | */ |
92 | unsigned long auto_demotion_disable_flags; | 92 | unsigned long auto_demotion_disable_flags; |
93 | bool disable_promotion_to_c1e; | ||
93 | }; | 94 | }; |
94 | 95 | ||
95 | static const struct idle_cpu *icpu; | 96 | static const struct idle_cpu *icpu; |
@@ -132,6 +133,13 @@ static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = { | |||
132 | .target_residency = 6, | 133 | .target_residency = 6, |
133 | .enter = &intel_idle }, | 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 | .name = "C3-NHM", | 143 | .name = "C3-NHM", |
136 | .desc = "MWAIT 0x10", | 144 | .desc = "MWAIT 0x10", |
137 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | 145 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
@@ -154,8 +162,15 @@ static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = { | |||
154 | .name = "C1-SNB", | 162 | .name = "C1-SNB", |
155 | .desc = "MWAIT 0x00", | 163 | .desc = "MWAIT 0x00", |
156 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, | 164 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, |
157 | .exit_latency = 1, | 165 | .exit_latency = 2, |
158 | .target_residency = 1, | 166 | .target_residency = 2, |
167 | .enter = &intel_idle }, | ||
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, | ||
159 | .enter = &intel_idle }, | 174 | .enter = &intel_idle }, |
160 | { | 175 | { |
161 | .name = "C3-SNB", | 176 | .name = "C3-SNB", |
@@ -191,6 +206,13 @@ static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = { | |||
191 | .target_residency = 1, | 206 | .target_residency = 1, |
192 | .enter = &intel_idle }, | 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 | .name = "C3-IVB", | 216 | .name = "C3-IVB", |
195 | .desc = "MWAIT 0x10", | 217 | .desc = "MWAIT 0x10", |
196 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | 218 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
@@ -224,6 +246,13 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = { | |||
224 | .target_residency = 2, | 246 | .target_residency = 2, |
225 | .enter = &intel_idle }, | 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 | .name = "C3-HSW", | 256 | .name = "C3-HSW", |
228 | .desc = "MWAIT 0x10", | 257 | .desc = "MWAIT 0x10", |
229 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | 258 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
@@ -250,11 +279,11 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = { | |||
250 | 279 | ||
251 | static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = { | 280 | static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = { |
252 | { | 281 | { |
253 | .name = "C1-ATM", | 282 | .name = "C1E-ATM", |
254 | .desc = "MWAIT 0x00", | 283 | .desc = "MWAIT 0x00", |
255 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, | 284 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, |
256 | .exit_latency = 1, | 285 | .exit_latency = 10, |
257 | .target_residency = 4, | 286 | .target_residency = 20, |
258 | .enter = &intel_idle }, | 287 | .enter = &intel_idle }, |
259 | { | 288 | { |
260 | .name = "C2-ATM", | 289 | .name = "C2-ATM", |
@@ -377,10 +406,19 @@ static void auto_demotion_disable(void *dummy) | |||
377 | msr_bits &= ~(icpu->auto_demotion_disable_flags); | 406 | msr_bits &= ~(icpu->auto_demotion_disable_flags); |
378 | wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); | 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; | ||
412 | |||
413 | rdmsrl(MSR_IA32_POWER_CTL, msr_bits); | ||
414 | msr_bits &= ~0x2; | ||
415 | wrmsrl(MSR_IA32_POWER_CTL, msr_bits); | ||
416 | } | ||
380 | 417 | ||
381 | static const struct idle_cpu idle_cpu_nehalem = { | 418 | static const struct idle_cpu idle_cpu_nehalem = { |
382 | .state_table = nehalem_cstates, | 419 | .state_table = nehalem_cstates, |
383 | .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, | 420 | .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, |
421 | .disable_promotion_to_c1e = true, | ||
384 | }; | 422 | }; |
385 | 423 | ||
386 | static const struct idle_cpu idle_cpu_atom = { | 424 | static const struct idle_cpu idle_cpu_atom = { |
@@ -394,14 +432,17 @@ static const struct idle_cpu idle_cpu_lincroft = { | |||
394 | 432 | ||
395 | static const struct idle_cpu idle_cpu_snb = { | 433 | static const struct idle_cpu idle_cpu_snb = { |
396 | .state_table = snb_cstates, | 434 | .state_table = snb_cstates, |
435 | .disable_promotion_to_c1e = true, | ||
397 | }; | 436 | }; |
398 | 437 | ||
399 | static const struct idle_cpu idle_cpu_ivb = { | 438 | static const struct idle_cpu idle_cpu_ivb = { |
400 | .state_table = ivb_cstates, | 439 | .state_table = ivb_cstates, |
440 | .disable_promotion_to_c1e = true, | ||
401 | }; | 441 | }; |
402 | 442 | ||
403 | static const struct idle_cpu idle_cpu_hsw = { | 443 | static const struct idle_cpu idle_cpu_hsw = { |
404 | .state_table = hsw_cstates, | 444 | .state_table = hsw_cstates, |
445 | .disable_promotion_to_c1e = true, | ||
405 | }; | 446 | }; |
406 | 447 | ||
407 | #define ICPU(model, cpu) \ | 448 | #define ICPU(model, cpu) \ |
@@ -544,6 +585,9 @@ static int intel_idle_cpuidle_driver_init(void) | |||
544 | if (icpu->auto_demotion_disable_flags) | 585 | if (icpu->auto_demotion_disable_flags) |
545 | on_each_cpu(auto_demotion_disable, NULL, 1); | 586 | on_each_cpu(auto_demotion_disable, NULL, 1); |
546 | 587 | ||
588 | if (icpu->disable_promotion_to_c1e) /* each-cpu is redundant */ | ||
589 | on_each_cpu(c1e_promotion_disable, NULL, 1); | ||
590 | |||
547 | return 0; | 591 | return 0; |
548 | } | 592 | } |
549 | 593 | ||