aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/idle
diff options
context:
space:
mode:
authorDeepthi Dharwar <deepthi@linux.vnet.ibm.com>2011-10-28 06:50:42 -0400
committerLen Brown <len.brown@intel.com>2011-11-06 21:13:58 -0500
commit46bcfad7a819bd17ac4e831b04405152d59784ab (patch)
tree20041e788154d103edff2699f88d4a30320e3ee2 /drivers/idle
parent4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2 (diff)
cpuidle: Single/Global registration of idle states
This patch makes the cpuidle_states structure global (single copy) instead of per-cpu. The statistics needed on per-cpu basis by the governor are kept per-cpu. This simplifies the cpuidle subsystem as state registration is done by single cpu only. Having single copy of cpuidle_states saves memory. Rare case of asymmetric C-states can be handled within the cpuidle driver and architectures such as POWER do not have asymmetric C-states. Having single/global registration of all the idle states, dynamic C-state transitions on x86 are handled by the boot cpu. Here, the boot cpu would disable all the devices, re-populate the states and later enable all the devices, irrespective of the cpu that would receive the notification first. Reference: https://lkml.org/lkml/2011/4/25/83 Signed-off-by: Deepthi Dharwar <deepthi@linux.vnet.ibm.com> Signed-off-by: Trinabh Gupta <g.trinabh@gmail.com> Tested-by: Jean Pihet <j-pihet@ti.com> Reviewed-by: Kevin Hilman <khilman@ti.com> Acked-by: Arjan van de Ven <arjan@linux.intel.com> Acked-by: Kevin Hilman <khilman@ti.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/idle')
-rw-r--r--drivers/idle/intel_idle.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 3aa8d4cb6dca..5be9d599ff6b 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -81,7 +81,8 @@ static unsigned int mwait_substates;
81static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ 81static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */
82 82
83static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; 83static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
84static int intel_idle(struct cpuidle_device *dev, int index); 84static int intel_idle(struct cpuidle_device *dev,
85 struct cpuidle_driver *drv, int index);
85 86
86static struct cpuidle_state *cpuidle_state_table; 87static struct cpuidle_state *cpuidle_state_table;
87 88
@@ -227,13 +228,15 @@ static int get_driver_data(int cstate)
227/** 228/**
228 * intel_idle 229 * intel_idle
229 * @dev: cpuidle_device 230 * @dev: cpuidle_device
231 * @drv: cpuidle driver
230 * @index: index of cpuidle state 232 * @index: index of cpuidle state
231 * 233 *
232 */ 234 */
233static int intel_idle(struct cpuidle_device *dev, int index) 235static int intel_idle(struct cpuidle_device *dev,
236 struct cpuidle_driver *drv, int index)
234{ 237{
235 unsigned long ecx = 1; /* break on interrupt flag */ 238 unsigned long ecx = 1; /* break on interrupt flag */
236 struct cpuidle_state *state = &dev->states[index]; 239 struct cpuidle_state *state = &drv->states[index];
237 struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; 240 struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
238 unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage); 241 unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
239 unsigned int cstate; 242 unsigned int cstate;
@@ -420,6 +423,60 @@ static void intel_idle_cpuidle_devices_uninit(void)
420 return; 423 return;
421} 424}
422/* 425/*
426 * intel_idle_cpuidle_driver_init()
427 * allocate, initialize cpuidle_states
428 */
429static int intel_idle_cpuidle_driver_init(void)
430{
431 int cstate;
432 struct cpuidle_driver *drv = &intel_idle_driver;
433
434 drv->state_count = 1;
435
436 for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) {
437 int num_substates;
438
439 if (cstate > max_cstate) {
440 printk(PREFIX "max_cstate %d reached\n",
441 max_cstate);
442 break;
443 }
444
445 /* does the state exist in CPUID.MWAIT? */
446 num_substates = (mwait_substates >> ((cstate) * 4))
447 & MWAIT_SUBSTATE_MASK;
448 if (num_substates == 0)
449 continue;
450 /* is the state not enabled? */
451 if (cpuidle_state_table[cstate].enter == NULL) {
452 /* does the driver not know about the state? */
453 if (*cpuidle_state_table[cstate].name == '\0')
454 pr_debug(PREFIX "unaware of model 0x%x"
455 " MWAIT %d please"
456 " contact lenb@kernel.org",
457 boot_cpu_data.x86_model, cstate);
458 continue;
459 }
460
461 if ((cstate > 2) &&
462 !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
463 mark_tsc_unstable("TSC halts in idle"
464 " states deeper than C2");
465
466 drv->states[drv->state_count] = /* structure copy */
467 cpuidle_state_table[cstate];
468
469 drv->state_count += 1;
470 }
471
472 if (auto_demotion_disable_flags)
473 smp_call_function(auto_demotion_disable, NULL, 1);
474
475 return 0;
476}
477
478
479/*
423 * intel_idle_cpuidle_devices_init() 480 * intel_idle_cpuidle_devices_init()
424 * allocate, initialize, register cpuidle_devices 481 * allocate, initialize, register cpuidle_devices
425 */ 482 */
@@ -453,23 +510,9 @@ static int intel_idle_cpuidle_devices_init(void)
453 continue; 510 continue;
454 /* is the state not enabled? */ 511 /* is the state not enabled? */
455 if (cpuidle_state_table[cstate].enter == NULL) { 512 if (cpuidle_state_table[cstate].enter == NULL) {
456 /* does the driver not know about the state? */
457 if (*cpuidle_state_table[cstate].name == '\0')
458 pr_debug(PREFIX "unaware of model 0x%x"
459 " MWAIT %d please"
460 " contact lenb@kernel.org",
461 boot_cpu_data.x86_model, cstate);
462 continue; 513 continue;
463 } 514 }
464 515
465 if ((cstate > 2) &&
466 !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
467 mark_tsc_unstable("TSC halts in idle"
468 " states deeper than C2");
469
470 dev->states[dev->state_count] = /* structure copy */
471 cpuidle_state_table[cstate];
472
473 dev->states_usage[dev->state_count].driver_data = 516 dev->states_usage[dev->state_count].driver_data =
474 (void *)get_driver_data(cstate); 517 (void *)get_driver_data(cstate);
475 518
@@ -484,8 +527,6 @@ static int intel_idle_cpuidle_devices_init(void)
484 return -EIO; 527 return -EIO;
485 } 528 }
486 } 529 }
487 if (auto_demotion_disable_flags)
488 smp_call_function(auto_demotion_disable, NULL, 1);
489 530
490 return 0; 531 return 0;
491} 532}
@@ -503,6 +544,7 @@ static int __init intel_idle_init(void)
503 if (retval) 544 if (retval)
504 return retval; 545 return retval;
505 546
547 intel_idle_cpuidle_driver_init();
506 retval = cpuidle_register_driver(&intel_idle_driver); 548 retval = cpuidle_register_driver(&intel_idle_driver);
507 if (retval) { 549 if (retval) {
508 printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", 550 printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",