aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
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
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')
-rw-r--r--arch/arm/mach-at91/cpuidle.c10
-rw-r--r--arch/arm/mach-davinci/cpuidle.c9
-rw-r--r--arch/arm/mach-exynos4/cpuidle.c7
-rw-r--r--arch/arm/mach-kirkwood/cpuidle.c12
-rw-r--r--arch/arm/mach-omap2/cpuidle34xx.c67
5 files changed, 63 insertions, 42 deletions
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c
index 1cfeac1483d6..4696a0d61e2e 100644
--- a/arch/arm/mach-at91/cpuidle.c
+++ b/arch/arm/mach-at91/cpuidle.c
@@ -33,7 +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 */
35static int at91_enter_idle(struct cpuidle_device *dev, 35static int at91_enter_idle(struct cpuidle_device *dev,
36 struct cpuidle_state *state) 36 int index)
37{ 37{
38 struct timeval before, after; 38 struct timeval before, after;
39 int idle_time; 39 int idle_time;
@@ -41,10 +41,10 @@ static int at91_enter_idle(struct cpuidle_device *dev,
41 41
42 local_irq_disable(); 42 local_irq_disable();
43 do_gettimeofday(&before); 43 do_gettimeofday(&before);
44 if (state == &dev->states[0]) 44 if (index == 0)
45 /* Wait for interrupt state */ 45 /* Wait for interrupt state */
46 cpu_do_idle(); 46 cpu_do_idle();
47 else if (state == &dev->states[1]) { 47 else if (index == 1) {
48 asm("b 1f; .align 5; 1:"); 48 asm("b 1f; .align 5; 1:");
49 asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ 49 asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */
50 saved_lpr = sdram_selfrefresh_enable(); 50 saved_lpr = sdram_selfrefresh_enable();
@@ -55,7 +55,9 @@ static int at91_enter_idle(struct cpuidle_device *dev,
55 local_irq_enable(); 55 local_irq_enable();
56 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + 56 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
57 (after.tv_usec - before.tv_usec); 57 (after.tv_usec - before.tv_usec);
58 return idle_time; 58
59 dev->last_residency = idle_time;
60 return index;
59} 61}
60 62
61/* Initialize CPU idle by registering the idle states */ 63/* Initialize CPU idle by registering the idle states */
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index bd59f31b8a95..ca8582a95ad9 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -78,9 +78,9 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = {
78 78
79/* Actual code that puts the SoC in different idle states */ 79/* Actual code that puts the SoC in different idle states */
80static int davinci_enter_idle(struct cpuidle_device *dev, 80static int davinci_enter_idle(struct cpuidle_device *dev,
81 struct cpuidle_state *state) 81 int index)
82{ 82{
83 struct davinci_ops *ops = cpuidle_get_statedata(state); 83 struct davinci_ops *ops = cpuidle_get_statedata(&dev->states[index]);
84 struct timeval before, after; 84 struct timeval before, after;
85 int idle_time; 85 int idle_time;
86 86
@@ -98,7 +98,10 @@ static int davinci_enter_idle(struct cpuidle_device *dev,
98 local_irq_enable(); 98 local_irq_enable();
99 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + 99 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
100 (after.tv_usec - before.tv_usec); 100 (after.tv_usec - before.tv_usec);
101 return idle_time; 101
102 dev->last_residency = idle_time;
103
104 return index;
102} 105}
103 106
104static int __init davinci_cpuidle_probe(struct platform_device *pdev) 107static int __init davinci_cpuidle_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-exynos4/cpuidle.c b/arch/arm/mach-exynos4/cpuidle.c
index bf7e96f2793a..ea026e72b977 100644
--- a/arch/arm/mach-exynos4/cpuidle.c
+++ b/arch/arm/mach-exynos4/cpuidle.c
@@ -16,7 +16,7 @@
16#include <asm/proc-fns.h> 16#include <asm/proc-fns.h>
17 17
18static int exynos4_enter_idle(struct cpuidle_device *dev, 18static int exynos4_enter_idle(struct cpuidle_device *dev,
19 struct cpuidle_state *state); 19 int index);
20 20
21static struct cpuidle_state exynos4_cpuidle_set[] = { 21static struct cpuidle_state exynos4_cpuidle_set[] = {
22 [0] = { 22 [0] = {
@@ -37,7 +37,7 @@ static struct cpuidle_driver exynos4_idle_driver = {
37}; 37};
38 38
39static int exynos4_enter_idle(struct cpuidle_device *dev, 39static int exynos4_enter_idle(struct cpuidle_device *dev,
40 struct cpuidle_state *state) 40 int index)
41{ 41{
42 struct timeval before, after; 42 struct timeval before, after;
43 int idle_time; 43 int idle_time;
@@ -52,7 +52,8 @@ static int exynos4_enter_idle(struct cpuidle_device *dev,
52 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + 52 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
53 (after.tv_usec - before.tv_usec); 53 (after.tv_usec - before.tv_usec);
54 54
55 return idle_time; 55 dev->last_residency = idle_time;
56 return index;
56} 57}
57 58
58static int __init exynos4_init_cpuidle(void) 59static int __init exynos4_init_cpuidle(void)
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c
index f68d33f1f396..358dd80b3a07 100644
--- a/arch/arm/mach-kirkwood/cpuidle.c
+++ b/arch/arm/mach-kirkwood/cpuidle.c
@@ -32,17 +32,17 @@ static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
32 32
33/* Actual code that puts the SoC in different idle states */ 33/* Actual code that puts the SoC in different idle states */
34static int kirkwood_enter_idle(struct cpuidle_device *dev, 34static int kirkwood_enter_idle(struct cpuidle_device *dev,
35 struct cpuidle_state *state) 35 int index)
36{ 36{
37 struct timeval before, after; 37 struct timeval before, after;
38 int idle_time; 38 int idle_time;
39 39
40 local_irq_disable(); 40 local_irq_disable();
41 do_gettimeofday(&before); 41 do_gettimeofday(&before);
42 if (state == &dev->states[0]) 42 if (index == 0)
43 /* Wait for interrupt state */ 43 /* Wait for interrupt state */
44 cpu_do_idle(); 44 cpu_do_idle();
45 else if (state == &dev->states[1]) { 45 else if (index == 1) {
46 /* 46 /*
47 * Following write will put DDR in self refresh. 47 * Following write will put DDR in self refresh.
48 * Note that we have 256 cycles before DDR puts it 48 * Note that we have 256 cycles before DDR puts it
@@ -57,7 +57,11 @@ static int kirkwood_enter_idle(struct cpuidle_device *dev,
57 local_irq_enable(); 57 local_irq_enable();
58 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + 58 idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
59 (after.tv_usec - before.tv_usec); 59 (after.tv_usec - before.tv_usec);
60 return idle_time; 60
61 /* Update last residency */
62 dev->last_residency = idle_time;
63
64 return index;
61} 65}
62 66
63/* Initialize CPU idle by registering the idle states */ 67/* Initialize CPU idle by registering the idle states */
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;