Skip to content

Commit e1c9214

Browse files
dlezcanoKAGA-KOKO
authored andcommitted
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
1 parent b2d3d61 commit e1c9214

File tree

3 files changed

+359
-0
lines changed

3 files changed

+359
-0
lines changed

include/linux/interrupt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ static inline void init_irq_proc(void)
706706
#ifdef CONFIG_IRQ_TIMINGS
707707
void irq_timings_enable(void);
708708
void irq_timings_disable(void);
709+
u64 irq_timings_next_event(u64 now);
709710
#endif
710711

711712
struct seq_file;

kernel/irq/internals.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,39 @@ struct irq_timings {
275275

276276
DECLARE_PER_CPU(struct irq_timings, irq_timings);
277277

278+
extern void irq_timings_free(int irq);
279+
extern int irq_timings_alloc(int irq);
280+
278281
static inline void irq_remove_timings(struct irq_desc *desc)
279282
{
280283
desc->istate &= ~IRQS_TIMINGS;
284+
285+
irq_timings_free(irq_desc_get_irq(desc));
281286
}
282287

283288
static inline void irq_setup_timings(struct irq_desc *desc, struct irqaction *act)
284289
{
290+
int irq = irq_desc_get_irq(desc);
291+
int ret;
292+
285293
/*
286294
* We don't need the measurement because the idle code already
287295
* knows the next expiry event.
288296
*/
289297
if (act->flags & __IRQF_TIMER)
290298
return;
291299

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+
292311
desc->istate |= IRQS_TIMINGS;
293312
}
294313

0 commit comments

Comments
 (0)