aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-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 e6972f85d2b0..c98dcac70ae0 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 a8f8ab027ba8..5f5462447aff 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 a6daa5c5cdb0..7918fbea36bb 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 c4e7269d4a09..86ec7447e1f5 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 61066f6f71a5..077a99389b07 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 82664a3c17ee..4a36d5b5e4c9 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 7fcd690d42c7..aff0e350d776 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 42601d6e166f..2fb9e63b8fc4 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 0cb385da202c..b5b2916895e0 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 e985744f6334..60e0372545d2 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);