diff options
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 32 | ||||
-rw-r--r-- | drivers/cpuidle/governors/ladder.c | 13 | ||||
-rw-r--r-- | drivers/cpuidle/governors/menu.c | 7 |
3 files changed, 34 insertions, 18 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d4c542372886..88bd12104396 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -62,7 +62,7 @@ int cpuidle_idle_call(void) | |||
62 | { | 62 | { |
63 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | 63 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); |
64 | struct cpuidle_state *target_state; | 64 | struct cpuidle_state *target_state; |
65 | int next_state; | 65 | int next_state, entered_state; |
66 | 66 | ||
67 | if (off) | 67 | if (off) |
68 | return -ENODEV; | 68 | return -ENODEV; |
@@ -102,26 +102,27 @@ int cpuidle_idle_call(void) | |||
102 | 102 | ||
103 | target_state = &dev->states[next_state]; | 103 | target_state = &dev->states[next_state]; |
104 | 104 | ||
105 | /* enter the state and update stats */ | ||
106 | dev->last_state = target_state; | ||
107 | |||
108 | trace_power_start(POWER_CSTATE, next_state, dev->cpu); | 105 | trace_power_start(POWER_CSTATE, next_state, dev->cpu); |
109 | trace_cpu_idle(next_state, dev->cpu); | 106 | trace_cpu_idle(next_state, dev->cpu); |
110 | 107 | ||
111 | dev->last_residency = target_state->enter(dev, target_state); | 108 | entered_state = target_state->enter(dev, next_state); |
112 | 109 | ||
113 | trace_power_end(dev->cpu); | 110 | trace_power_end(dev->cpu); |
114 | trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); | 111 | trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); |
115 | 112 | ||
116 | if (dev->last_state) | 113 | if (entered_state >= 0) { |
117 | target_state = dev->last_state; | 114 | /* Update cpuidle counters */ |
118 | 115 | /* This can be moved to within driver enter routine | |
119 | target_state->time += (unsigned long long)dev->last_residency; | 116 | * but that results in multiple copies of same code. |
120 | target_state->usage++; | 117 | */ |
118 | dev->states[entered_state].time += | ||
119 | (unsigned long long)dev->last_residency; | ||
120 | dev->states[entered_state].usage++; | ||
121 | } | ||
121 | 122 | ||
122 | /* give the governor an opportunity to reflect on the outcome */ | 123 | /* give the governor an opportunity to reflect on the outcome */ |
123 | if (cpuidle_curr_governor->reflect) | 124 | if (cpuidle_curr_governor->reflect) |
124 | cpuidle_curr_governor->reflect(dev); | 125 | cpuidle_curr_governor->reflect(dev, entered_state); |
125 | 126 | ||
126 | return 0; | 127 | return 0; |
127 | } | 128 | } |
@@ -172,11 +173,10 @@ void cpuidle_resume_and_unlock(void) | |||
172 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); | 173 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); |
173 | 174 | ||
174 | #ifdef CONFIG_ARCH_HAS_CPU_RELAX | 175 | #ifdef CONFIG_ARCH_HAS_CPU_RELAX |
175 | static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st) | 176 | static int poll_idle(struct cpuidle_device *dev, int index) |
176 | { | 177 | { |
177 | ktime_t t1, t2; | 178 | ktime_t t1, t2; |
178 | s64 diff; | 179 | s64 diff; |
179 | int ret; | ||
180 | 180 | ||
181 | t1 = ktime_get(); | 181 | t1 = ktime_get(); |
182 | local_irq_enable(); | 182 | local_irq_enable(); |
@@ -188,8 +188,9 @@ static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st) | |||
188 | if (diff > INT_MAX) | 188 | if (diff > INT_MAX) |
189 | diff = INT_MAX; | 189 | diff = INT_MAX; |
190 | 190 | ||
191 | ret = (int) diff; | 191 | dev->last_residency = (int) diff; |
192 | return ret; | 192 | |
193 | return index; | ||
193 | } | 194 | } |
194 | 195 | ||
195 | static void poll_idle_init(struct cpuidle_device *dev) | 196 | static void poll_idle_init(struct cpuidle_device *dev) |
@@ -248,7 +249,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) | |||
248 | dev->states[i].time = 0; | 249 | dev->states[i].time = 0; |
249 | } | 250 | } |
250 | dev->last_residency = 0; | 251 | dev->last_residency = 0; |
251 | dev->last_state = NULL; | ||
252 | 252 | ||
253 | smp_wmb(); | 253 | smp_wmb(); |
254 | 254 | ||
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 12c98900dcf8..6a686a76711f 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c | |||
@@ -153,11 +153,24 @@ static int ladder_enable_device(struct cpuidle_device *dev) | |||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | /** | ||
157 | * ladder_reflect - update the correct last_state_idx | ||
158 | * @dev: the CPU | ||
159 | * @index: the index of actual state entered | ||
160 | */ | ||
161 | static void ladder_reflect(struct cpuidle_device *dev, int index) | ||
162 | { | ||
163 | struct ladder_device *ldev = &__get_cpu_var(ladder_devices); | ||
164 | if (index > 0) | ||
165 | ldev->last_state_idx = index; | ||
166 | } | ||
167 | |||
156 | static struct cpuidle_governor ladder_governor = { | 168 | static struct cpuidle_governor ladder_governor = { |
157 | .name = "ladder", | 169 | .name = "ladder", |
158 | .rating = 10, | 170 | .rating = 10, |
159 | .enable = ladder_enable_device, | 171 | .enable = ladder_enable_device, |
160 | .select = ladder_select_state, | 172 | .select = ladder_select_state, |
173 | .reflect = ladder_reflect, | ||
161 | .owner = THIS_MODULE, | 174 | .owner = THIS_MODULE, |
162 | }; | 175 | }; |
163 | 176 | ||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index c47f3d09c1ee..e4b200c5b441 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -310,14 +310,17 @@ static int menu_select(struct cpuidle_device *dev) | |||
310 | /** | 310 | /** |
311 | * menu_reflect - records that data structures need update | 311 | * menu_reflect - records that data structures need update |
312 | * @dev: the CPU | 312 | * @dev: the CPU |
313 | * @index: the index of actual entered state | ||
313 | * | 314 | * |
314 | * NOTE: it's important to be fast here because this operation will add to | 315 | * NOTE: it's important to be fast here because this operation will add to |
315 | * the overall exit latency. | 316 | * the overall exit latency. |
316 | */ | 317 | */ |
317 | static void menu_reflect(struct cpuidle_device *dev) | 318 | static void menu_reflect(struct cpuidle_device *dev, int index) |
318 | { | 319 | { |
319 | struct menu_device *data = &__get_cpu_var(menu_devices); | 320 | struct menu_device *data = &__get_cpu_var(menu_devices); |
320 | data->needs_update = 1; | 321 | data->last_state_idx = index; |
322 | if (index >= 0) | ||
323 | data->needs_update = 1; | ||
321 | } | 324 | } |
322 | 325 | ||
323 | /** | 326 | /** |