aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2013-01-02 09:18:18 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2013-01-08 04:57:07 -0500
commit420f42ecf48a926ba775ec7d7294425f004b6ade (patch)
treecd8a382554a325355701f0d7214cb0c7166b11b8 /arch
parentadd9bde216fefe1b65b41f7c0948cef48aa98c14 (diff)
s390/irq: remove split irq fields from /proc/stat
Now that irq sum accounting for /proc/stat's "intr" line works again we have the oddity that the sum field (first field) contains only the sum of the second (external irqs) and third field (I/O interrupts). The reason for that is that these two fields are already sums of all other fields. So if we would sum up everything we would count every interrupt twice. This is broken since the split interrupt accounting was merged two years ago: 052ff461c8427629aee887ccc27478fc7373237c "[S390] irq: have detailed statistics for interrupt types". To fix this remove the split interrupt fields from /proc/stat's "intr" line again and only have them in /proc/interrupts. This restores the old behaviour, seems to be the only sane fix and mimics a behaviour from other architectures where /proc/interrupts also contains more than /proc/stat's "intr" line does. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/irq.h77
-rw-r--r--arch/s390/kernel/irq.c121
-rw-r--r--arch/s390/kernel/nmi.c2
-rw-r--r--arch/s390/kernel/perf_cpum_cf.c2
-rw-r--r--arch/s390/kernel/runtime_instr.c2
-rw-r--r--arch/s390/kernel/smp.c4
-rw-r--r--arch/s390/kernel/time.c4
-rw-r--r--arch/s390/mm/fault.c2
-rw-r--r--arch/s390/oprofile/hwsampler.c2
-rw-r--r--arch/s390/pci/pci.c4
10 files changed, 131 insertions, 89 deletions
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index e6972f85d2b..c98dcac70ae 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -2,43 +2,60 @@
2#define _ASM_IRQ_H 2#define _ASM_IRQ_H
3 3
4#include <linux/hardirq.h> 4#include <linux/hardirq.h>
5#include <linux/percpu.h>
6#include <linux/cache.h>
5#include <linux/types.h> 7#include <linux/types.h>
6 8
7enum interruption_class { 9enum interruption_main_class {
8 EXTERNAL_INTERRUPT, 10 EXTERNAL_INTERRUPT,
9 IO_INTERRUPT, 11 IO_INTERRUPT,
10 EXTINT_CLK, 12 NR_IRQS
11 EXTINT_EXC, 13};
12 EXTINT_EMS, 14
13 EXTINT_TMR, 15enum interruption_class {
14 EXTINT_TLA, 16 IRQEXT_CLK,
15 EXTINT_PFL, 17 IRQEXT_EXC,
16 EXTINT_DSD, 18 IRQEXT_EMS,
17 EXTINT_VRT, 19 IRQEXT_TMR,
18 EXTINT_SCP, 20 IRQEXT_TLA,
19 EXTINT_IUC, 21 IRQEXT_PFL,
20 EXTINT_CMS, 22 IRQEXT_DSD,
21 EXTINT_CMC, 23 IRQEXT_VRT,
22 EXTINT_CMR, 24 IRQEXT_SCP,
23 IOINT_CIO, 25 IRQEXT_IUC,
24 IOINT_QAI, 26 IRQEXT_CMS,
25 IOINT_DAS, 27 IRQEXT_CMC,
26 IOINT_C15, 28 IRQEXT_CMR,
27 IOINT_C70, 29 IRQIO_CIO,
28 IOINT_TAP, 30 IRQIO_QAI,
29 IOINT_VMR, 31 IRQIO_DAS,
30 IOINT_LCS, 32 IRQIO_C15,
31 IOINT_CLW, 33 IRQIO_C70,
32 IOINT_CTC, 34 IRQIO_TAP,
33 IOINT_APB, 35 IRQIO_VMR,
34 IOINT_ADM, 36 IRQIO_LCS,
35 IOINT_CSC, 37 IRQIO_CLW,
36 IOINT_PCI, 38 IRQIO_CTC,
37 IOINT_MSI, 39 IRQIO_APB,
40 IRQIO_ADM,
41 IRQIO_CSC,
42 IRQIO_PCI,
43 IRQIO_MSI,
38 NMI_NMI, 44 NMI_NMI,
39 NR_IRQS, 45 NR_ARCH_IRQS
40}; 46};
41 47
48struct irq_stat {
49 unsigned int irqs[NR_ARCH_IRQS];
50};
51
52DECLARE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
53
54static __always_inline void inc_irq_stat(enum interruption_class irq)
55{
56 __get_cpu_var(irq_stat).irqs[irq]++;
57}
58
42struct ext_code { 59struct ext_code {
43 unsigned short subcode; 60 unsigned short subcode;
44 unsigned short code; 61 unsigned short code;
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index a8f8ab027ba..5f5462447af 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -24,42 +24,63 @@
24#include <asm/irq.h> 24#include <asm/irq.h>
25#include "entry.h" 25#include "entry.h"
26 26
27DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
28EXPORT_PER_CPU_SYMBOL_GPL(irq_stat);
29
27struct irq_class { 30struct irq_class {
28 char *name; 31 char *name;
29 char *desc; 32 char *desc;
30}; 33};
31 34
32static const struct irq_class intrclass_names[] = { 35/*
36 * The list of "main" irq classes on s390. This is the list of interrrupts
37 * that appear both in /proc/stat ("intr" line) and /proc/interrupts.
38 * Historically only external and I/O interrupts have been part of /proc/stat.
39 * We can't add the split external and I/O sub classes since the first field
40 * in the "intr" line in /proc/stat is supposed to be the sum of all other
41 * fields.
42 * Since the external and I/O interrupt fields are already sums we would end
43 * up with having a sum which accounts each interrupt twice.
44 */
45static const struct irq_class irqclass_main_desc[NR_IRQS] = {
33 [EXTERNAL_INTERRUPT] = {.name = "EXT"}, 46 [EXTERNAL_INTERRUPT] = {.name = "EXT"},
34 [IO_INTERRUPT] = {.name = "I/O"}, 47 [IO_INTERRUPT] = {.name = "I/O"}
35 [EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, 48};
36 [EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, 49
37 [EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, 50/*
38 [EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, 51 * The list of split external and I/O interrupts that appear only in
39 [EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, 52 * /proc/interrupts.
40 [EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, 53 * In addition this list contains non external / I/O events like NMIs.
41 [EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, 54 */
42 [EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, 55static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
43 [EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, 56 [IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
44 [EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, 57 [IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
45 [EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, 58 [IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
46 [EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, 59 [IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
47 [EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, 60 [IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
48 [IOINT_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, 61 [IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
49 [IOINT_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, 62 [IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
50 [IOINT_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, 63 [IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
51 [IOINT_C15] = {.name = "C15", .desc = "[I/O] 3215"}, 64 [IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
52 [IOINT_C70] = {.name = "C70", .desc = "[I/O] 3270"}, 65 [IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
53 [IOINT_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, 66 [IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
54 [IOINT_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, 67 [IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
55 [IOINT_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, 68 [IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
56 [IOINT_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, 69 [IRQIO_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
57 [IOINT_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, 70 [IRQIO_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
58 [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, 71 [IRQIO_DAS] = {.name = "DAS", .desc = "[I/O] DASD"},
59 [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, 72 [IRQIO_C15] = {.name = "C15", .desc = "[I/O] 3215"},
60 [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, 73 [IRQIO_C70] = {.name = "C70", .desc = "[I/O] 3270"},
61 [IOINT_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, 74 [IRQIO_TAP] = {.name = "TAP", .desc = "[I/O] Tape"},
62 [IOINT_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, 75 [IRQIO_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
76 [IRQIO_LCS] = {.name = "LCS", .desc = "[I/O] LCS"},
77 [IRQIO_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"},
78 [IRQIO_CTC] = {.name = "CTC", .desc = "[I/O] CTC"},
79 [IRQIO_APB] = {.name = "APB", .desc = "[I/O] AP Bus"},
80 [IRQIO_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
81 [IRQIO_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
82 [IRQIO_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
83 [IRQIO_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
63 [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, 84 [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"},
64}; 85};
65 86
@@ -68,30 +89,34 @@ static const struct irq_class intrclass_names[] = {
68 */ 89 */
69int show_interrupts(struct seq_file *p, void *v) 90int show_interrupts(struct seq_file *p, void *v)
70{ 91{
71 int i = *(loff_t *) v, j; 92 int irq = *(loff_t *) v;
93 int cpu;
72 94
73 get_online_cpus(); 95 get_online_cpus();
74 if (i == 0) { 96 if (irq == 0) {
75 seq_puts(p, " "); 97 seq_puts(p, " ");
76 for_each_online_cpu(j) 98 for_each_online_cpu(cpu)
77 seq_printf(p, "CPU%d ",j); 99 seq_printf(p, "CPU%d ", cpu);
78 seq_putc(p, '\n'); 100 seq_putc(p, '\n');
79 } 101 }
80 102 if (irq < NR_IRQS) {
81 if (i < NR_IRQS) { 103 seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
82 seq_printf(p, "%s: ", intrclass_names[i].name); 104 for_each_online_cpu(cpu)
83#ifndef CONFIG_SMP 105 seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]);
84 seq_printf(p, "%10u ", kstat_irqs(i)); 106 seq_putc(p, '\n');
85#else 107 goto skip_arch_irqs;
86 for_each_online_cpu(j) 108 }
87 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); 109 for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
88#endif 110 seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
89 if (intrclass_names[i].desc) 111 for_each_online_cpu(cpu)
90 seq_printf(p, " %s", intrclass_names[i].desc); 112 seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]);
91 seq_putc(p, '\n'); 113 if (irqclass_sub_desc[irq].desc)
92 } 114 seq_printf(p, " %s", irqclass_sub_desc[irq].desc);
115 seq_putc(p, '\n');
116 }
117skip_arch_irqs:
93 put_online_cpus(); 118 put_online_cpus();
94 return 0; 119 return 0;
95} 120}
96 121
97/* 122/*
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index a6daa5c5cdb..7918fbea36b 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -254,7 +254,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs)
254 int umode; 254 int umode;
255 255
256 nmi_enter(); 256 nmi_enter();
257 kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++; 257 inc_irq_stat(NMI_NMI);
258 mci = (struct mci *) &S390_lowcore.mcck_interruption_code; 258 mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
259 mcck = &__get_cpu_var(cpu_mcck); 259 mcck = &__get_cpu_var(cpu_mcck);
260 umode = user_mode(regs); 260 umode = user_mode(regs);
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
index c4e7269d4a0..86ec7447e1f 100644
--- a/arch/s390/kernel/perf_cpum_cf.c
+++ b/arch/s390/kernel/perf_cpum_cf.c
@@ -229,7 +229,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code,
229 if (!(alert & CPU_MF_INT_CF_MASK)) 229 if (!(alert & CPU_MF_INT_CF_MASK))
230 return; 230 return;
231 231
232 kstat_cpu(smp_processor_id()).irqs[EXTINT_CMC]++; 232 inc_irq_stat(IRQEXT_CMC);
233 cpuhw = &__get_cpu_var(cpu_hw_events); 233 cpuhw = &__get_cpu_var(cpu_hw_events);
234 234
235 /* Measurement alerts are shared and might happen when the PMU 235 /* Measurement alerts are shared and might happen when the PMU
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c
index 61066f6f71a..077a99389b0 100644
--- a/arch/s390/kernel/runtime_instr.c
+++ b/arch/s390/kernel/runtime_instr.c
@@ -71,7 +71,7 @@ static void runtime_instr_int_handler(struct ext_code ext_code,
71 if (!(param32 & CPU_MF_INT_RI_MASK)) 71 if (!(param32 & CPU_MF_INT_RI_MASK))
72 return; 72 return;
73 73
74 kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++; 74 inc_irq_stat(IRQEXT_CMR);
75 75
76 if (!current->thread.ri_cb) 76 if (!current->thread.ri_cb)
77 return; 77 return;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 82664a3c17e..4a36d5b5e4c 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -433,9 +433,9 @@ static void do_ext_call_interrupt(struct ext_code ext_code,
433 433
434 cpu = smp_processor_id(); 434 cpu = smp_processor_id();
435 if (ext_code.code == 0x1202) 435 if (ext_code.code == 0x1202)
436 kstat_cpu(cpu).irqs[EXTINT_EXC]++; 436 inc_irq_stat(IRQEXT_EXC);
437 else 437 else
438 kstat_cpu(cpu).irqs[EXTINT_EMS]++; 438 inc_irq_stat(IRQEXT_EMS);
439 /* 439 /*
440 * handle bit signal external calls 440 * handle bit signal external calls
441 */ 441 */
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 7fcd690d42c..aff0e350d77 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -168,7 +168,7 @@ static void clock_comparator_interrupt(struct ext_code ext_code,
168 unsigned int param32, 168 unsigned int param32,
169 unsigned long param64) 169 unsigned long param64)
170{ 170{
171 kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++; 171 inc_irq_stat(IRQEXT_CLK);
172 if (S390_lowcore.clock_comparator == -1ULL) 172 if (S390_lowcore.clock_comparator == -1ULL)
173 set_clock_comparator(S390_lowcore.clock_comparator); 173 set_clock_comparator(S390_lowcore.clock_comparator);
174} 174}
@@ -179,7 +179,7 @@ static void stp_timing_alert(struct stp_irq_parm *);
179static void timing_alert_interrupt(struct ext_code ext_code, 179static void timing_alert_interrupt(struct ext_code ext_code,
180 unsigned int param32, unsigned long param64) 180 unsigned int param32, unsigned long param64)
181{ 181{
182 kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++; 182 inc_irq_stat(IRQEXT_TLA);
183 if (param32 & 0x00c40000) 183 if (param32 & 0x00c40000)
184 etr_timing_alert((struct etr_irq_parm *) &param32); 184 etr_timing_alert((struct etr_irq_parm *) &param32);
185 if (param32 & 0x00038000) 185 if (param32 & 0x00038000)
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 42601d6e166..2fb9e63b8fc 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -569,7 +569,7 @@ static void pfault_interrupt(struct ext_code ext_code,
569 subcode = ext_code.subcode; 569 subcode = ext_code.subcode;
570 if ((subcode & 0xff00) != __SUBCODE_MASK) 570 if ((subcode & 0xff00) != __SUBCODE_MASK)
571 return; 571 return;
572 kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; 572 inc_irq_stat(IRQEXT_PFL);
573 /* Get the token (= pid of the affected task). */ 573 /* Get the token (= pid of the affected task). */
574 pid = sizeof(void *) == 4 ? param32 : param64; 574 pid = sizeof(void *) == 4 ? param32 : param64;
575 rcu_read_lock(); 575 rcu_read_lock();
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c
index 0cb385da202..b5b2916895e 100644
--- a/arch/s390/oprofile/hwsampler.c
+++ b/arch/s390/oprofile/hwsampler.c
@@ -233,7 +233,7 @@ static void hws_ext_handler(struct ext_code ext_code,
233 if (!(param32 & CPU_MF_INT_SF_MASK)) 233 if (!(param32 & CPU_MF_INT_SF_MASK))
234 return; 234 return;
235 235
236 kstat_cpu(smp_processor_id()).irqs[EXTINT_CMS]++; 236 inc_irq_stat(IRQEXT_CMS);
237 atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); 237 atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32);
238 238
239 if (hws_wq) 239 if (hws_wq)
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index e985744f633..60e0372545d 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -440,7 +440,7 @@ static void zpci_irq_handler(void *dont, void *need)
440 int rescan = 0, max = aisb_max; 440 int rescan = 0, max = aisb_max;
441 struct zdev_irq_map *imap; 441 struct zdev_irq_map *imap;
442 442
443 kstat_cpu(smp_processor_id()).irqs[IOINT_PCI]++; 443 inc_irq_stat(IRQIO_PCI);
444 sbit = start; 444 sbit = start;
445 445
446scan: 446scan:
@@ -452,7 +452,7 @@ scan:
452 /* find vector bit */ 452 /* find vector bit */
453 imap = bucket->imap[sbit]; 453 imap = bucket->imap[sbit];
454 for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) { 454 for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) {
455 kstat_cpu(smp_processor_id()).irqs[IOINT_MSI]++; 455 inc_irq_stat(IRQIO_MSI);
456 clear_bit(63 - mbit, &imap->aibv); 456 clear_bit(63 - mbit, &imap->aibv);
457 457
458 spin_lock(&imap->lock); 458 spin_lock(&imap->lock);