- Remember how often an IRQ was posted into and pulled from the IRQ log - Measure the time between push and pull - Count how often we merge IRQs (multiple post events before pulling again)
Signed-off-by: Florian Bezdeka <florian.bezd...@siemens.com> --- kernel/irq/pipeline.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/kernel/irq/pipeline.c b/kernel/irq/pipeline.c index f64d731e8db1..7fcc03b74459 100644 --- a/kernel/irq/pipeline.c +++ b/kernel/irq/pipeline.c @@ -592,10 +592,18 @@ static inline bool irq_post_check(struct irq_stage *stage, unsigned int irq) #if __IRQ_STAGE_MAP_LEVELS == 4 +static inline struct pipe_stats __percpu *get_stage_stats(struct irq_stage *s, + struct irq_desc *desc) +{ + return this_cpu_ptr(s->index == 0 ? desc->ib_stats : desc->oob_stats); +} + /* Must be called hard irqs off. */ void irq_post_stage(struct irq_stage *stage, unsigned int irq) { struct irq_stage_data *p = this_staged(stage); + struct irq_desc *desc = irq_to_cached_desc(irq); + struct pipe_stats __percpu *stats = get_stage_stats(stage, desc); int l0b, l1b, l2b; if (irq_post_check(stage, irq)) @@ -605,10 +613,20 @@ void irq_post_stage(struct irq_stage *stage, unsigned int irq) l1b = irq / (BITS_PER_LONG * BITS_PER_LONG); l2b = irq / BITS_PER_LONG; + if (test_bit(irq, p->log.map->flat) + && test_bit(l2b, p->log.map->index_2) + && test_bit(l1b, p->log.map->index_1) + && test_bit(l0b, &p->log.index_0)) + stats->post_merge_cnt++; + else + stats->post_time = local_clock(); + __set_bit(irq, p->log.map->flat); __set_bit(l2b, p->log.map->index_2); __set_bit(l1b, p->log.map->index_1); __set_bit(l0b, &p->log.index_0); + + stats->post_cnt++; } EXPORT_SYMBOL_GPL(irq_post_stage); @@ -619,6 +637,9 @@ EXPORT_SYMBOL_GPL(irq_post_stage); static inline int pull_next_irq(struct irq_stage_data *p) { unsigned long l0m, l1m, l2m, l3m; + struct irq_desc *desc; + struct pipe_stats __percpu *stats; + u64 core_time, max_log_time, diff; int l0b, l1b, l2b, l3b; unsigned int irq; @@ -660,6 +681,19 @@ static inline int pull_next_irq(struct irq_stage_data *p) } } + desc = irq_to_cached_desc(irq); + stats = get_stage_stats(p->stage, desc); + + core_time = local_clock(); + stats->pull_time = core_time; + stats->pull_cnt++; + + max_log_time = stats->max_log_time; + diff = core_time - stats->post_time; + + if (diff > max_log_time) + stats->max_log_time = diff; + return irq; } -- 2.30.2