s390/irq: improve displayed interrupt order in /proc/interrupts

Rework the irqclass_main_desc and irqclass_sub_desc data structures which
are used to report detaild IRQ statistics in /proc/interrupts.  When
called from the procfs ops, the entries in the structures are processed
one by one.

The index of an IRQ in the structures is identical to its definition in
the "enum interruption_class".   To control and (re)order the displayed
sequence, introduce an irq member in each entry.  This helps to display
related IRQs together without changing the assigned number in the
interruption_class enumeration.  That means, adding and displaying new
IRQs are independent.
Finally, this new behavior improves to maintain a kernel ABI.

Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Hendrik Brueckner 2014-07-22 16:58:52 +02:00 committed by Martin Schwidefsky
parent dc295880c6
commit e2213e04c1

View File

@ -30,6 +30,7 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
EXPORT_PER_CPU_SYMBOL_GPL(irq_stat);
struct irq_class {
int irq;
char *name;
char *desc;
};
@ -45,9 +46,9 @@ struct irq_class {
* up with having a sum which accounts each interrupt twice.
*/
static const struct irq_class irqclass_main_desc[NR_IRQS_BASE] = {
[EXT_INTERRUPT] = {.name = "EXT"},
[IO_INTERRUPT] = {.name = "I/O"},
[THIN_INTERRUPT] = {.name = "AIO"},
{.irq = EXT_INTERRUPT, .name = "EXT"},
{.irq = IO_INTERRUPT, .name = "I/O"},
{.irq = THIN_INTERRUPT, .name = "AIO"},
};
/*
@ -56,38 +57,38 @@ static const struct irq_class irqclass_main_desc[NR_IRQS_BASE] = {
* In addition this list contains non external / I/O events like NMIs.
*/
static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
[IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
[IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
[IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
[IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
[IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
[IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
[IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
[IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
[IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
[IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
[IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
[IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
[IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
[IRQIO_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
[IRQIO_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
[IRQIO_DAS] = {.name = "DAS", .desc = "[I/O] DASD"},
[IRQIO_C15] = {.name = "C15", .desc = "[I/O] 3215"},
[IRQIO_C70] = {.name = "C70", .desc = "[I/O] 3270"},
[IRQIO_TAP] = {.name = "TAP", .desc = "[I/O] Tape"},
[IRQIO_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
[IRQIO_LCS] = {.name = "LCS", .desc = "[I/O] LCS"},
[IRQIO_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"},
[IRQIO_CTC] = {.name = "CTC", .desc = "[I/O] CTC"},
[IRQIO_APB] = {.name = "APB", .desc = "[I/O] AP Bus"},
[IRQIO_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
[IRQIO_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
[IRQIO_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
[IRQIO_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
[IRQIO_VIR] = {.name = "VIR", .desc = "[I/O] Virtual I/O Devices"},
[IRQIO_VAI] = {.name = "VAI", .desc = "[I/O] Virtual I/O Devices AI"},
[NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"},
[CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"},
{.irq = IRQEXT_CLK, .name = "CLK", .desc = "[EXT] Clock Comparator"},
{.irq = IRQEXT_EXC, .name = "EXC", .desc = "[EXT] External Call"},
{.irq = IRQEXT_EMS, .name = "EMS", .desc = "[EXT] Emergency Signal"},
{.irq = IRQEXT_TMR, .name = "TMR", .desc = "[EXT] CPU Timer"},
{.irq = IRQEXT_TLA, .name = "TAL", .desc = "[EXT] Timing Alert"},
{.irq = IRQEXT_PFL, .name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
{.irq = IRQEXT_DSD, .name = "DSD", .desc = "[EXT] DASD Diag"},
{.irq = IRQEXT_VRT, .name = "VRT", .desc = "[EXT] Virtio"},
{.irq = IRQEXT_SCP, .name = "SCP", .desc = "[EXT] Service Call"},
{.irq = IRQEXT_IUC, .name = "IUC", .desc = "[EXT] IUCV"},
{.irq = IRQEXT_CMS, .name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
{.irq = IRQEXT_CMC, .name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
{.irq = IRQEXT_CMR, .name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
{.irq = IRQIO_CIO, .name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
{.irq = IRQIO_QAI, .name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
{.irq = IRQIO_DAS, .name = "DAS", .desc = "[I/O] DASD"},
{.irq = IRQIO_C15, .name = "C15", .desc = "[I/O] 3215"},
{.irq = IRQIO_C70, .name = "C70", .desc = "[I/O] 3270"},
{.irq = IRQIO_TAP, .name = "TAP", .desc = "[I/O] Tape"},
{.irq = IRQIO_VMR, .name = "VMR", .desc = "[I/O] Unit Record Devices"},
{.irq = IRQIO_LCS, .name = "LCS", .desc = "[I/O] LCS"},
{.irq = IRQIO_CLW, .name = "CLW", .desc = "[I/O] CLAW"},
{.irq = IRQIO_CTC, .name = "CTC", .desc = "[I/O] CTC"},
{.irq = IRQIO_APB, .name = "APB", .desc = "[I/O] AP Bus"},
{.irq = IRQIO_ADM, .name = "ADM", .desc = "[I/O] EADM Subchannel"},
{.irq = IRQIO_CSC, .name = "CSC", .desc = "[I/O] CHSC Subchannel"},
{.irq = IRQIO_PCI, .name = "PCI", .desc = "[I/O] PCI Interrupt" },
{.irq = IRQIO_MSI, .name = "MSI", .desc = "[I/O] MSI Interrupt" },
{.irq = IRQIO_VIR, .name = "VIR", .desc = "[I/O] Virtual I/O Devices"},
{.irq = IRQIO_VAI, .name = "VAI", .desc = "[I/O] Virtual I/O Devices AI"},
{.irq = NMI_NMI, .name = "NMI", .desc = "[NMI] Machine Check"},
{.irq = CPU_RST, .name = "RST", .desc = "[CPU] CPU Restart"},
};
void __init init_IRQ(void)
@ -116,33 +117,37 @@ void do_IRQ(struct pt_regs *regs, int irq)
*/
int show_interrupts(struct seq_file *p, void *v)
{
int irq = *(loff_t *) v;
int cpu;
int index = *(loff_t *) v;
int cpu, irq;
get_online_cpus();
if (irq == 0) {
if (index == 0) {
seq_puts(p, " ");
for_each_online_cpu(cpu)
seq_printf(p, "CPU%d ", cpu);
seq_putc(p, '\n');
goto out;
}
if (irq < NR_IRQS) {
if (irq >= NR_IRQS_BASE)
if (index < NR_IRQS) {
if (index >= NR_IRQS_BASE)
goto out;
seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
/* Adjust index to process irqclass_main_desc array entries */
index--;
seq_printf(p, "%s: ", irqclass_main_desc[index].name);
irq = irqclass_main_desc[index].irq;
for_each_online_cpu(cpu)
seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));
seq_putc(p, '\n');
goto out;
}
for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
for (index = 0; index < NR_ARCH_IRQS; index++) {
seq_printf(p, "%s: ", irqclass_sub_desc[index].name);
irq = irqclass_sub_desc[index].irq;
for_each_online_cpu(cpu)
seq_printf(p, "%10u ",
per_cpu(irq_stat, cpu).irqs[irq]);
if (irqclass_sub_desc[irq].desc)
seq_printf(p, " %s", irqclass_sub_desc[irq].desc);
if (irqclass_sub_desc[index].desc)
seq_printf(p, " %s", irqclass_sub_desc[index].desc);
seq_putc(p, '\n');
}
out: