aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/cpuidle34xx.c
diff options
context:
space:
mode:
authorDeepthi Dharwar <deepthi@linux.vnet.ibm.com>2011-10-28 06:50:09 -0400
committerLen Brown <len.brown@intel.com>2011-11-06 21:13:30 -0500
commite978aa7d7d57d04eb5f88a7507c4fb98577def77 (patch)
treed6d6dfe1dba4d4749c7eafe348351aa499c3c5eb /arch/arm/mach-omap2/cpuidle34xx.c
parentc3b92c8787367a8bb53d57d9789b558f1295cc96 (diff)
cpuidle: Move dev->last_residency update to driver enter routine; remove dev->last_state
Cpuidle governor only suggests the state to enter using the governor->select() interface, but allows the low level driver to override the recommended state. The actual entered state may be different because of software or hardware demotion. Software demotion is done by the back-end cpuidle driver and can be accounted correctly. Current cpuidle code uses last_state field to capture the actual state entered and based on that updates the statistics for the state entered. Ideally the driver enter routine should update the counters, and it should return the state actually entered rather than the time spent there. The generic cpuidle code should simply handle where the counters live in the sysfs namespace, not updating the counters. Reference: https://lkml.org/lkml/2011/3/25/52 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-omap2/cpuidle34xx.c')
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 4bf6e6e8b100..58425c75f1b8 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -88,17 +88,19 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
88/** 88/**
89 * omap3_enter_idle - Programs OMAP3 to enter the specified state 89 * omap3_enter_idle - Programs OMAP3 to enter the specified state
90 * @dev: cpuidle device 90 * @dev: cpuidle device
91 * @state: The target state to be programmed 91 * @index: the index of state to be entered
92 * 92 *
93 * Called from the CPUidle framework to program the device to the 93 * Called from the CPUidle framework to program the device to the
94 * specified target state selected by the governor. 94 * specified target state selected by the governor.
95 */ 95 */
96static int omap3_enter_idle(struct cpuidle_device *dev, 96static int omap3_enter_idle(struct cpuidle_device *dev,
97 struct cpuidle_state *state) 97 int index)
98{ 98{
99 struct omap3_idle_statedata *cx = cpuidle_get_statedata(state); 99 struct omap3_idle_statedata *cx =
100 cpuidle_get_statedata(&dev->states[index]);
100 struct timespec ts_preidle, ts_postidle, ts_idle; 101 struct timespec ts_preidle, ts_postidle, ts_idle;
101 u32 mpu_state = cx->mpu_state, core_state = cx->core_state; 102 u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
103 int idle_time;
102 104
103 /* Used to keep track of the total time in idle */ 105 /* Used to keep track of the total time in idle */
104 getnstimeofday(&ts_preidle); 106 getnstimeofday(&ts_preidle);
@@ -113,7 +115,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
113 goto return_sleep_time; 115 goto return_sleep_time;
114 116
115 /* Deny idle for C1 */ 117 /* Deny idle for C1 */
116 if (state == &dev->states[0]) { 118 if (index == 0) {
117 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle); 119 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
118 pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle); 120 pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
119 } 121 }
@@ -122,7 +124,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
122 omap_sram_idle(); 124 omap_sram_idle();
123 125
124 /* Re-allow idle for C1 */ 126 /* Re-allow idle for C1 */
125 if (state == &dev->states[0]) { 127 if (index == 0) {
126 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle); 128 pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
127 pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle); 129 pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
128 } 130 }
@@ -134,28 +136,35 @@ return_sleep_time:
134 local_irq_enable(); 136 local_irq_enable();
135 local_fiq_enable(); 137 local_fiq_enable();
136 138
137 return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC; 139 idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \
140 USEC_PER_SEC;
141
142 /* Update cpuidle counters */
143 dev->last_residency = idle_time;
144
145 return index;
138} 146}
139 147
140/** 148/**
141 * next_valid_state - Find next valid C-state 149 * next_valid_state - Find next valid C-state
142 * @dev: cpuidle device 150 * @dev: cpuidle device
143 * @state: Currently selected C-state 151 * @index: Index of currently selected c-state
144 * 152 *
145 * If the current state is valid, it is returned back to the caller. 153 * If the state corresponding to index is valid, index is returned back
146 * Else, this function searches for a lower c-state which is still 154 * to the caller. Else, this function searches for a lower c-state which is
147 * valid. 155 * still valid (as defined in omap3_power_states[]) and returns its index.
148 * 156 *
149 * A state is valid if the 'valid' field is enabled and 157 * A state is valid if the 'valid' field is enabled and
150 * if it satisfies the enable_off_mode condition. 158 * if it satisfies the enable_off_mode condition.
151 */ 159 */
152static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev, 160static int next_valid_state(struct cpuidle_device *dev,
153 struct cpuidle_state *curr) 161 int index)
154{ 162{
155 struct cpuidle_state *next = NULL; 163 struct cpuidle_state *curr = &dev->states[index];
156 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr); 164 struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr);
157 u32 mpu_deepest_state = PWRDM_POWER_RET; 165 u32 mpu_deepest_state = PWRDM_POWER_RET;
158 u32 core_deepest_state = PWRDM_POWER_RET; 166 u32 core_deepest_state = PWRDM_POWER_RET;
167 int next_index = -1;
159 168
160 if (enable_off_mode) { 169 if (enable_off_mode) {
161 mpu_deepest_state = PWRDM_POWER_OFF; 170 mpu_deepest_state = PWRDM_POWER_OFF;
@@ -172,20 +181,20 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
172 if ((cx->valid) && 181 if ((cx->valid) &&
173 (cx->mpu_state >= mpu_deepest_state) && 182 (cx->mpu_state >= mpu_deepest_state) &&
174 (cx->core_state >= core_deepest_state)) { 183 (cx->core_state >= core_deepest_state)) {
175 return curr; 184 return index;
176 } else { 185 } else {
177 int idx = OMAP3_NUM_STATES - 1; 186 int idx = OMAP3_NUM_STATES - 1;
178 187
179 /* Reach the current state starting at highest C-state */ 188 /* Reach the current state starting at highest C-state */
180 for (; idx >= 0; idx--) { 189 for (; idx >= 0; idx--) {
181 if (&dev->states[idx] == curr) { 190 if (&dev->states[idx] == curr) {
182 next = &dev->states[idx]; 191 next_index = idx;
183 break; 192 break;
184 } 193 }
185 } 194 }
186 195
187 /* Should never hit this condition */ 196 /* Should never hit this condition */
188 WARN_ON(next == NULL); 197 WARN_ON(next_index == -1);
189 198
190 /* 199 /*
191 * Drop to next valid state. 200 * Drop to next valid state.
@@ -197,37 +206,39 @@ static struct cpuidle_state *next_valid_state(struct cpuidle_device *dev,
197 if ((cx->valid) && 206 if ((cx->valid) &&
198 (cx->mpu_state >= mpu_deepest_state) && 207 (cx->mpu_state >= mpu_deepest_state) &&
199 (cx->core_state >= core_deepest_state)) { 208 (cx->core_state >= core_deepest_state)) {
200 next = &dev->states[idx]; 209 next_index = idx;
201 break; 210 break;
202 } 211 }
203 } 212 }
204 /* 213 /*
205 * C1 is always valid. 214 * C1 is always valid.
206 * So, no need to check for 'next==NULL' outside this loop. 215 * So, no need to check for 'next_index == -1' outside
216 * this loop.
207 */ 217 */
208 } 218 }
209 219
210 return next; 220 return next_index;
211} 221}
212 222
213/** 223/**
214 * omap3_enter_idle_bm - Checks for any bus activity 224 * omap3_enter_idle_bm - Checks for any bus activity
215 * @dev: cpuidle device 225 * @dev: cpuidle device
216 * @state: The target state to be programmed 226 * @index: array index of target state to be programmed
217 * 227 *
218 * This function checks for any pending activity and then programs 228 * This function checks for any pending activity and then programs
219 * the device to the specified or a safer state. 229 * the device to the specified or a safer state.
220 */ 230 */
221static int omap3_enter_idle_bm(struct cpuidle_device *dev, 231static int omap3_enter_idle_bm(struct cpuidle_device *dev,
222 struct cpuidle_state *state) 232 int index)
223{ 233{
224 struct cpuidle_state *new_state; 234 struct cpuidle_state *state = &dev->states[index];
235 int new_state_idx;
225 u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state; 236 u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
226 struct omap3_idle_statedata *cx; 237 struct omap3_idle_statedata *cx;
227 int ret; 238 int ret;
228 239
229 if (!omap3_can_sleep()) { 240 if (!omap3_can_sleep()) {
230 new_state = dev->safe_state; 241 new_state_idx = dev->safe_state_index;
231 goto select_state; 242 goto select_state;
232 } 243 }
233 244
@@ -237,7 +248,7 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
237 */ 248 */
238 cam_state = pwrdm_read_pwrst(cam_pd); 249 cam_state = pwrdm_read_pwrst(cam_pd);
239 if (cam_state == PWRDM_POWER_ON) { 250 if (cam_state == PWRDM_POWER_ON) {
240 new_state = dev->safe_state; 251 new_state_idx = dev->safe_state_index;
241 goto select_state; 252 goto select_state;
242 } 253 }
243 254
@@ -264,11 +275,10 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
264 if (per_next_state != per_saved_state) 275 if (per_next_state != per_saved_state)
265 pwrdm_set_next_pwrst(per_pd, per_next_state); 276 pwrdm_set_next_pwrst(per_pd, per_next_state);
266 277
267 new_state = next_valid_state(dev, state); 278 new_state_idx = next_valid_state(dev, index);
268 279
269select_state: 280select_state:
270 dev->last_state = new_state; 281 ret = omap3_enter_idle(dev, new_state_idx);
271 ret = omap3_enter_idle(dev, new_state);
272 282
273 /* Restore original PER state if it was modified */ 283 /* Restore original PER state if it was modified */
274 if (per_next_state != per_saved_state) 284 if (per_next_state != per_saved_state)
@@ -339,11 +349,12 @@ int __init omap3_idle_init(void)
339 349
340 cpuidle_register_driver(&omap3_idle_driver); 350 cpuidle_register_driver(&omap3_idle_driver);
341 dev = &per_cpu(omap3_idle_dev, smp_processor_id()); 351 dev = &per_cpu(omap3_idle_dev, smp_processor_id());
352 dev->safe_state_index = -1;
342 353
343 /* C1 . MPU WFI + Core active */ 354 /* C1 . MPU WFI + Core active */
344 cx = _fill_cstate(dev, 0, "MPU ON + CORE ON"); 355 cx = _fill_cstate(dev, 0, "MPU ON + CORE ON");
345 (&dev->states[0])->enter = omap3_enter_idle; 356 (&dev->states[0])->enter = omap3_enter_idle;
346 dev->safe_state = &dev->states[0]; 357 dev->safe_state_index = 0;
347 cx->valid = 1; /* C1 is always valid */ 358 cx->valid = 1; /* C1 is always valid */
348 cx->mpu_state = PWRDM_POWER_ON; 359 cx->mpu_state = PWRDM_POWER_ON;
349 cx->core_state = PWRDM_POWER_ON; 360 cx->core_state = PWRDM_POWER_ON;