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.c69
1 files changed, 62 insertions, 7 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 56ac09d6c930..7acb32e7f817 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -59,6 +59,8 @@
59#include <linux/hrtimer.h> /* ktime_get_real() */ 59#include <linux/hrtimer.h> /* ktime_get_real() */
60#include <trace/events/power.h> 60#include <trace/events/power.h>
61#include <linux/sched.h> 61#include <linux/sched.h>
62#include <linux/notifier.h>
63#include <linux/cpu.h>
62#include <asm/mwait.h> 64#include <asm/mwait.h>
63 65
64#define INTEL_IDLE_VERSION "0.4" 66#define INTEL_IDLE_VERSION "0.4"
@@ -73,6 +75,7 @@ static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
73 75
74static unsigned int mwait_substates; 76static unsigned int mwait_substates;
75 77
78#define LAPIC_TIMER_ALWAYS_RELIABLE 0xFFFFFFFF
76/* Reliable LAPIC Timer States, bit 1 for C1 etc. */ 79/* Reliable LAPIC Timer States, bit 1 for C1 etc. */
77static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ 80static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
78 81
@@ -82,6 +85,14 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
82static struct cpuidle_state *cpuidle_state_table; 85static struct cpuidle_state *cpuidle_state_table;
83 86
84/* 87/*
88 * Set this flag for states where the HW flushes the TLB for us
89 * and so we don't need cross-calls to keep it consistent.
90 * If this flag is set, SW flushes the TLB, so even if the
91 * HW doesn't do the flushing, this flag is safe to use.
92 */
93#define CPUIDLE_FLAG_TLB_FLUSHED 0x10000
94
95/*
85 * States are indexed by the cstate number, 96 * States are indexed by the cstate number,
86 * which is also the index into the MWAIT hint array. 97 * which is also the index into the MWAIT hint array.
87 * Thus C0 is a dummy. 98 * Thus C0 is a dummy.
@@ -122,7 +133,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
122 .driver_data = (void *) 0x00, 133 .driver_data = (void *) 0x00,
123 .flags = CPUIDLE_FLAG_TIME_VALID, 134 .flags = CPUIDLE_FLAG_TIME_VALID,
124 .exit_latency = 1, 135 .exit_latency = 1,
125 .target_residency = 4, 136 .target_residency = 1,
126 .enter = &intel_idle }, 137 .enter = &intel_idle },
127 { /* MWAIT C2 */ 138 { /* MWAIT C2 */
128 .name = "SNB-C3", 139 .name = "SNB-C3",
@@ -130,7 +141,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
130 .driver_data = (void *) 0x10, 141 .driver_data = (void *) 0x10,
131 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 142 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
132 .exit_latency = 80, 143 .exit_latency = 80,
133 .target_residency = 160, 144 .target_residency = 211,
134 .enter = &intel_idle }, 145 .enter = &intel_idle },
135 { /* MWAIT C3 */ 146 { /* MWAIT C3 */
136 .name = "SNB-C6", 147 .name = "SNB-C6",
@@ -138,7 +149,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
138 .driver_data = (void *) 0x20, 149 .driver_data = (void *) 0x20,
139 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 150 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
140 .exit_latency = 104, 151 .exit_latency = 104,
141 .target_residency = 208, 152 .target_residency = 345,
142 .enter = &intel_idle }, 153 .enter = &intel_idle },
143 { /* MWAIT C4 */ 154 { /* MWAIT C4 */
144 .name = "SNB-C7", 155 .name = "SNB-C7",
@@ -146,7 +157,7 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
146 .driver_data = (void *) 0x30, 157 .driver_data = (void *) 0x30,
147 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, 158 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
148 .exit_latency = 109, 159 .exit_latency = 109,
149 .target_residency = 300, 160 .target_residency = 345,
150 .enter = &intel_idle }, 161 .enter = &intel_idle },
151}; 162};
152 163
@@ -220,8 +231,6 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
220 kt_before = ktime_get_real(); 231 kt_before = ktime_get_real();
221 232
222 stop_critical_timings(); 233 stop_critical_timings();
223 trace_power_start(POWER_CSTATE, (eax >> 4) + 1, cpu);
224 trace_cpu_idle((eax >> 4) + 1, cpu);
225 if (!need_resched()) { 234 if (!need_resched()) {
226 235
227 __monitor((void *)&current_thread_info()->flags, 0, 0); 236 __monitor((void *)&current_thread_info()->flags, 0, 0);
@@ -243,6 +252,39 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
243 return usec_delta; 252 return usec_delta;
244} 253}
245 254
255static void __setup_broadcast_timer(void *arg)
256{
257 unsigned long reason = (unsigned long)arg;
258 int cpu = smp_processor_id();
259
260 reason = reason ?
261 CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF;
262
263 clockevents_notify(reason, &cpu);
264}
265
266static int __cpuinit setup_broadcast_cpuhp_notify(struct notifier_block *n,
267 unsigned long action, void *hcpu)
268{
269 int hotcpu = (unsigned long)hcpu;
270
271 switch (action & 0xf) {
272 case CPU_ONLINE:
273 smp_call_function_single(hotcpu, __setup_broadcast_timer,
274 (void *)true, 1);
275 break;
276 case CPU_DOWN_PREPARE:
277 smp_call_function_single(hotcpu, __setup_broadcast_timer,
278 (void *)false, 1);
279 break;
280 }
281 return NOTIFY_OK;
282}
283
284static struct notifier_block __cpuinitdata setup_broadcast_notifier = {
285 .notifier_call = setup_broadcast_cpuhp_notify,
286};
287
246/* 288/*
247 * intel_idle_probe() 289 * intel_idle_probe()
248 */ 290 */
@@ -305,7 +347,11 @@ static int intel_idle_probe(void)
305 } 347 }
306 348
307 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ 349 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
308 lapic_timer_reliable_states = 0xFFFFFFFF; 350 lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
351 else {
352 smp_call_function(__setup_broadcast_timer, (void *)true, 1);
353 register_cpu_notifier(&setup_broadcast_notifier);
354 }
309 355
310 pr_debug(PREFIX "v" INTEL_IDLE_VERSION 356 pr_debug(PREFIX "v" INTEL_IDLE_VERSION
311 " model 0x%X\n", boot_cpu_data.x86_model); 357 " model 0x%X\n", boot_cpu_data.x86_model);
@@ -403,6 +449,10 @@ static int __init intel_idle_init(void)
403{ 449{
404 int retval; 450 int retval;
405 451
452 /* Do not load intel_idle at all for now if idle= is passed */
453 if (boot_option_idle_override != IDLE_NO_OVERRIDE)
454 return -ENODEV;
455
406 retval = intel_idle_probe(); 456 retval = intel_idle_probe();
407 if (retval) 457 if (retval)
408 return retval; 458 return retval;
@@ -428,6 +478,11 @@ static void __exit intel_idle_exit(void)
428 intel_idle_cpuidle_devices_uninit(); 478 intel_idle_cpuidle_devices_uninit();
429 cpuidle_unregister_driver(&intel_idle_driver); 479 cpuidle_unregister_driver(&intel_idle_driver);
430 480
481 if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
482 smp_call_function(__setup_broadcast_timer, (void *)false, 1);
483 unregister_cpu_notifier(&setup_broadcast_notifier);
484 }
485
431 return; 486 return;
432} 487}
433 488