Commit 32e9518005c8dd9ed668f40f98632c8186df4909

Authored by Len Brown
1 parent e022e7eb90

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 }