History

genirq/proc: Utilize irq_desc::tot_count to avoid evaluation

Interrupts which are not marked per CPU increment not only the per CPU statistics, but also the accumulation counter irq_desc::tot_count. Change the counter to type unsigned long so it does not produce sporadic zeros due to wrap arounds on 64-bit machines and do a quick check for non per CPU interrupts. If the counter is zero, then simply emit a full set of zero strings. That spares the evaluation of the per CPU counters completely for interrupts with zero events.

Thomas Gleixner committed 6 months ago

Commit 01794641 parent 95c33a62 files · +13 −4Browse files

Unified · Split

2 files
  1. include/linux/irqdesc.h +3 −3
  2. kernel/irq/proc.c +10 −1
include/linux/irqdesc.h+3−3
@@ -52,8 +52,8 @@ struct irq_redirect { · 51 unmodified lines
52 * @depth: disable-depth, for nested irq_disable() calls52 * @depth: disable-depth, for nested irq_disable() calls
53 * @wake_depth: enable depth, for multiple irq_set_irq_wake() callers53 * @wake_depth: enable depth, for multiple irq_set_irq_wake() callers
54 * @tot_count: stats field for non-percpu irqs54 * @tot_count: stats field for non-percpu irqs
55 * @irq_count: stats field to detect stalled irqs
56 * @last_unhandled: aging timer for unhandled count55 * @last_unhandled: aging timer for unhandled count
56 * @irq_count: stats field to detect stalled irqs
57 * @irqs_unhandled: stats field for spurious unhandled interrupts57 * @irqs_unhandled: stats field for spurious unhandled interrupts
58 * @threads_handled: stats field for deferred spurious detection of threaded handlers58 * @threads_handled: stats field for deferred spurious detection of threaded handlers
59 * @threads_handled_last: comparator field for deferred spurious detection of threaded handlers59 * @threads_handled_last: comparator field for deferred spurious detection of threaded handlers
@@ -87,9 +87,9 @@ struct irq_desc { · 27 unmodified lines
87 unsigned int core_internal_state__do_not_mess_with_it;87 unsigned int core_internal_state__do_not_mess_with_it;
88 unsigned int depth; /* nested irq disables */88 unsigned int depth; /* nested irq disables */
89 unsigned int wake_depth; /* nested wake enables */89 unsigned int wake_depth; /* nested wake enables */
90 unsigned int tot_count;90 unsigned long tot_count;
91 unsigned int irq_count; /* For detecting broken IRQs */
92 unsigned long last_unhandled; /* Aging timer for unhandled count */91 unsigned long last_unhandled; /* Aging timer for unhandled count */
92 unsigned int irq_count; /* For detecting broken IRQs */
93 unsigned int irqs_unhandled;93 unsigned int irqs_unhandled;
94 atomic_t threads_handled;94 atomic_t threads_handled;
95 int threads_handled_last;95 int threads_handled_last;
kernel/irq/proc.c+10−1
@@ -523,7 +523,16 @@ int show_interrupts(struct seq_file *p, void *v) · 522 unmodified lines
523 return 0;523 return 0;
524 524
525 seq_printf(p, "%*d:", prec, i);525 seq_printf(p, "%*d:", prec, i);
526 irq_proc_emit_counts(p, &desc->kstat_irqs->cnt);526
527 /*
528 * Always output per CPU interrupts. Output device interrupts only when
529 * desc::tot_count is not zero.
530 */
531 if (irq_settings_is_per_cpu(desc) || irq_settings_is_per_cpu_devid(desc) ||
532 data_race(desc->tot_count))
533 irq_proc_emit_counts(p, &desc->kstat_irqs->cnt);
534 else
535 irq_proc_emit_zero_counts(p, num_online_cpus());
527 seq_putc(p, ' ');536 seq_putc(p, ' ');
528 537
529 guard(raw_spinlock_irq)(&desc->lock);538 guard(raw_spinlock_irq)(&desc->lock);