Skip to content

Commit 25a4a01

Browse files
hubitao-yaomaKAGA-KOKO
authored andcommitted
genirq: Avoid summation loops for /proc/interrupts
show_interrupts() unconditionally accumulates the per CPU interrupt statistics to determine whether an interrupt was ever raised. This can be avoided for all interrupts which are not strictly per CPU and not of type NMI because those interrupts provide already an accumulated counter. The required logic is already implemented in kstat_irqs(). Split the inner access logic out of kstat_irqs() and use it for kstat_irqs() and show_interrupts() to avoid the accumulation loop when possible. Originally-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Bitao Hu <yaoma@linux.alibaba.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Liu Song <liusong@linux.alibaba.com> Reviewed-by: Douglas Anderson <dianders@chromium.org> Link: https://lore.kernel.org/r/20240411074134.30922-4-yaoma@linux.alibaba.com
1 parent 99cf63c commit 25a4a01

3 files changed

Lines changed: 15 additions & 9 deletions

File tree

kernel/irq/internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ extern void mask_irq(struct irq_desc *desc);
9898
extern void unmask_irq(struct irq_desc *desc);
9999
extern void unmask_threaded_irq(struct irq_desc *desc);
100100

101+
extern unsigned int kstat_irqs_desc(struct irq_desc *desc, const struct cpumask *cpumask);
102+
101103
#ifdef CONFIG_SPARSE_IRQ
102104
static inline void irq_mark_irq(unsigned int irq) { }
103105
#else

kernel/irq/irqdesc.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -976,24 +976,30 @@ static bool irq_is_nmi(struct irq_desc *desc)
976976
return desc->istate & IRQS_NMI;
977977
}
978978

979-
static unsigned int kstat_irqs(unsigned int irq)
979+
unsigned int kstat_irqs_desc(struct irq_desc *desc, const struct cpumask *cpumask)
980980
{
981-
struct irq_desc *desc = irq_to_desc(irq);
982981
unsigned int sum = 0;
983982
int cpu;
984983

985-
if (!desc || !desc->kstat_irqs)
986-
return 0;
987984
if (!irq_settings_is_per_cpu_devid(desc) &&
988985
!irq_settings_is_per_cpu(desc) &&
989986
!irq_is_nmi(desc))
990987
return data_race(desc->tot_count);
991988

992-
for_each_possible_cpu(cpu)
989+
for_each_cpu(cpu, cpumask)
993990
sum += data_race(per_cpu(desc->kstat_irqs->cnt, cpu));
994991
return sum;
995992
}
996993

994+
static unsigned int kstat_irqs(unsigned int irq)
995+
{
996+
struct irq_desc *desc = irq_to_desc(irq);
997+
998+
if (!desc || !desc->kstat_irqs)
999+
return 0;
1000+
return kstat_irqs_desc(desc, cpu_possible_mask);
1001+
}
1002+
9971003
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
9981004

9991005
void kstat_snapshot_irqs(void)

kernel/irq/proc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,10 +488,8 @@ int show_interrupts(struct seq_file *p, void *v)
488488
if (!desc || irq_settings_is_hidden(desc))
489489
goto outsparse;
490490

491-
if (desc->kstat_irqs) {
492-
for_each_online_cpu(j)
493-
any_count |= data_race(per_cpu(desc->kstat_irqs->cnt, j));
494-
}
491+
if (desc->kstat_irqs)
492+
any_count = kstat_irqs_desc(desc, cpu_online_mask);
495493

496494
if ((!desc->action || irq_desc_is_chained(desc)) && !any_count)
497495
goto outsparse;

0 commit comments

Comments
 (0)