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/sh | |
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/sh')
-rw-r--r-- | arch/sh/kernel/cpu/shmobile/cpuidle.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index 7be50d4c4268..ad1012ad6b42 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c | |||
@@ -25,6 +25,7 @@ static unsigned long cpuidle_mode[] = { | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | static int cpuidle_sleep_enter(struct cpuidle_device *dev, | 27 | static int cpuidle_sleep_enter(struct cpuidle_device *dev, |
28 | struct cpuidle_driver *drv, | ||
28 | int index) | 29 | int index) |
29 | { | 30 | { |
30 | unsigned long allowed_mode = arch_hwblk_sleep_mode(); | 31 | unsigned long allowed_mode = arch_hwblk_sleep_mode(); |
@@ -64,19 +65,19 @@ static struct cpuidle_driver cpuidle_driver = { | |||
64 | void sh_mobile_setup_cpuidle(void) | 65 | void sh_mobile_setup_cpuidle(void) |
65 | { | 66 | { |
66 | struct cpuidle_device *dev = &cpuidle_dev; | 67 | struct cpuidle_device *dev = &cpuidle_dev; |
68 | struct cpuidle_driver *drv = &cpuidle_driver; | ||
67 | struct cpuidle_state *state; | 69 | struct cpuidle_state *state; |
68 | int i; | 70 | int i; |
69 | 71 | ||
70 | cpuidle_register_driver(&cpuidle_driver); | ||
71 | 72 | ||
72 | for (i = 0; i < CPUIDLE_STATE_MAX; i++) { | 73 | for (i = 0; i < CPUIDLE_STATE_MAX; i++) { |
73 | dev->states[i].name[0] = '\0'; | 74 | drv->states[i].name[0] = '\0'; |
74 | dev->states[i].desc[0] = '\0'; | 75 | drv->states[i].desc[0] = '\0'; |
75 | } | 76 | } |
76 | 77 | ||
77 | i = CPUIDLE_DRIVER_STATE_START; | 78 | i = CPUIDLE_DRIVER_STATE_START; |
78 | 79 | ||
79 | state = &dev->states[i++]; | 80 | state = &drv->states[i++]; |
80 | snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); | 81 | snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); |
81 | strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN); | 82 | strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN); |
82 | state->exit_latency = 1; | 83 | state->exit_latency = 1; |
@@ -86,10 +87,10 @@ void sh_mobile_setup_cpuidle(void) | |||
86 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 87 | state->flags |= CPUIDLE_FLAG_TIME_VALID; |
87 | state->enter = cpuidle_sleep_enter; | 88 | state->enter = cpuidle_sleep_enter; |
88 | 89 | ||
89 | dev->safe_state_index = i-1; | 90 | drv->safe_state_index = i-1; |
90 | 91 | ||
91 | if (sh_mobile_sleep_supported & SUSP_SH_SF) { | 92 | if (sh_mobile_sleep_supported & SUSP_SH_SF) { |
92 | state = &dev->states[i++]; | 93 | state = &drv->states[i++]; |
93 | snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); | 94 | snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); |
94 | strncpy(state->desc, "SuperH Sleep Mode [SF]", | 95 | strncpy(state->desc, "SuperH Sleep Mode [SF]", |
95 | CPUIDLE_DESC_LEN); | 96 | CPUIDLE_DESC_LEN); |
@@ -102,7 +103,7 @@ void sh_mobile_setup_cpuidle(void) | |||
102 | } | 103 | } |
103 | 104 | ||
104 | if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) { | 105 | if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) { |
105 | state = &dev->states[i++]; | 106 | state = &drv->states[i++]; |
106 | snprintf(state->name, CPUIDLE_NAME_LEN, "C3"); | 107 | snprintf(state->name, CPUIDLE_NAME_LEN, "C3"); |
107 | strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", | 108 | strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", |
108 | CPUIDLE_DESC_LEN); | 109 | CPUIDLE_DESC_LEN); |
@@ -114,7 +115,10 @@ void sh_mobile_setup_cpuidle(void) | |||
114 | state->enter = cpuidle_sleep_enter; | 115 | state->enter = cpuidle_sleep_enter; |
115 | } | 116 | } |
116 | 117 | ||
118 | drv->state_count = i; | ||
117 | dev->state_count = i; | 119 | dev->state_count = i; |
118 | 120 | ||
121 | cpuidle_register_driver(&cpuidle_driver); | ||
122 | |||
119 | cpuidle_register_device(dev); | 123 | cpuidle_register_device(dev); |
120 | } | 124 | } |