diff options
Diffstat (limited to 'drivers/idle/intel_idle.c')
-rw-r--r-- | drivers/idle/intel_idle.c | 51 |
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 | */ |
126 | static struct cpuidle_state nehalem_cstates[] __initdata = { | 126 | static 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 | ||
159 | static struct cpuidle_state snb_cstates[] __initdata = { | 159 | static 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 | ||
199 | static struct cpuidle_state ivb_cstates[] __initdata = { | 199 | static 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 | ||
239 | static struct cpuidle_state hsw_cstates[] __initdata = { | 239 | static 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 | ||
300 | static struct cpuidle_state atom_cstates[] __initdata = { | 300 | static 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 | }; |
332 | static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = { | 332 | static 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 *)¤t_thread_info()->flags); | ||
384 | |||
380 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | 385 | __monitor((void *)¤t_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 | */ |
640 | static int intel_idle_cpu_init(int cpu) | 645 | static 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 | ||