diff options
| -rw-r--r-- | drivers/idle/intel_idle.c | 141 |
1 files changed, 140 insertions, 1 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 710ab54ab04b..9ddbf550bafa 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
| @@ -283,6 +283,105 @@ static struct cpuidle_state ivb_cstates[] = { | |||
| 283 | .enter = NULL } | 283 | .enter = NULL } |
| 284 | }; | 284 | }; |
| 285 | 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 | |||
| 286 | static struct cpuidle_state hsw_cstates[] = { | 385 | static struct cpuidle_state hsw_cstates[] = { |
| 287 | { | 386 | { |
| 288 | .name = "C1-HSW", | 387 | .name = "C1-HSW", |
| @@ -521,6 +620,11 @@ static const struct idle_cpu idle_cpu_ivb = { | |||
| 521 | .disable_promotion_to_c1e = true, | 620 | .disable_promotion_to_c1e = true, |
| 522 | }; | 621 | }; |
| 523 | 622 | ||
| 623 | static const struct idle_cpu idle_cpu_ivt = { | ||
| 624 | .state_table = ivt_cstates, | ||
| 625 | .disable_promotion_to_c1e = true, | ||
| 626 | }; | ||
| 627 | |||
| 524 | static const struct idle_cpu idle_cpu_hsw = { | 628 | static const struct idle_cpu idle_cpu_hsw = { |
| 525 | .state_table = hsw_cstates, | 629 | .state_table = hsw_cstates, |
| 526 | .disable_promotion_to_c1e = true, | 630 | .disable_promotion_to_c1e = true, |
| @@ -549,7 +653,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { | |||
| 549 | ICPU(0x36, idle_cpu_atom), | 653 | ICPU(0x36, idle_cpu_atom), |
| 550 | ICPU(0x37, idle_cpu_byt), | 654 | ICPU(0x37, idle_cpu_byt), |
| 551 | ICPU(0x3a, idle_cpu_ivb), | 655 | ICPU(0x3a, idle_cpu_ivb), |
| 552 | ICPU(0x3e, idle_cpu_ivb), | 656 | ICPU(0x3e, idle_cpu_ivt), |
| 553 | ICPU(0x3c, idle_cpu_hsw), | 657 | ICPU(0x3c, idle_cpu_hsw), |
| 554 | ICPU(0x3f, idle_cpu_hsw), | 658 | ICPU(0x3f, idle_cpu_hsw), |
| 555 | ICPU(0x45, idle_cpu_hsw), | 659 | ICPU(0x45, idle_cpu_hsw), |
| @@ -626,6 +730,39 @@ static void intel_idle_cpuidle_devices_uninit(void) | |||
| 626 | free_percpu(intel_idle_cpuidle_devices); | 730 | free_percpu(intel_idle_cpuidle_devices); |
| 627 | return; | 731 | return; |
| 628 | } | 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 | |||
| 629 | /* | 766 | /* |
| 630 | * intel_idle_cpuidle_driver_init() | 767 | * intel_idle_cpuidle_driver_init() |
| 631 | * allocate, initialize cpuidle_states | 768 | * allocate, initialize cpuidle_states |
| @@ -635,6 +772,8 @@ static int __init intel_idle_cpuidle_driver_init(void) | |||
| 635 | int cstate; | 772 | int cstate; |
| 636 | struct cpuidle_driver *drv = &intel_idle_driver; | 773 | struct cpuidle_driver *drv = &intel_idle_driver; |
| 637 | 774 | ||
| 775 | intel_idle_state_table_update(); | ||
| 776 | |||
| 638 | drv->state_count = 1; | 777 | drv->state_count = 1; |
| 639 | 778 | ||
| 640 | for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { | 779 | for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) { |
