diff options
Diffstat (limited to 'arch/s390/kernel/irq.c')
-rw-r--r-- | arch/s390/kernel/irq.c | 124 |
1 files changed, 75 insertions, 49 deletions
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index bf24293970ce..9df824ea1667 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -24,43 +24,65 @@ | |||
24 | #include <asm/irq.h> | 24 | #include <asm/irq.h> |
25 | #include "entry.h" | 25 | #include "entry.h" |
26 | 26 | ||
27 | DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); | ||
28 | EXPORT_PER_CPU_SYMBOL_GPL(irq_stat); | ||
29 | |||
27 | struct irq_class { | 30 | struct irq_class { |
28 | char *name; | 31 | char *name; |
29 | char *desc; | 32 | char *desc; |
30 | }; | 33 | }; |
31 | 34 | ||
32 | static 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 | */ | ||
45 | static 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"}, | 55 | static 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"}, |
85 | [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"}, | ||
64 | }; | 86 | }; |
65 | 87 | ||
66 | /* | 88 | /* |
@@ -68,30 +90,34 @@ static const struct irq_class intrclass_names[] = { | |||
68 | */ | 90 | */ |
69 | int show_interrupts(struct seq_file *p, void *v) | 91 | int show_interrupts(struct seq_file *p, void *v) |
70 | { | 92 | { |
71 | int i = *(loff_t *) v, j; | 93 | int irq = *(loff_t *) v; |
94 | int cpu; | ||
72 | 95 | ||
73 | get_online_cpus(); | 96 | get_online_cpus(); |
74 | if (i == 0) { | 97 | if (irq == 0) { |
75 | seq_puts(p, " "); | 98 | seq_puts(p, " "); |
76 | for_each_online_cpu(j) | 99 | for_each_online_cpu(cpu) |
77 | seq_printf(p, "CPU%d ",j); | 100 | seq_printf(p, "CPU%d ", cpu); |
78 | seq_putc(p, '\n'); | 101 | seq_putc(p, '\n'); |
79 | } | 102 | } |
80 | 103 | if (irq < NR_IRQS) { | |
81 | if (i < NR_IRQS) { | 104 | seq_printf(p, "%s: ", irqclass_main_desc[irq].name); |
82 | seq_printf(p, "%s: ", intrclass_names[i].name); | 105 | for_each_online_cpu(cpu) |
83 | #ifndef CONFIG_SMP | 106 | seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]); |
84 | seq_printf(p, "%10u ", kstat_irqs(i)); | 107 | seq_putc(p, '\n'); |
85 | #else | 108 | goto skip_arch_irqs; |
86 | for_each_online_cpu(j) | 109 | } |
87 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | 110 | for (irq = 0; irq < NR_ARCH_IRQS; irq++) { |
88 | #endif | 111 | seq_printf(p, "%s: ", irqclass_sub_desc[irq].name); |
89 | if (intrclass_names[i].desc) | 112 | for_each_online_cpu(cpu) |
90 | seq_printf(p, " %s", intrclass_names[i].desc); | 113 | seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]); |
91 | seq_putc(p, '\n'); | 114 | if (irqclass_sub_desc[irq].desc) |
92 | } | 115 | seq_printf(p, " %s", irqclass_sub_desc[irq].desc); |
116 | seq_putc(p, '\n'); | ||
117 | } | ||
118 | skip_arch_irqs: | ||
93 | put_online_cpus(); | 119 | put_online_cpus(); |
94 | return 0; | 120 | return 0; |
95 | } | 121 | } |
96 | 122 | ||
97 | /* | 123 | /* |
@@ -222,7 +248,7 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, | |||
222 | /* Serve timer interrupts first. */ | 248 | /* Serve timer interrupts first. */ |
223 | clock_comparator_work(); | 249 | clock_comparator_work(); |
224 | } | 250 | } |
225 | kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; | 251 | kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL); |
226 | if (ext_code.code != 0x1004) | 252 | if (ext_code.code != 0x1004) |
227 | __get_cpu_var(s390_idle).nohz_delay = 1; | 253 | __get_cpu_var(s390_idle).nohz_delay = 1; |
228 | 254 | ||