diff options
Diffstat (limited to 'drivers/idle/intel_idle.c')
-rwxr-xr-x | drivers/idle/intel_idle.c | 61 |
1 files changed, 7 insertions, 54 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 03d202b1ff27..a10152bb1427 100755 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -77,10 +77,8 @@ static struct cpuidle_driver intel_idle_driver = { | |||
77 | }; | 77 | }; |
78 | /* intel_idle.max_cstate=0 disables driver */ | 78 | /* intel_idle.max_cstate=0 disables driver */ |
79 | static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1; | 79 | static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1; |
80 | static int power_policy = 7; /* 0 = max perf; 15 = max powersave */ | ||
81 | 80 | ||
82 | static unsigned int substates; | 81 | static unsigned int mwait_substates; |
83 | static int (*choose_substate)(int); | ||
84 | 82 | ||
85 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ | 83 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ |
86 | static unsigned int lapic_timer_reliable_states; | 84 | static unsigned int lapic_timer_reliable_states; |
@@ -168,41 +166,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { | |||
168 | .enter = NULL }, /* disabled */ | 166 | .enter = NULL }, /* disabled */ |
169 | }; | 167 | }; |
170 | 168 | ||
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 | */ | ||
179 | static 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 | */ | ||
201 | static int choose_zero_substate(int cstate) | ||
202 | { | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /** | 169 | /** |
207 | * intel_idle | 170 | * intel_idle |
208 | * @dev: cpuidle_device | 171 | * @dev: cpuidle_device |
@@ -220,8 +183,6 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) | |||
220 | 183 | ||
221 | cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; | 184 | cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; |
222 | 185 | ||
223 | eax = eax + (choose_substate)(cstate); | ||
224 | |||
225 | local_irq_disable(); | 186 | local_irq_disable(); |
226 | 187 | ||
227 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) | 188 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) |
@@ -259,7 +220,7 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) | |||
259 | */ | 220 | */ |
260 | static int intel_idle_probe(void) | 221 | static int intel_idle_probe(void) |
261 | { | 222 | { |
262 | unsigned int eax, ebx, ecx, edx; | 223 | unsigned int eax, ebx, ecx; |
263 | 224 | ||
264 | if (max_cstate == 0) { | 225 | if (max_cstate == 0) { |
265 | pr_debug(PREFIX "disabled\n"); | 226 | pr_debug(PREFIX "disabled\n"); |
@@ -275,17 +236,13 @@ static int intel_idle_probe(void) | |||
275 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) | 236 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) |
276 | return -ENODEV; | 237 | return -ENODEV; |
277 | 238 | ||
278 | cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx); | 239 | cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates); |
279 | 240 | ||
280 | if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || | 241 | if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || |
281 | !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) | 242 | !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) |
282 | return -ENODEV; | 243 | return -ENODEV; |
283 | #ifdef DEBUG | ||
284 | if (substates == 0) /* can over-ride via modparam */ | ||
285 | #endif | ||
286 | substates = edx; | ||
287 | 244 | ||
288 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", substates); | 245 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); |
289 | 246 | ||
290 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ | 247 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ |
291 | lapic_timer_reliable_states = 0xFFFFFFFF; | 248 | lapic_timer_reliable_states = 0xFFFFFFFF; |
@@ -299,18 +256,18 @@ static int intel_idle_probe(void) | |||
299 | case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ | 256 | case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ |
300 | case 0x1F: /* Core i7 and i5 Processor - Nehalem */ | 257 | case 0x1F: /* Core i7 and i5 Processor - Nehalem */ |
301 | case 0x2E: /* Nehalem-EX Xeon */ | 258 | case 0x2E: /* Nehalem-EX Xeon */ |
259 | case 0x2F: /* Westmere-EX Xeon */ | ||
302 | lapic_timer_reliable_states = (1 << 1); /* C1 */ | 260 | lapic_timer_reliable_states = (1 << 1); /* C1 */ |
303 | 261 | ||
304 | case 0x25: /* Westmere */ | 262 | case 0x25: /* Westmere */ |
305 | case 0x2C: /* Westmere */ | 263 | case 0x2C: /* Westmere */ |
306 | cpuidle_state_table = nehalem_cstates; | 264 | cpuidle_state_table = nehalem_cstates; |
307 | choose_substate = choose_tunable_substate; | ||
308 | break; | 265 | break; |
309 | 266 | ||
310 | case 0x1C: /* 28 - Atom Processor */ | 267 | case 0x1C: /* 28 - Atom Processor */ |
268 | case 0x26: /* 38 - Lincroft Atom Processor */ | ||
311 | lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ | 269 | lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ |
312 | cpuidle_state_table = atom_cstates; | 270 | cpuidle_state_table = atom_cstates; |
313 | choose_substate = choose_zero_substate; | ||
314 | break; | 271 | break; |
315 | #ifdef FUTURE_USE | 272 | #ifdef FUTURE_USE |
316 | case 0x17: /* 23 - Core 2 Duo */ | 273 | case 0x17: /* 23 - Core 2 Duo */ |
@@ -376,7 +333,7 @@ static int intel_idle_cpuidle_devices_init(void) | |||
376 | } | 333 | } |
377 | 334 | ||
378 | /* does the state exist in CPUID.MWAIT? */ | 335 | /* does the state exist in CPUID.MWAIT? */ |
379 | num_substates = (substates >> ((cstate) * 4)) | 336 | num_substates = (mwait_substates >> ((cstate) * 4)) |
380 | & MWAIT_SUBSTATE_MASK; | 337 | & MWAIT_SUBSTATE_MASK; |
381 | if (num_substates == 0) | 338 | if (num_substates == 0) |
382 | continue; | 339 | continue; |
@@ -450,11 +407,7 @@ static void __exit intel_idle_exit(void) | |||
450 | module_init(intel_idle_init); | 407 | module_init(intel_idle_init); |
451 | module_exit(intel_idle_exit); | 408 | module_exit(intel_idle_exit); |
452 | 409 | ||
453 | module_param(power_policy, int, 0644); | ||
454 | module_param(max_cstate, int, 0444); | 410 | module_param(max_cstate, int, 0444); |
455 | #ifdef DEBUG | ||
456 | module_param(substates, int, 0444); | ||
457 | #endif | ||
458 | 411 | ||
459 | MODULE_AUTHOR("Len Brown <len.brown@intel.com>"); | 412 | MODULE_AUTHOR("Len Brown <len.brown@intel.com>"); |
460 | MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION); | 413 | MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION); |