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.
Unified · Split
| @@ -52,8 +52,8 @@ struct irq_redirect { · 51 unmodified lines | |||
| 52 | * @depth: disable-depth, for nested irq_disable() calls | 52 | * @depth: disable-depth, for nested irq_disable() calls |
| 53 | * @wake_depth: enable depth, for multiple irq_set_irq_wake() callers | 53 | * @wake_depth: enable depth, for multiple irq_set_irq_wake() callers |
| 54 | * @tot_count: stats field for non-percpu irqs | 54 | * @tot_count: stats field for non-percpu irqs |
| 55 | * @irq_count: stats field to detect stalled irqs | ||
| 56 | * @last_unhandled: aging timer for unhandled count | 55 | * @last_unhandled: aging timer for unhandled count |
| 56 | * @irq_count: stats field to detect stalled irqs | ||
| 57 | * @irqs_unhandled: stats field for spurious unhandled interrupts | 57 | * @irqs_unhandled: stats field for spurious unhandled interrupts |
| 58 | * @threads_handled: stats field for deferred spurious detection of threaded handlers | 58 | * @threads_handled: stats field for deferred spurious detection of threaded handlers |
| 59 | * @threads_handled_last: comparator field for deferred spurious detection of threaded handlers | 59 | * @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; |
| @@ -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); |