aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/idle/intel_idle.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-12-30 00:20:30 -0500
committerGrant Likely <grant.likely@secretlab.ca>2010-12-30 00:21:47 -0500
commitd392da5207352f09030e95d9ea335a4225667ec0 (patch)
tree7d6cd1932afcad0a5619a5c504a6d93ca318187c /drivers/idle/intel_idle.c
parente39d5ef678045d61812c1401f04fe8edb14d6359 (diff)
parent387c31c7e5c9805b0aef8833d1731a5fe7bdea14 (diff)
Merge v2.6.37-rc8 into powerpc/next
Diffstat (limited to 'drivers/idle/intel_idle.c')
-rw-r--r--[-rwxr-xr-x]drivers/idle/intel_idle.c159
1 files changed, 70 insertions, 89 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 03d202b1ff27..c131d58bcb50 100755..100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -59,33 +59,24 @@
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 <asm/mwait.h>
62 63
63#define INTEL_IDLE_VERSION "0.4" 64#define INTEL_IDLE_VERSION "0.4"
64#define PREFIX "intel_idle: " 65#define PREFIX "intel_idle: "
65 66
66#define MWAIT_SUBSTATE_MASK (0xf)
67#define MWAIT_CSTATE_MASK (0xf)
68#define MWAIT_SUBSTATE_SIZE (4)
69#define MWAIT_MAX_NUM_CSTATES 8
70#define CPUID_MWAIT_LEAF (5)
71#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1)
72#define CPUID5_ECX_INTERRUPT_BREAK (0x2)
73
74static struct cpuidle_driver intel_idle_driver = { 67static struct cpuidle_driver intel_idle_driver = {
75 .name = "intel_idle", 68 .name = "intel_idle",
76 .owner = THIS_MODULE, 69 .owner = THIS_MODULE,
77}; 70};
78/* intel_idle.max_cstate=0 disables driver */ 71/* intel_idle.max_cstate=0 disables driver */
79static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1; 72static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
80static int power_policy = 7; /* 0 = max perf; 15 = max powersave */
81 73
82static unsigned int substates; 74static unsigned int mwait_substates;
83static int (*choose_substate)(int);
84 75
85/* Reliable LAPIC Timer States, bit 1 for C1 etc. */ 76/* Reliable LAPIC Timer States, bit 1 for C1 etc. */
86static unsigned int lapic_timer_reliable_states; 77static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
87 78
88static struct cpuidle_device *intel_idle_cpuidle_devices; 79static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
89static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); 80static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
90 81
91static struct cpuidle_state *cpuidle_state_table; 82static struct cpuidle_state *cpuidle_state_table;
@@ -103,29 +94,62 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
103 .driver_data = (void *) 0x00, 94 .driver_data = (void *) 0x00,
104 .flags = CPUIDLE_FLAG_TIME_VALID, 95 .flags = CPUIDLE_FLAG_TIME_VALID,
105 .exit_latency = 3, 96 .exit_latency = 3,
106 .power_usage = 1000,
107 .target_residency = 6, 97 .target_residency = 6,
108 .enter = &intel_idle }, 98 .enter = &intel_idle },
109 { /* MWAIT C2 */ 99 { /* MWAIT C2 */
110 .name = "NHM-C3", 100 .name = "NHM-C3",
111 .desc = "MWAIT 0x10", 101 .desc = "MWAIT 0x10",
112 .driver_data = (void *) 0x10, 102 .driver_data = (void *) 0x10,
113 .flags = CPUIDLE_FLAG_TIME_VALID, 103 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
114 .exit_latency = 20, 104 .exit_latency = 20,
115 .power_usage = 500,
116 .target_residency = 80, 105 .target_residency = 80,
117 .enter = &intel_idle }, 106 .enter = &intel_idle },
118 { /* MWAIT C3 */ 107 { /* MWAIT C3 */
119 .name = "NHM-C6", 108 .name = "NHM-C6",
120 .desc = "MWAIT 0x20", 109 .desc = "MWAIT 0x20",
121 .driver_data = (void *) 0x20, 110 .driver_data = (void *) 0x20,
122 .flags = CPUIDLE_FLAG_TIME_VALID, 111 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
123 .exit_latency = 200, 112 .exit_latency = 200,
124 .power_usage = 350,
125 .target_residency = 800, 113 .target_residency = 800,
126 .enter = &intel_idle }, 114 .enter = &intel_idle },
127}; 115};
128 116
117static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
118 { /* MWAIT C0 */ },
119 { /* MWAIT C1 */
120 .name = "SNB-C1",
121 .desc = "MWAIT 0x00",
122 .driver_data = (void *) 0x00,
123 .flags = CPUIDLE_FLAG_TIME_VALID,
124 .exit_latency = 1,
125 .target_residency = 4,
126 .enter = &intel_idle },
127 { /* MWAIT C2 */
128 .name = "SNB-C3",
129 .desc = "MWAIT 0x10",
130 .driver_data = (void *) 0x10,
131 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
132 .exit_latency = 80,
133 .target_residency = 160,
134 .enter = &intel_idle },
135 { /* MWAIT C3 */
136 .name = "SNB-C6",
137 .desc = "MWAIT 0x20",
138 .driver_data = (void *) 0x20,
139 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
140 .exit_latency = 104,
141 .target_residency = 208,
142 .enter = &intel_idle },
143 { /* MWAIT C4 */
144 .name = "SNB-C7",
145 .desc = "MWAIT 0x30",
146 .driver_data = (void *) 0x30,
147 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
148 .exit_latency = 109,
149 .target_residency = 300,
150 .enter = &intel_idle },
151};
152
129static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { 153static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
130 { /* MWAIT C0 */ }, 154 { /* MWAIT C0 */ },
131 { /* MWAIT C1 */ 155 { /* MWAIT C1 */
@@ -134,7 +158,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
134 .driver_data = (void *) 0x00, 158 .driver_data = (void *) 0x00,
135 .flags = CPUIDLE_FLAG_TIME_VALID, 159 .flags = CPUIDLE_FLAG_TIME_VALID,
136 .exit_latency = 1, 160 .exit_latency = 1,
137 .power_usage = 1000,
138 .target_residency = 4, 161 .target_residency = 4,
139 .enter = &intel_idle }, 162 .enter = &intel_idle },
140 { /* MWAIT C2 */ 163 { /* MWAIT C2 */
@@ -143,7 +166,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
143 .driver_data = (void *) 0x10, 166 .driver_data = (void *) 0x10,
144 .flags = CPUIDLE_FLAG_TIME_VALID, 167 .flags = CPUIDLE_FLAG_TIME_VALID,
145 .exit_latency = 20, 168 .exit_latency = 20,
146 .power_usage = 500,
147 .target_residency = 80, 169 .target_residency = 80,
148 .enter = &intel_idle }, 170 .enter = &intel_idle },
149 { /* MWAIT C3 */ }, 171 { /* MWAIT C3 */ },
@@ -151,58 +173,21 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
151 .name = "ATM-C4", 173 .name = "ATM-C4",
152 .desc = "MWAIT 0x30", 174 .desc = "MWAIT 0x30",
153 .driver_data = (void *) 0x30, 175 .driver_data = (void *) 0x30,
154 .flags = CPUIDLE_FLAG_TIME_VALID, 176 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
155 .exit_latency = 100, 177 .exit_latency = 100,
156 .power_usage = 250,
157 .target_residency = 400, 178 .target_residency = 400,
158 .enter = &intel_idle }, 179 .enter = &intel_idle },
159 { /* MWAIT C5 */ }, 180 { /* MWAIT C5 */ },
160 { /* MWAIT C6 */ 181 { /* MWAIT C6 */
161 .name = "ATM-C6", 182 .name = "ATM-C6",
162 .desc = "MWAIT 0x40", 183 .desc = "MWAIT 0x52",
163 .driver_data = (void *) 0x40, 184 .driver_data = (void *) 0x52,
164 .flags = CPUIDLE_FLAG_TIME_VALID, 185 .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
165 .exit_latency = 200, 186 .exit_latency = 140,
166 .power_usage = 150, 187 .target_residency = 560,
167 .target_residency = 800, 188 .enter = &intel_idle },
168 .enter = NULL }, /* disabled */
169}; 189};
170 190
171/*
172 * choose_tunable_substate()
173 *
174 * Run-time decision on which C-state substate to invoke
175 * If power_policy = 0, choose shallowest substate (0)
176 * If power_policy = 15, choose deepest substate
177 * If power_policy = middle, choose middle substate etc.
178 */
179static int choose_tunable_substate(int cstate)
180{
181 unsigned int num_substates;
182 unsigned int substate_choice;
183
184 power_policy &= 0xF; /* valid range: 0-15 */
185 cstate &= 7; /* valid range: 0-7 */
186
187 num_substates = (substates >> ((cstate) * 4)) & MWAIT_SUBSTATE_MASK;
188
189 if (num_substates <= 1)
190 return 0;
191
192 substate_choice = ((power_policy + (power_policy + 1) *
193 (num_substates - 1)) / 16);
194
195 return substate_choice;
196}
197
198/*
199 * choose_zero_substate()
200 */
201static int choose_zero_substate(int cstate)
202{
203 return 0;
204}
205
206/** 191/**
207 * intel_idle 192 * intel_idle
208 * @dev: cpuidle_device 193 * @dev: cpuidle_device
@@ -220,10 +205,15 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
220 205
221 cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; 206 cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
222 207
223 eax = eax + (choose_substate)(cstate);
224
225 local_irq_disable(); 208 local_irq_disable();
226 209
210 /*
211 * leave_mm() to avoid costly and often unnecessary wakeups
212 * for flushing the user TLB's associated with the active mm.
213 */
214 if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
215 leave_mm(cpu);
216
227 if (!(lapic_timer_reliable_states & (1 << (cstate)))) 217 if (!(lapic_timer_reliable_states & (1 << (cstate))))
228 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); 218 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
229 219
@@ -259,7 +249,7 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
259 */ 249 */
260static int intel_idle_probe(void) 250static int intel_idle_probe(void)
261{ 251{
262 unsigned int eax, ebx, ecx, edx; 252 unsigned int eax, ebx, ecx;
263 253
264 if (max_cstate == 0) { 254 if (max_cstate == 0) {
265 pr_debug(PREFIX "disabled\n"); 255 pr_debug(PREFIX "disabled\n");
@@ -275,20 +265,14 @@ static int intel_idle_probe(void)
275 if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) 265 if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
276 return -ENODEV; 266 return -ENODEV;
277 267
278 cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx); 268 cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
279 269
280 if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || 270 if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
281 !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) 271 !(ecx & CPUID5_ECX_INTERRUPT_BREAK))
282 return -ENODEV; 272 return -ENODEV;
283#ifdef DEBUG
284 if (substates == 0) /* can over-ride via modparam */
285#endif
286 substates = edx;
287 273
288 pr_debug(PREFIX "MWAIT substates: 0x%x\n", substates); 274 pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
289 275
290 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
291 lapic_timer_reliable_states = 0xFFFFFFFF;
292 276
293 if (boot_cpu_data.x86 != 6) /* family 6 */ 277 if (boot_cpu_data.x86 != 6) /* family 6 */
294 return -ENODEV; 278 return -ENODEV;
@@ -299,23 +283,21 @@ static int intel_idle_probe(void)
299 case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ 283 case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */
300 case 0x1F: /* Core i7 and i5 Processor - Nehalem */ 284 case 0x1F: /* Core i7 and i5 Processor - Nehalem */
301 case 0x2E: /* Nehalem-EX Xeon */ 285 case 0x2E: /* Nehalem-EX Xeon */
302 lapic_timer_reliable_states = (1 << 1); /* C1 */ 286 case 0x2F: /* Westmere-EX Xeon */
303
304 case 0x25: /* Westmere */ 287 case 0x25: /* Westmere */
305 case 0x2C: /* Westmere */ 288 case 0x2C: /* Westmere */
306 cpuidle_state_table = nehalem_cstates; 289 cpuidle_state_table = nehalem_cstates;
307 choose_substate = choose_tunable_substate;
308 break; 290 break;
309 291
310 case 0x1C: /* 28 - Atom Processor */ 292 case 0x1C: /* 28 - Atom Processor */
311 lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ 293 case 0x26: /* 38 - Lincroft Atom Processor */
312 cpuidle_state_table = atom_cstates; 294 cpuidle_state_table = atom_cstates;
313 choose_substate = choose_zero_substate;
314 break; 295 break;
315#ifdef FUTURE_USE 296
316 case 0x17: /* 23 - Core 2 Duo */ 297 case 0x2A: /* SNB */
317 lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ 298 case 0x2D: /* SNB Xeon */
318#endif 299 cpuidle_state_table = snb_cstates;
300 break;
319 301
320 default: 302 default:
321 pr_debug(PREFIX "does not run on family %d model %d\n", 303 pr_debug(PREFIX "does not run on family %d model %d\n",
@@ -323,6 +305,9 @@ static int intel_idle_probe(void)
323 return -ENODEV; 305 return -ENODEV;
324 } 306 }
325 307
308 if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
309 lapic_timer_reliable_states = 0xFFFFFFFF;
310
326 pr_debug(PREFIX "v" INTEL_IDLE_VERSION 311 pr_debug(PREFIX "v" INTEL_IDLE_VERSION
327 " model 0x%X\n", boot_cpu_data.x86_model); 312 " model 0x%X\n", boot_cpu_data.x86_model);
328 313
@@ -376,7 +361,7 @@ static int intel_idle_cpuidle_devices_init(void)
376 } 361 }
377 362
378 /* does the state exist in CPUID.MWAIT? */ 363 /* does the state exist in CPUID.MWAIT? */
379 num_substates = (substates >> ((cstate) * 4)) 364 num_substates = (mwait_substates >> ((cstate) * 4))
380 & MWAIT_SUBSTATE_MASK; 365 & MWAIT_SUBSTATE_MASK;
381 if (num_substates == 0) 366 if (num_substates == 0)
382 continue; 367 continue;
@@ -450,11 +435,7 @@ static void __exit intel_idle_exit(void)
450module_init(intel_idle_init); 435module_init(intel_idle_init);
451module_exit(intel_idle_exit); 436module_exit(intel_idle_exit);
452 437
453module_param(power_policy, int, 0644);
454module_param(max_cstate, int, 0444); 438module_param(max_cstate, int, 0444);
455#ifdef DEBUG
456module_param(substates, int, 0444);
457#endif
458 439
459MODULE_AUTHOR("Len Brown <len.brown@intel.com>"); 440MODULE_AUTHOR("Len Brown <len.brown@intel.com>");
460MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION); 441MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION);