summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2019-01-22 22:05:55 +0100
committerDaniel Lezcano <daniel.lezcano@linaro.org>2019-01-22 22:05:55 +0100
commit2ec79b45c03746177ae5e0d2461faab7d01fff95 (patch)
tree8bd5f4fc5fe1efab6998b2e2efd988346679ddf3
parent9cb5a446039dd97aefc4e3783057430ca7decc88 (diff)
Fix irq governor
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
-rw-r--r--drivers/cpuidle/governors/irq.c35
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;
}