diff options
Diffstat (limited to 'drivers/cpuidle/driver.c')
-rw-r--r-- | drivers/cpuidle/driver.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 2458a741ad45..06dbe7c86199 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/mutex.h> | 11 | #include <linux/mutex.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sched.h> | ||
13 | #include <linux/cpuidle.h> | 14 | #include <linux/cpuidle.h> |
14 | #include <linux/cpumask.h> | 15 | #include <linux/cpumask.h> |
15 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
@@ -177,6 +178,45 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) | |||
177 | } | 178 | } |
178 | } | 179 | } |
179 | 180 | ||
181 | #ifdef CONFIG_ARCH_HAS_CPU_RELAX | ||
182 | static int poll_idle(struct cpuidle_device *dev, | ||
183 | struct cpuidle_driver *drv, int index) | ||
184 | { | ||
185 | ktime_t t1, t2; | ||
186 | s64 diff; | ||
187 | |||
188 | t1 = ktime_get(); | ||
189 | local_irq_enable(); | ||
190 | while (!need_resched()) | ||
191 | cpu_relax(); | ||
192 | |||
193 | t2 = ktime_get(); | ||
194 | diff = ktime_to_us(ktime_sub(t2, t1)); | ||
195 | if (diff > INT_MAX) | ||
196 | diff = INT_MAX; | ||
197 | |||
198 | dev->last_residency = (int) diff; | ||
199 | |||
200 | return index; | ||
201 | } | ||
202 | |||
203 | static void poll_idle_init(struct cpuidle_driver *drv) | ||
204 | { | ||
205 | struct cpuidle_state *state = &drv->states[0]; | ||
206 | |||
207 | snprintf(state->name, CPUIDLE_NAME_LEN, "POLL"); | ||
208 | snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); | ||
209 | state->exit_latency = 0; | ||
210 | state->target_residency = 0; | ||
211 | state->power_usage = -1; | ||
212 | state->flags = 0; | ||
213 | state->enter = poll_idle; | ||
214 | state->disabled = false; | ||
215 | } | ||
216 | #else | ||
217 | static void poll_idle_init(struct cpuidle_driver *drv) {} | ||
218 | #endif /* !CONFIG_ARCH_HAS_CPU_RELAX */ | ||
219 | |||
180 | /** | 220 | /** |
181 | * __cpuidle_register_driver: register the driver | 221 | * __cpuidle_register_driver: register the driver |
182 | * @drv: a valid pointer to a struct cpuidle_driver | 222 | * @drv: a valid pointer to a struct cpuidle_driver |
@@ -210,6 +250,8 @@ static int __cpuidle_register_driver(struct cpuidle_driver *drv) | |||
210 | on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, | 250 | on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, |
211 | (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1); | 251 | (void *)CLOCK_EVT_NOTIFY_BROADCAST_ON, 1); |
212 | 252 | ||
253 | poll_idle_init(drv); | ||
254 | |||
213 | return 0; | 255 | return 0; |
214 | } | 256 | } |
215 | 257 | ||