diff options
author | Deepthi Dharwar <deepthi@linux.vnet.ibm.com> | 2011-10-28 06:50:42 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-11-06 21:13:58 -0500 |
commit | 46bcfad7a819bd17ac4e831b04405152d59784ab (patch) | |
tree | 20041e788154d103edff2699f88d4a30320e3ee2 /arch/arm/mach-at91/cpuidle.c | |
parent | 4202735e8ab6ecfb0381631a0d0b58fefe0bd4e2 (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 'arch/arm/mach-at91/cpuidle.c')
-rw-r--r-- | arch/arm/mach-at91/cpuidle.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index 4696a0d61e2e..93178f67420e 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c | |||
@@ -33,6 +33,7 @@ static struct cpuidle_driver at91_idle_driver = { | |||
33 | 33 | ||
34 | /* Actual code that puts the SoC in different idle states */ | 34 | /* Actual code that puts the SoC in different idle states */ |
35 | static int at91_enter_idle(struct cpuidle_device *dev, | 35 | static int at91_enter_idle(struct cpuidle_device *dev, |
36 | struct cpuidle_driver *drv, | ||
36 | int index) | 37 | int index) |
37 | { | 38 | { |
38 | struct timeval before, after; | 39 | struct timeval before, after; |
@@ -64,27 +65,29 @@ static int at91_enter_idle(struct cpuidle_device *dev, | |||
64 | static int at91_init_cpuidle(void) | 65 | static int at91_init_cpuidle(void) |
65 | { | 66 | { |
66 | struct cpuidle_device *device; | 67 | struct cpuidle_device *device; |
67 | 68 | struct cpuidle_driver *driver = &at91_idle_driver; | |
68 | cpuidle_register_driver(&at91_idle_driver); | ||
69 | 69 | ||
70 | device = &per_cpu(at91_cpuidle_device, smp_processor_id()); | 70 | device = &per_cpu(at91_cpuidle_device, smp_processor_id()); |
71 | device->state_count = AT91_MAX_STATES; | 71 | device->state_count = AT91_MAX_STATES; |
72 | driver->state_count = AT91_MAX_STATES; | ||
72 | 73 | ||
73 | /* Wait for interrupt state */ | 74 | /* Wait for interrupt state */ |
74 | device->states[0].enter = at91_enter_idle; | 75 | driver->states[0].enter = at91_enter_idle; |
75 | device->states[0].exit_latency = 1; | 76 | driver->states[0].exit_latency = 1; |
76 | device->states[0].target_residency = 10000; | 77 | driver->states[0].target_residency = 10000; |
77 | device->states[0].flags = CPUIDLE_FLAG_TIME_VALID; | 78 | driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; |
78 | strcpy(device->states[0].name, "WFI"); | 79 | strcpy(driver->states[0].name, "WFI"); |
79 | strcpy(device->states[0].desc, "Wait for interrupt"); | 80 | strcpy(driver->states[0].desc, "Wait for interrupt"); |
80 | 81 | ||
81 | /* Wait for interrupt and RAM self refresh state */ | 82 | /* Wait for interrupt and RAM self refresh state */ |
82 | device->states[1].enter = at91_enter_idle; | 83 | driver->states[1].enter = at91_enter_idle; |
83 | device->states[1].exit_latency = 10; | 84 | driver->states[1].exit_latency = 10; |
84 | device->states[1].target_residency = 10000; | 85 | driver->states[1].target_residency = 10000; |
85 | device->states[1].flags = CPUIDLE_FLAG_TIME_VALID; | 86 | driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; |
86 | strcpy(device->states[1].name, "RAM_SR"); | 87 | strcpy(driver->states[1].name, "RAM_SR"); |
87 | strcpy(device->states[1].desc, "WFI and RAM Self Refresh"); | 88 | strcpy(driver->states[1].desc, "WFI and RAM Self Refresh"); |
89 | |||
90 | cpuidle_register_driver(&at91_idle_driver); | ||
88 | 91 | ||
89 | if (cpuidle_register_device(device)) { | 92 | if (cpuidle_register_device(device)) { |
90 | printk(KERN_ERR "at91_init_cpuidle: Failed registering\n"); | 93 | printk(KERN_ERR "at91_init_cpuidle: Failed registering\n"); |