aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/idle
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2013-02-02 01:31:56 -0500
committerLen Brown <len.brown@intel.com>2013-02-13 18:22:08 -0500
commit32e9518005c8dd9ed668f40f98632c8186df4909 (patch)
tree277dde14dec62b8734d404f74f55335ce354d43f /drivers/idle
parente022e7eb90f3edb83f9ff77825eda3d1b3a2f2e0 (diff)
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>
Diffstat (limited to 'drivers/idle')
-rw-r--r--drivers/idle/intel_idle.c54
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
95static const struct idle_cpu *icpu; 96static 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
251static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = { 280static 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}
409static 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
381static const struct idle_cpu idle_cpu_nehalem = { 418static 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
386static const struct idle_cpu idle_cpu_atom = { 424static const struct idle_cpu idle_cpu_atom = {
@@ -394,14 +432,17 @@ static const struct idle_cpu idle_cpu_lincroft = {
394 432
395static const struct idle_cpu idle_cpu_snb = { 433static 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
399static const struct idle_cpu idle_cpu_ivb = { 438static 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
403static const struct idle_cpu idle_cpu_hsw = { 443static 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