Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

genirq: Convert kstat_irqs to a struct

The irq_desc::kstat_irqs member is a per-CPU variable of type int, which is
only capable of counting. A snapshot mechanism for interrupt statistics
will be added soon, which requires an additional variable to store the
snapshot.

To facilitate expansion, convert kstat_irqs here to a struct containing
only the count.

Originally-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Bitao Hu <yaoma@linux.alibaba.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20240411074134.30922-2-yaoma@linux.alibaba.com

authored by

Bitao Hu and committed by
Thomas Gleixner
86d2a2f5 81e4cb0f

+23 -17
+1 -1
arch/mips/dec/setup.c
··· 756 756 NULL)) 757 757 pr_err("Failed to register fpu interrupt\n"); 758 758 desc_fpu = irq_to_desc(irq_fpu); 759 - fpu_kstat_irq = this_cpu_ptr(desc_fpu->kstat_irqs); 759 + fpu_kstat_irq = this_cpu_ptr(&desc_fpu->kstat_irqs->cnt); 760 760 } 761 761 if (dec_interrupt[DEC_IRQ_CASCADE] >= 0) { 762 762 if (request_irq(dec_interrupt[DEC_IRQ_CASCADE], no_action,
+1 -1
arch/parisc/kernel/smp.c
··· 344 344 struct irq_desc *desc = irq_to_desc(i); 345 345 346 346 if (desc && desc->kstat_irqs) 347 - *per_cpu_ptr(desc->kstat_irqs, cpuid) = 0; 347 + *per_cpu_ptr(desc->kstat_irqs, cpuid) = (struct irqstat) { }; 348 348 } 349 349 #endif 350 350
+1 -1
arch/powerpc/kvm/book3s_hv_rm_xics.c
··· 837 837 */ 838 838 static void kvmppc_rm_handle_irq_desc(struct irq_desc *desc) 839 839 { 840 - this_cpu_inc_rm(desc->kstat_irqs); 840 + this_cpu_inc_rm(&desc->kstat_irqs->cnt); 841 841 __this_cpu_inc(kstat.irqs_sum); 842 842 } 843 843
+10 -2
include/linux/irqdesc.h
··· 18 18 struct pt_regs; 19 19 20 20 /** 21 + * struct irqstat - interrupt statistics 22 + * @cnt: real-time interrupt count 23 + */ 24 + struct irqstat { 25 + unsigned int cnt; 26 + }; 27 + 28 + /** 21 29 * struct irq_desc - interrupt descriptor 22 30 * @irq_common_data: per irq and chip data passed down to chip functions 23 31 * @kstat_irqs: irq stats per cpu ··· 63 55 struct irq_desc { 64 56 struct irq_common_data irq_common_data; 65 57 struct irq_data irq_data; 66 - unsigned int __percpu *kstat_irqs; 58 + struct irqstat __percpu *kstat_irqs; 67 59 irq_flow_handler_t handle_irq; 68 60 struct irqaction *action; /* IRQ action list */ 69 61 unsigned int status_use_accessors; ··· 127 119 static inline unsigned int irq_desc_kstat_cpu(struct irq_desc *desc, 128 120 unsigned int cpu) 129 121 { 130 - return desc->kstat_irqs ? *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; 122 + return desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, cpu) : 0; 131 123 } 132 124 133 125 static inline struct irq_desc *irq_data_to_desc(struct irq_data *data)
+1 -1
kernel/irq/internals.h
··· 258 258 259 259 static inline void __kstat_incr_irqs_this_cpu(struct irq_desc *desc) 260 260 { 261 - __this_cpu_inc(*desc->kstat_irqs); 261 + __this_cpu_inc(desc->kstat_irqs->cnt); 262 262 __this_cpu_inc(kstat.irqs_sum); 263 263 } 264 264
+4 -5
kernel/irq/irqdesc.c
··· 134 134 desc->name = NULL; 135 135 desc->owner = owner; 136 136 for_each_possible_cpu(cpu) 137 - *per_cpu_ptr(desc->kstat_irqs, cpu) = 0; 137 + *per_cpu_ptr(desc->kstat_irqs, cpu) = (struct irqstat) { }; 138 138 desc_smp_init(desc, node, affinity); 139 139 } 140 140 ··· 186 186 const struct cpumask *affinity, 187 187 struct module *owner) 188 188 { 189 - desc->kstat_irqs = alloc_percpu(unsigned int); 189 + desc->kstat_irqs = alloc_percpu(struct irqstat); 190 190 if (!desc->kstat_irqs) 191 191 return -ENOMEM; 192 192 ··· 968 968 { 969 969 struct irq_desc *desc = irq_to_desc(irq); 970 970 971 - return desc && desc->kstat_irqs ? 972 - *per_cpu_ptr(desc->kstat_irqs, cpu) : 0; 971 + return desc && desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, cpu) : 0; 973 972 } 974 973 975 974 static bool irq_is_nmi(struct irq_desc *desc) ··· 990 991 return data_race(desc->tot_count); 991 992 992 993 for_each_possible_cpu(cpu) 993 - sum += data_race(*per_cpu_ptr(desc->kstat_irqs, cpu)); 994 + sum += data_race(per_cpu(desc->kstat_irqs->cnt, cpu)); 994 995 return sum; 995 996 } 996 997
+2 -3
kernel/irq/proc.c
··· 490 490 491 491 if (desc->kstat_irqs) { 492 492 for_each_online_cpu(j) 493 - any_count |= data_race(*per_cpu_ptr(desc->kstat_irqs, j)); 493 + any_count |= data_race(per_cpu(desc->kstat_irqs->cnt, j)); 494 494 } 495 495 496 496 if ((!desc->action || irq_desc_is_chained(desc)) && !any_count) ··· 498 498 499 499 seq_printf(p, "%*d: ", prec, i); 500 500 for_each_online_cpu(j) 501 - seq_printf(p, "%10u ", desc->kstat_irqs ? 502 - *per_cpu_ptr(desc->kstat_irqs, j) : 0); 501 + seq_printf(p, "%10u ", desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, j) : 0); 503 502 504 503 raw_spin_lock_irqsave(&desc->lock, flags); 505 504 if (desc->irq_data.chip) {
+3 -3
scripts/gdb/linux/interrupts.py
··· 37 37 any_count = 0 38 38 if desc['kstat_irqs']: 39 39 for cpu in cpus.each_online_cpu(): 40 - any_count += cpus.per_cpu(desc['kstat_irqs'], cpu) 40 + any_count += cpus.per_cpu(desc['kstat_irqs'], cpu)['cnt'] 41 41 42 42 if (desc['action'] == 0 or irq_desc_is_chained(desc)) and any_count == 0: 43 43 return text; ··· 45 45 text += "%*d: " % (prec, irq) 46 46 for cpu in cpus.each_online_cpu(): 47 47 if desc['kstat_irqs']: 48 - count = cpus.per_cpu(desc['kstat_irqs'], cpu) 48 + count = cpus.per_cpu(desc['kstat_irqs'], cpu)['cnt'] 49 49 else: 50 50 count = 0 51 51 text += "%10u" % (count) ··· 177 177 if desc == 0: 178 178 continue 179 179 for cpu in cpus.each_online_cpu(): 180 - text += "%10u" % (cpus.per_cpu(desc['kstat_irqs'], cpu)) 180 + text += "%10u" % (cpus.per_cpu(desc['kstat_irqs'], cpu)['cnt']) 181 181 text += " %s" % (ipi_types[ipi].string()) 182 182 text += "\n" 183 183 return text