diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-04-08 07:27:40 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-04-08 07:27:40 -0400 |
commit | 8c73c4d8319f38ec1a1fc630a88cbcb79cb1a8f6 (patch) | |
tree | 66bfc4406ddd5d6c4f4526b99536ee54f735d057 /drivers/idle | |
parent | 48edb259863ffa1ab958ffe4eca39d7f1a02e0c0 (diff) | |
parent | 73df623addeaa6154b325b429a6c06eb6ad36004 (diff) |
Merge branch 'pm-cpuidle'
* pm-cpuidle:
cpuidle: sysfs: Export target residency information
intel_idle: fine-tune IVT residency targets
tools/power turbostat: Run on Broadwell
tools/power turbostat: simplify output, add Avg_MHz
intel_idle: Add CPU model 54 (Atom N2000 series)
intel_idle: support Bay Trail
intel_idle: allow sparse sub-state numbering, for Bay Trail
ACPI idle: permit sparse C-state sub-state numbers
Diffstat (limited to 'drivers/idle')
-rw-r--r-- | drivers/idle/intel_idle.c | 204 |
1 files changed, 198 insertions, 6 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 51493ed4643b..a43220c2e3d9 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -196,6 +196,53 @@ static struct cpuidle_state snb_cstates[] = { | |||
196 | .enter = NULL } | 196 | .enter = NULL } |
197 | }; | 197 | }; |
198 | 198 | ||
199 | static struct cpuidle_state byt_cstates[] = { | ||
200 | { | ||
201 | .name = "C1-BYT", | ||
202 | .desc = "MWAIT 0x00", | ||
203 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, | ||
204 | .exit_latency = 1, | ||
205 | .target_residency = 1, | ||
206 | .enter = &intel_idle }, | ||
207 | { | ||
208 | .name = "C1E-BYT", | ||
209 | .desc = "MWAIT 0x01", | ||
210 | .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | ||
211 | .exit_latency = 15, | ||
212 | .target_residency = 30, | ||
213 | .enter = &intel_idle }, | ||
214 | { | ||
215 | .name = "C6N-BYT", | ||
216 | .desc = "MWAIT 0x58", | ||
217 | .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
218 | .exit_latency = 40, | ||
219 | .target_residency = 275, | ||
220 | .enter = &intel_idle }, | ||
221 | { | ||
222 | .name = "C6S-BYT", | ||
223 | .desc = "MWAIT 0x52", | ||
224 | .flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
225 | .exit_latency = 140, | ||
226 | .target_residency = 560, | ||
227 | .enter = &intel_idle }, | ||
228 | { | ||
229 | .name = "C7-BYT", | ||
230 | .desc = "MWAIT 0x60", | ||
231 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
232 | .exit_latency = 1200, | ||
233 | .target_residency = 1500, | ||
234 | .enter = &intel_idle }, | ||
235 | { | ||
236 | .name = "C7S-BYT", | ||
237 | .desc = "MWAIT 0x64", | ||
238 | .flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
239 | .exit_latency = 10000, | ||
240 | .target_residency = 20000, | ||
241 | .enter = &intel_idle }, | ||
242 | { | ||
243 | .enter = NULL } | ||
244 | }; | ||
245 | |||
199 | static struct cpuidle_state ivb_cstates[] = { | 246 | static struct cpuidle_state ivb_cstates[] = { |
200 | { | 247 | { |
201 | .name = "C1-IVB", | 248 | .name = "C1-IVB", |
@@ -236,6 +283,105 @@ static struct cpuidle_state ivb_cstates[] = { | |||
236 | .enter = NULL } | 283 | .enter = NULL } |
237 | }; | 284 | }; |
238 | 285 | ||
286 | static struct cpuidle_state ivt_cstates[] = { | ||
287 | { | ||
288 | .name = "C1-IVT", | ||
289 | .desc = "MWAIT 0x00", | ||
290 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, | ||
291 | .exit_latency = 1, | ||
292 | .target_residency = 1, | ||
293 | .enter = &intel_idle }, | ||
294 | { | ||
295 | .name = "C1E-IVT", | ||
296 | .desc = "MWAIT 0x01", | ||
297 | .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | ||
298 | .exit_latency = 10, | ||
299 | .target_residency = 80, | ||
300 | .enter = &intel_idle }, | ||
301 | { | ||
302 | .name = "C3-IVT", | ||
303 | .desc = "MWAIT 0x10", | ||
304 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
305 | .exit_latency = 59, | ||
306 | .target_residency = 156, | ||
307 | .enter = &intel_idle }, | ||
308 | { | ||
309 | .name = "C6-IVT", | ||
310 | .desc = "MWAIT 0x20", | ||
311 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
312 | .exit_latency = 82, | ||
313 | .target_residency = 300, | ||
314 | .enter = &intel_idle }, | ||
315 | { | ||
316 | .enter = NULL } | ||
317 | }; | ||
318 | |||
319 | static struct cpuidle_state ivt_cstates_4s[] = { | ||
320 | { | ||
321 | .name = "C1-IVT-4S", | ||
322 | .desc = "MWAIT 0x00", | ||
323 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, | ||
324 | .exit_latency = 1, | ||
325 | .target_residency = 1, | ||
326 | .enter = &intel_idle }, | ||
327 | { | ||
328 | .name = "C1E-IVT-4S", | ||
329 | .desc = "MWAIT 0x01", | ||
330 | .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | ||
331 | .exit_latency = 10, | ||
332 | .target_residency = 250, | ||
333 | .enter = &intel_idle }, | ||
334 | { | ||
335 | .name = "C3-IVT-4S", | ||
336 | .desc = "MWAIT 0x10", | ||
337 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
338 | .exit_latency = 59, | ||
339 | .target_residency = 300, | ||
340 | .enter = &intel_idle }, | ||
341 | { | ||
342 | .name = "C6-IVT-4S", | ||
343 | .desc = "MWAIT 0x20", | ||
344 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
345 | .exit_latency = 84, | ||
346 | .target_residency = 400, | ||
347 | .enter = &intel_idle }, | ||
348 | { | ||
349 | .enter = NULL } | ||
350 | }; | ||
351 | |||
352 | static struct cpuidle_state ivt_cstates_8s[] = { | ||
353 | { | ||
354 | .name = "C1-IVT-8S", | ||
355 | .desc = "MWAIT 0x00", | ||
356 | .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, | ||
357 | .exit_latency = 1, | ||
358 | .target_residency = 1, | ||
359 | .enter = &intel_idle }, | ||
360 | { | ||
361 | .name = "C1E-IVT-8S", | ||
362 | .desc = "MWAIT 0x01", | ||
363 | .flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_TIME_VALID, | ||
364 | .exit_latency = 10, | ||
365 | .target_residency = 500, | ||
366 | .enter = &intel_idle }, | ||
367 | { | ||
368 | .name = "C3-IVT-8S", | ||
369 | .desc = "MWAIT 0x10", | ||
370 | .flags = MWAIT2flg(0x10) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
371 | .exit_latency = 59, | ||
372 | .target_residency = 600, | ||
373 | .enter = &intel_idle }, | ||
374 | { | ||
375 | .name = "C6-IVT-8S", | ||
376 | .desc = "MWAIT 0x20", | ||
377 | .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
378 | .exit_latency = 88, | ||
379 | .target_residency = 700, | ||
380 | .enter = &intel_idle }, | ||
381 | { | ||
382 | .enter = NULL } | ||
383 | }; | ||
384 | |||
239 | static struct cpuidle_state hsw_cstates[] = { | 385 | static struct cpuidle_state hsw_cstates[] = { |
240 | { | 386 | { |
241 | .name = "C1-HSW", | 387 | .name = "C1-HSW", |
@@ -464,11 +610,21 @@ static const struct idle_cpu idle_cpu_snb = { | |||
464 | .disable_promotion_to_c1e = true, | 610 | .disable_promotion_to_c1e = true, |
465 | }; | 611 | }; |
466 | 612 | ||
613 | static const struct idle_cpu idle_cpu_byt = { | ||
614 | .state_table = byt_cstates, | ||
615 | .disable_promotion_to_c1e = true, | ||
616 | }; | ||
617 | |||
467 | static const struct idle_cpu idle_cpu_ivb = { | 618 | static const struct idle_cpu idle_cpu_ivb = { |
468 | .state_table = ivb_cstates, | 619 | .state_table = ivb_cstates, |
469 | .disable_promotion_to_c1e = true, | 620 | .disable_promotion_to_c1e = true, |
470 | }; | 621 | }; |
471 | 622 | ||
623 | static const struct idle_cpu idle_cpu_ivt = { | ||
624 | .state_table = ivt_cstates, | ||
625 | .disable_promotion_to_c1e = true, | ||
626 | }; | ||
627 | |||
472 | static const struct idle_cpu idle_cpu_hsw = { | 628 | static const struct idle_cpu idle_cpu_hsw = { |
473 | .state_table = hsw_cstates, | 629 | .state_table = hsw_cstates, |
474 | .disable_promotion_to_c1e = true, | 630 | .disable_promotion_to_c1e = true, |
@@ -494,8 +650,10 @@ static const struct x86_cpu_id intel_idle_ids[] = { | |||
494 | ICPU(0x2f, idle_cpu_nehalem), | 650 | ICPU(0x2f, idle_cpu_nehalem), |
495 | ICPU(0x2a, idle_cpu_snb), | 651 | ICPU(0x2a, idle_cpu_snb), |
496 | ICPU(0x2d, idle_cpu_snb), | 652 | ICPU(0x2d, idle_cpu_snb), |
653 | ICPU(0x36, idle_cpu_atom), | ||
654 | ICPU(0x37, idle_cpu_byt), | ||
497 | ICPU(0x3a, idle_cpu_ivb), | 655 | ICPU(0x3a, idle_cpu_ivb), |
498 | ICPU(0x3e, idle_cpu_ivb), | 656 | ICPU(0x3e, idle_cpu_ivt), |
499 | ICPU(0x3c, idle_cpu_hsw), | 657 | ICPU(0x3c, idle_cpu_hsw), |
500 | ICPU(0x3f, idle_cpu_hsw), | 658 | ICPU(0x3f, idle_cpu_hsw), |
501 | ICPU(0x45, idle_cpu_hsw), | 659 | ICPU(0x45, idle_cpu_hsw), |
@@ -572,6 +730,39 @@ static void intel_idle_cpuidle_devices_uninit(void) | |||
572 | free_percpu(intel_idle_cpuidle_devices); | 730 | free_percpu(intel_idle_cpuidle_devices); |
573 | return; | 731 | return; |
574 | } | 732 | } |
733 | |||
734 | /* | ||
735 | * intel_idle_state_table_update() | ||
736 | * | ||
737 | * Update the default state_table for this CPU-id | ||
738 | * | ||
739 | * Currently used to access tuned IVT multi-socket targets | ||
740 | * Assumption: num_sockets == (max_package_num + 1) | ||
741 | */ | ||
742 | void intel_idle_state_table_update(void) | ||
743 | { | ||
744 | /* IVT uses a different table for 1-2, 3-4, and > 4 sockets */ | ||
745 | if (boot_cpu_data.x86_model == 0x3e) { /* IVT */ | ||
746 | int cpu, package_num, num_sockets = 1; | ||
747 | |||
748 | for_each_online_cpu(cpu) { | ||
749 | package_num = topology_physical_package_id(cpu); | ||
750 | if (package_num + 1 > num_sockets) { | ||
751 | num_sockets = package_num + 1; | ||
752 | |||
753 | if (num_sockets > 4) | ||
754 | cpuidle_state_table = ivt_cstates_8s; | ||
755 | return; | ||
756 | } | ||
757 | } | ||
758 | |||
759 | if (num_sockets > 2) | ||
760 | cpuidle_state_table = ivt_cstates_4s; | ||
761 | /* else, 1 and 2 socket systems use default ivt_cstates */ | ||
762 | } | ||
763 | return; | ||
764 | } | ||
765 | |||
575 | /* | 766 | /* |
576 | * intel_idle_cpuidle_driver_init() | 767 | * intel_idle_cpuidle_driver_init() |
577 | * allocate, initialize cpuidle_states | 768 | * allocate, initialize cpuidle_states |
@@ -581,10 +772,12 @@ static int __init intel_idle_cpuidle_driver_init(void) | |||
581 | int cstate; | 772 | int cstate; |
582 | struct cpuidle_driver *drv = &intel_idle_driver; | 773 | struct cpuidle_driver *drv = &intel_idle_driver; |
583 | 774 | ||
775 | intel_idle_state_table_update(); | ||
776 | |||
584 | drv->state_count = 1; | 777 | drv->state_count = 1; |
585 | 778 | ||
586 | for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { | 779 | for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { |
587 | int num_substates, mwait_hint, mwait_cstate, mwait_substate; | 780 | int num_substates, mwait_hint, mwait_cstate; |
588 | 781 | ||
589 | if (cpuidle_state_table[cstate].enter == NULL) | 782 | if (cpuidle_state_table[cstate].enter == NULL) |
590 | break; | 783 | break; |
@@ -597,14 +790,13 @@ static int __init intel_idle_cpuidle_driver_init(void) | |||
597 | 790 | ||
598 | mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); | 791 | mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags); |
599 | mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint); | 792 | mwait_cstate = MWAIT_HINT2CSTATE(mwait_hint); |
600 | mwait_substate = MWAIT_HINT2SUBSTATE(mwait_hint); | ||
601 | 793 | ||
602 | /* does the state exist in CPUID.MWAIT? */ | 794 | /* number of sub-states for this state in CPUID.MWAIT */ |
603 | num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4)) | 795 | num_substates = (mwait_substates >> ((mwait_cstate + 1) * 4)) |
604 | & MWAIT_SUBSTATE_MASK; | 796 | & MWAIT_SUBSTATE_MASK; |
605 | 797 | ||
606 | /* if sub-state in table is not enumerated by CPUID */ | 798 | /* if NO sub-states for this state in CPUID, skip it */ |
607 | if ((mwait_substate + 1) > num_substates) | 799 | if (num_substates == 0) |
608 | continue; | 800 | continue; |
609 | 801 | ||
610 | if (((mwait_cstate + 1) > 2) && | 802 | if (((mwait_cstate + 1) > 2) && |