Skip to content

Commit 36227b1

Browse files
author
Fox Snowpatch
committed
1 parent 4db4221 commit 36227b1

File tree

12 files changed

+302
-30
lines changed

12 files changed

+302
-30
lines changed

arch/mips/dec/setup.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ void __init arch_init_irq(void)
756756
NULL))
757757
pr_err("Failed to register fpu interrupt\n");
758758
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);
760760
}
761761
if (dec_interrupt[DEC_IRQ_CASCADE] >= 0) {
762762
if (request_irq(dec_interrupt[DEC_IRQ_CASCADE], no_action,

arch/parisc/kernel/smp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ static int smp_boot_one_cpu(int cpuid, struct task_struct *idle)
344344
struct irq_desc *desc = irq_to_desc(i);
345345

346346
if (desc && desc->kstat_irqs)
347-
*per_cpu_ptr(desc->kstat_irqs, cpuid) = 0;
347+
*per_cpu_ptr(desc->kstat_irqs, cpuid) = (struct irqstat) { };
348348
}
349349
#endif
350350

arch/powerpc/kvm/book3s_hv_rm_xics.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ static inline void this_cpu_inc_rm(unsigned int __percpu *addr)
837837
*/
838838
static void kvmppc_rm_handle_irq_desc(struct irq_desc *desc)
839839
{
840-
this_cpu_inc_rm(desc->kstat_irqs);
840+
this_cpu_inc_rm(&desc->kstat_irqs->cnt);
841841
__this_cpu_inc(kstat.irqs_sum);
842842
}
843843

include/linux/irqdesc.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ struct irq_desc;
1717
struct irq_domain;
1818
struct pt_regs;
1919

20+
/**
21+
* struct irqstat - interrupt statistics
22+
* @cnt: real-time interrupt count
23+
* @ref: snapshot of interrupt count
24+
*/
25+
struct irqstat {
26+
unsigned int cnt;
27+
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
28+
unsigned int ref;
29+
#endif
30+
};
31+
2032
/**
2133
* struct irq_desc - interrupt descriptor
2234
* @irq_common_data: per irq and chip data passed down to chip functions
@@ -55,7 +67,7 @@ struct pt_regs;
5567
struct irq_desc {
5668
struct irq_common_data irq_common_data;
5769
struct irq_data irq_data;
58-
unsigned int __percpu *kstat_irqs;
70+
struct irqstat __percpu *kstat_irqs;
5971
irq_flow_handler_t handle_irq;
6072
struct irqaction *action; /* IRQ action list */
6173
unsigned int status_use_accessors;
@@ -119,7 +131,7 @@ extern struct irq_desc irq_desc[NR_IRQS];
119131
static inline unsigned int irq_desc_kstat_cpu(struct irq_desc *desc,
120132
unsigned int cpu)
121133
{
122-
return desc->kstat_irqs ? *per_cpu_ptr(desc->kstat_irqs, cpu) : 0;
134+
return desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, cpu) : 0;
123135
}
124136

125137
static inline struct irq_desc *irq_data_to_desc(struct irq_data *data)

include/linux/kernel_stat.h

+8
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ static inline unsigned int kstat_cpu_softirqs_sum(int cpu)
7979
return sum;
8080
}
8181

82+
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
83+
extern void kstat_snapshot_irqs(void);
84+
extern unsigned int kstat_get_irq_since_snapshot(unsigned int irq);
85+
#else
86+
static inline void kstat_snapshot_irqs(void) { }
87+
static inline unsigned int kstat_get_irq_since_snapshot(unsigned int irq) { return 0; }
88+
#endif
89+
8290
/*
8391
* Number of interrupts per specific IRQ source, since bootup
8492
*/

kernel/irq/Kconfig

+4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ config GENERIC_IRQ_MATRIX_ALLOCATOR
108108
config GENERIC_IRQ_RESERVATION_MODE
109109
bool
110110

111+
# Snapshot for interrupt statistics
112+
config GENERIC_IRQ_STAT_SNAPSHOT
113+
bool
114+
111115
# Support forced irq threading
112116
config IRQ_FORCED_THREADING
113117
bool

kernel/irq/internals.h

+3-1
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
@@ -258,7 +260,7 @@ static inline void irq_state_set_masked(struct irq_desc *desc)
258260

259261
static inline void __kstat_incr_irqs_this_cpu(struct irq_desc *desc)
260262
{
261-
__this_cpu_inc(*desc->kstat_irqs);
263+
__this_cpu_inc(desc->kstat_irqs->cnt);
262264
__this_cpu_inc(kstat.irqs_sum);
263265
}
264266

kernel/irq/irqdesc.c

+40-10
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
134134
desc->name = NULL;
135135
desc->owner = owner;
136136
for_each_possible_cpu(cpu)
137-
*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
137+
*per_cpu_ptr(desc->kstat_irqs, cpu) = (struct irqstat) { };
138138
desc_smp_init(desc, node, affinity);
139139
}
140140

@@ -186,7 +186,7 @@ static int init_desc(struct irq_desc *desc, int irq, int node,
186186
const struct cpumask *affinity,
187187
struct module *owner)
188188
{
189-
desc->kstat_irqs = alloc_percpu(unsigned int);
189+
desc->kstat_irqs = alloc_percpu(struct irqstat);
190190
if (!desc->kstat_irqs)
191191
return -ENOMEM;
192192

@@ -968,33 +968,63 @@ unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
968968
{
969969
struct irq_desc *desc = irq_to_desc(irq);
970970

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;
973972
}
974973

975974
static bool irq_is_nmi(struct irq_desc *desc)
976975
{
977976
return desc->istate & IRQS_NMI;
978977
}
979978

980-
static unsigned int kstat_irqs(unsigned int irq)
979+
unsigned int kstat_irqs_desc(struct irq_desc *desc, const struct cpumask *cpumask)
981980
{
982-
struct irq_desc *desc = irq_to_desc(irq);
983981
unsigned int sum = 0;
984982
int cpu;
985983

986-
if (!desc || !desc->kstat_irqs)
987-
return 0;
988984
if (!irq_settings_is_per_cpu_devid(desc) &&
989985
!irq_settings_is_per_cpu(desc) &&
990986
!irq_is_nmi(desc))
991987
return data_race(desc->tot_count);
992988

993-
for_each_possible_cpu(cpu)
994-
sum += data_race(*per_cpu_ptr(desc->kstat_irqs, cpu));
989+
for_each_cpu(cpu, cpumask)
990+
sum += data_race(per_cpu(desc->kstat_irqs->cnt, cpu));
995991
return sum;
996992
}
997993

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+
1003+
#ifdef CONFIG_GENERIC_IRQ_STAT_SNAPSHOT
1004+
1005+
void kstat_snapshot_irqs(void)
1006+
{
1007+
struct irq_desc *desc;
1008+
unsigned int irq;
1009+
1010+
for_each_irq_desc(irq, desc) {
1011+
if (!desc->kstat_irqs)
1012+
continue;
1013+
this_cpu_write(desc->kstat_irqs->ref, this_cpu_read(desc->kstat_irqs->cnt));
1014+
}
1015+
}
1016+
1017+
unsigned int kstat_get_irq_since_snapshot(unsigned int irq)
1018+
{
1019+
struct irq_desc *desc = irq_to_desc(irq);
1020+
1021+
if (!desc || !desc->kstat_irqs)
1022+
return 0;
1023+
return this_cpu_read(desc->kstat_irqs->cnt) - this_cpu_read(desc->kstat_irqs->ref);
1024+
}
1025+
1026+
#endif
1027+
9981028
/**
9991029
* kstat_irqs_usr - Get the statistics for an interrupt from thread context
10001030
* @irq: The interrupt number

kernel/irq/proc.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -488,18 +488,15 @@ 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_ptr(desc->kstat_irqs, 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;
498496

499497
seq_printf(p, "%*d: ", prec, i);
500498
for_each_online_cpu(j)
501-
seq_printf(p, "%10u ", desc->kstat_irqs ?
502-
*per_cpu_ptr(desc->kstat_irqs, j) : 0);
499+
seq_printf(p, "%10u ", desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, j) : 0);
503500

504501
raw_spin_lock_irqsave(&desc->lock, flags);
505502
if (desc->irq_data.chip) {

0 commit comments

Comments
 (0)