summaryrefslogtreecommitdiffstats
path: root/kernel/irq/internals.h
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@linaro.org>2017-06-23 10:11:08 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-06-24 05:44:39 -0400
commite1c921495534002d727b15a76a2f8c20b6b108b5 (patch)
tree28500774c5b8ff667a304d9a74ead820590f85e3 /kernel/irq/internals.h
parentb2d3d61adb7b73cfe5f82404f7a130a76fc64232 (diff)
genirq/timings: Add infrastructure for estimating the next interrupt arrival time
An interrupt behaves with a burst of activity with periodic interval of time followed by one or two peaks of longer interval. As the time intervals are periodic, statistically speaking they follow a normal distribution and each interrupts can be tracked individually. Add a mechanism to compute the statistics on all interrupts, except the timers which are deterministic from a prediction point of view, as their expiry time is known. The goal is to extract the periodicity for each interrupt, with the last timestamp and sum them, so the next event can be predicted to a certain extent. Taking the earliest prediction gives the expected wakeup on the system (assuming a timer won't expire before). Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Jens Axboe <axboe@kernel.dk> Cc: Hannes Reinecke <hare@suse.com> Cc: Vincent Guittot <vincent.guittot@linaro.org> Cc: "Rafael J . Wysocki" <rafael@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Link: http://lkml.kernel.org/r/1498227072-5980-2-git-send-email-daniel.lezcano@linaro.org
Diffstat (limited to 'kernel/irq/internals.h')
-rw-r--r--kernel/irq/internals.h19
1 files changed, 19 insertions, 0 deletions
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index b95b74920433..9da14d125df4 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -275,13 +275,21 @@ struct irq_timings {
275 275
276DECLARE_PER_CPU(struct irq_timings, irq_timings); 276DECLARE_PER_CPU(struct irq_timings, irq_timings);
277 277
278extern void irq_timings_free(int irq);
279extern int irq_timings_alloc(int irq);
280
278static inline void irq_remove_timings(struct irq_desc *desc) 281static inline void irq_remove_timings(struct irq_desc *desc)
279{ 282{
280 desc->istate &= ~IRQS_TIMINGS; 283 desc->istate &= ~IRQS_TIMINGS;
284
285 irq_timings_free(irq_desc_get_irq(desc));
281} 286}
282 287
283static inline void irq_setup_timings(struct irq_desc *desc, struct irqaction *act) 288static inline void irq_setup_timings(struct irq_desc *desc, struct irqaction *act)
284{ 289{
290 int irq = irq_desc_get_irq(desc);
291 int ret;
292
285 /* 293 /*
286 * We don't need the measurement because the idle code already 294 * We don't need the measurement because the idle code already
287 * knows the next expiry event. 295 * knows the next expiry event.
@@ -289,6 +297,17 @@ static inline void irq_setup_timings(struct irq_desc *desc, struct irqaction *ac
289 if (act->flags & __IRQF_TIMER) 297 if (act->flags & __IRQF_TIMER)
290 return; 298 return;
291 299
300 /*
301 * In case the timing allocation fails, we just want to warn,
302 * not fail, so letting the system boot anyway.
303 */
304 ret = irq_timings_alloc(irq);
305 if (ret) {
306 pr_warn("Failed to allocate irq timing stats for irq%d (%d)",
307 irq, ret);
308 return;
309 }
310
292 desc->istate |= IRQS_TIMINGS; 311 desc->istate |= IRQS_TIMINGS;
293} 312}
294 313