aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/idle/intel_idle.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/idle/intel_idle.c')
-rw-r--r--drivers/idle/intel_idle.c51
1 files changed, 15 insertions, 36 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index cbd4e9abc47e..282186e53290 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
123 * which is also the index into the MWAIT hint array. 123 * which is also the index into the MWAIT hint array.
124 * Thus C0 is a dummy. 124 * Thus C0 is a dummy.
125 */ 125 */
126static struct cpuidle_state nehalem_cstates[] __initdata = { 126static struct cpuidle_state nehalem_cstates[] = {
127 { 127 {
128 .name = "C1-NHM", 128 .name = "C1-NHM",
129 .desc = "MWAIT 0x00", 129 .desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[] __initdata = {
156 .enter = NULL } 156 .enter = NULL }
157}; 157};
158 158
159static struct cpuidle_state snb_cstates[] __initdata = { 159static struct cpuidle_state snb_cstates[] = {
160 { 160 {
161 .name = "C1-SNB", 161 .name = "C1-SNB",
162 .desc = "MWAIT 0x00", 162 .desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[] __initdata = {
196 .enter = NULL } 196 .enter = NULL }
197}; 197};
198 198
199static struct cpuidle_state ivb_cstates[] __initdata = { 199static struct cpuidle_state ivb_cstates[] = {
200 { 200 {
201 .name = "C1-IVB", 201 .name = "C1-IVB",
202 .desc = "MWAIT 0x00", 202 .desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[] __initdata = {
236 .enter = NULL } 236 .enter = NULL }
237}; 237};
238 238
239static struct cpuidle_state hsw_cstates[] __initdata = { 239static struct cpuidle_state hsw_cstates[] = {
240 { 240 {
241 .name = "C1-HSW", 241 .name = "C1-HSW",
242 .desc = "MWAIT 0x00", 242 .desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[] __initdata = {
297 .enter = NULL } 297 .enter = NULL }
298}; 298};
299 299
300static struct cpuidle_state atom_cstates[] __initdata = { 300static struct cpuidle_state atom_cstates[] = {
301 { 301 {
302 .name = "C1E-ATM", 302 .name = "C1E-ATM",
303 .desc = "MWAIT 0x00", 303 .desc = "MWAIT 0x00",
@@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = {
329 { 329 {
330 .enter = NULL } 330 .enter = NULL }
331}; 331};
332static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = { 332static struct cpuidle_state avn_cstates[] = {
333 { 333 {
334 .name = "C1-AVN", 334 .name = "C1-AVN",
335 .desc = "MWAIT 0x00", 335 .desc = "MWAIT 0x00",
@@ -340,10 +340,12 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = {
340 { 340 {
341 .name = "C6-AVN", 341 .name = "C6-AVN",
342 .desc = "MWAIT 0x51", 342 .desc = "MWAIT 0x51",
343 .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 343 .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
344 .exit_latency = 15, 344 .exit_latency = 15,
345 .target_residency = 45, 345 .target_residency = 45,
346 .enter = &intel_idle }, 346 .enter = &intel_idle },
347 {
348 .enter = NULL }
347}; 349};
348 350
349/** 351/**
@@ -377,6 +379,9 @@ static int intel_idle(struct cpuidle_device *dev,
377 379
378 if (!current_set_polling_and_test()) { 380 if (!current_set_polling_and_test()) {
379 381
382 if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
383 clflush((void *)&current_thread_info()->flags);
384
380 __monitor((void *)&current_thread_info()->flags, 0, 0); 385 __monitor((void *)&current_thread_info()->flags, 0, 0);
381 smp_mb(); 386 smp_mb();
382 if (!need_resched()) 387 if (!need_resched())
@@ -639,39 +644,10 @@ static int __init intel_idle_cpuidle_driver_init(void)
639 */ 644 */
640static int intel_idle_cpu_init(int cpu) 645static int intel_idle_cpu_init(int cpu)
641{ 646{
642 int cstate;
643 struct cpuidle_device *dev; 647 struct cpuidle_device *dev;
644 648
645 dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu); 649 dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
646 650
647 dev->state_count = 1;
648
649 for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
650 int num_substates, mwait_hint, mwait_cstate, mwait_substate;
651
652 if (cpuidle_state_table[cstate].enter == NULL)
653 break;
654
655 if (cstate + 1 > max_cstate) {
656 printk(PREFIX "max_cstate %d reached\n", max_cstate);
657 break;
658 }
659
660 mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
661 mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint);
662 mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint);
663
664 /* does the state exist in CPUID.MWAIT? */
665 num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4))
666 & MWAIT_SUBSTATE_MASK;
667
668 /* if sub-state in table is not enumerated by CPUID */
669 if ((mwait_substate + 1) > num_substates)
670 continue;
671
672 dev->state_count += 1;
673 }
674
675 dev->cpu = cpu; 651 dev->cpu = cpu;
676 652
677 if (cpuidle_register_device(dev)) { 653 if (cpuidle_register_device(dev)) {
@@ -683,6 +659,9 @@ static int intel_idle_cpu_init(int cpu)
683 if (icpu->auto_demotion_disable_flags) 659 if (icpu->auto_demotion_disable_flags)
684 smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); 660 smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
685 661
662 if (icpu->disable_promotion_to_c1e)
663 smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1);
664
686 return 0; 665 return 0;
687} 666}
688 667