diff options
author | Daniel Lezcano <daniel.lezcano@linaro.org> | 2019-01-22 22:05:55 +0100 |
---|---|---|
committer | Daniel Lezcano <daniel.lezcano@linaro.org> | 2019-01-22 22:05:55 +0100 |
commit | 2ec79b45c03746177ae5e0d2461faab7d01fff95 (patch) | |
tree | 8bd5f4fc5fe1efab6998b2e2efd988346679ddf3 | |
parent | 9cb5a446039dd97aefc4e3783057430ca7decc88 (diff) |
Fix irq governor
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r-- | drivers/cpuidle/governors/irq.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/cpuidle/governors/irq.c b/drivers/cpuidle/governors/irq.c index 298d3f005eb1..1cba6f135266 100644 --- a/drivers/cpuidle/governors/irq.c +++ b/drivers/cpuidle/governors/irq.c @@ -9,6 +9,7 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/tick.h> #include <linux/interrupt.h> #include <linux/sched/clock.h> @@ -16,27 +17,39 @@ static u64 wakeup_next_event(u64 now) { - u64 next_event; + u64 next_event, next_irq, next_timer, next_ipi; - next_event = irq_timings_next_event(now); - next_event = min_t(u64, next_event, timer_next_event()); - next_event = min_t(u64, next_event, idle_next_wakeup()); + next_event = next_irq = next_timer = next_ipi = U64_MAX; - return (next_event <= now) ? now : next_event; + next_irq = irq_timings_next_event(now); + if (next_irq <= now) + goto out; + + next_timer = tick_next_timer(now); + if (next_timer <= now) + goto out; + + next_ipi = idle_next_wakeup(); +out: + next_event = min_t(u64, next_event, next_irq); + next_event = min_t(u64, next_event, next_timer); + next_event = min_t(u64, next_event, next_ipi); + next_event = max_t(u64, next_event, now); + + return next_event; } static int irq_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, bool *stop_tick) { int latency_req = cpuidle_governor_latency_req(dev->cpu); - int i, residency, index = 0; + int i, index = 0; u64 now, next_event; + u64 residency; now = local_clock(); next_event = wakeup_next_event(now); - residency = next_event - now; - - trace_next_wakeup(now, next_event, residency, dev->cpu); + residency = (next_event - now) / 1000; for (i = 0; i < drv->state_count; i++) { struct cpuidle_state *s = &drv->states[i]; @@ -46,10 +59,10 @@ static int irq_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, continue; if (s->exit_latency > latency_req) - continue; + break; if (s->target_residency > residency) - continue; + break; index = i; } |