diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/cpuidle/sysfs.c | 3 | ||||
| -rw-r--r-- | drivers/idle/intel_idle.c | 204 |
2 files changed, 201 insertions, 6 deletions
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index e918b6d0caf7..efe2f175168f 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
| @@ -293,6 +293,7 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ | |||
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | define_show_state_function(exit_latency) | 295 | define_show_state_function(exit_latency) |
| 296 | define_show_state_function(target_residency) | ||
| 296 | define_show_state_function(power_usage) | 297 | define_show_state_function(power_usage) |
| 297 | define_show_state_ull_function(usage) | 298 | define_show_state_ull_function(usage) |
| 298 | define_show_state_ull_function(time) | 299 | define_show_state_ull_function(time) |
| @@ -304,6 +305,7 @@ define_store_state_ull_function(disable) | |||
| 304 | define_one_state_ro(name, show_state_name); | 305 | define_one_state_ro(name, show_state_name); |
| 305 | define_one_state_ro(desc, show_state_desc); | 306 | define_one_state_ro(desc, show_state_desc); |
| 306 | define_one_state_ro(latency, show_state_exit_latency); | 307 | define_one_state_ro(latency, show_state_exit_latency); |
| 308 | define_one_state_ro(residency, show_state_target_residency); | ||
| 307 | define_one_state_ro(power, show_state_power_usage); | 309 | define_one_state_ro(power, show_state_power_usage); |
| 308 | define_one_state_ro(usage, show_state_usage); | 310 | define_one_state_ro(usage, show_state_usage); |
| 309 | define_one_state_ro(time, show_state_time); | 311 | define_one_state_ro(time, show_state_time); |
| @@ -313,6 +315,7 @@ static struct attribute *cpuidle_state_default_attrs[] = { | |||
| 313 | &attr_name.attr, | 315 | &attr_name.attr, |
| 314 | &attr_desc.attr, | 316 | &attr_desc.attr, |
| 315 | &attr_latency.attr, | 317 | &attr_latency.attr, |
| 318 | &attr_residency.attr, | ||
| 316 | &attr_power.attr, | 319 | &attr_power.attr, |
| 317 | &attr_usage.attr, | 320 | &attr_usage.attr, |
| 318 | &attr_time.attr, | 321 | &attr_time.attr, |
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) && |
