Skip to content

Commit

Permalink
genirq/timings: Add infrastructure for estimating the next interrupt …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Daniel Lezcano authored and Thomas Gleixner committed Jun 24, 2017
1 parent b2d3d61 commit e1c9214
Show file tree
Hide file tree
Showing 3 changed files with 359 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ static inline void init_irq_proc(void)
#ifdef CONFIG_IRQ_TIMINGS
void irq_timings_enable(void);
void irq_timings_disable(void);
u64 irq_timings_next_event(u64 now);
#endif

struct seq_file;
Expand Down
19 changes: 19 additions & 0 deletions kernel/irq/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,20 +275,39 @@ struct irq_timings {

DECLARE_PER_CPU(struct irq_timings, irq_timings);

extern void irq_timings_free(int irq);
extern int irq_timings_alloc(int irq);

static inline void irq_remove_timings(struct irq_desc *desc)
{
desc->istate &= ~IRQS_TIMINGS;

irq_timings_free(irq_desc_get_irq(desc));
}

static inline void irq_setup_timings(struct irq_desc *desc, struct irqaction *act)
{
int irq = irq_desc_get_irq(desc);
int ret;

/*
* We don't need the measurement because the idle code already
* knows the next expiry event.
*/
if (act->flags & __IRQF_TIMER)
return;

/*
* In case the timing allocation fails, we just want to warn,
* not fail, so letting the system boot anyway.
*/
ret = irq_timings_alloc(irq);
if (ret) {
pr_warn("Failed to allocate irq timing stats for irq%d (%d)",
irq, ret);
return;
}

desc->istate |= IRQS_TIMINGS;
}

Expand Down
Loading

0 comments on commit e1c9214

Please sign in to comment.