Commit c01b325f authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: irq stats.

Enable irq statistics for s390*. We defined NR_IRQS to 2, one for all i/o
interrupts and one for all external interrupts.
parent 2eb5ee04
...@@ -606,6 +606,8 @@ ext_int_handler: ...@@ -606,6 +606,8 @@ ext_int_handler:
SAVE_ALL_BASE SAVE_ALL_BASE
SAVE_ALL __LC_EXT_OLD_PSW,0 SAVE_ALL __LC_EXT_OLD_PSW,0
GET_THREAD_INFO # load pointer to task_struct to R9 GET_THREAD_INFO # load pointer to task_struct to R9
l %r1,BASED(.Ldo_extint)
basr %r14,%r1
lh %r6,__LC_EXT_INT_CODE # get interruption code lh %r6,__LC_EXT_INT_CODE # get interruption code
lr %r1,%r6 # calculate index = code & 0xff lr %r1,%r6 # calculate index = code & 0xff
n %r1,BASED(.Lc0xff) n %r1,BASED(.Lc0xff)
...@@ -694,6 +696,7 @@ restart_go: ...@@ -694,6 +696,7 @@ restart_go:
*/ */
.Ls390_mcck: .long s390_do_machine_check .Ls390_mcck: .long s390_do_machine_check
.Ldo_IRQ: .long do_IRQ .Ldo_IRQ: .long do_IRQ
.Ldo_extint: .long do_extint
.Ldo_signal: .long do_signal .Ldo_signal: .long do_signal
.Ldo_softirq: .long do_softirq .Ldo_softirq: .long do_softirq
.Lentry_base: .long entry_base .Lentry_base: .long entry_base
......
...@@ -637,6 +637,7 @@ io_sigpending: ...@@ -637,6 +637,7 @@ io_sigpending:
ext_int_handler: ext_int_handler:
SAVE_ALL __LC_EXT_OLD_PSW,0 SAVE_ALL __LC_EXT_OLD_PSW,0
GET_THREAD_INFO # load pointer to task_struct to R9 GET_THREAD_INFO # load pointer to task_struct to R9
brasl %r14,do_extint
llgh %r6,__LC_EXT_INT_CODE # get interruption code llgh %r6,__LC_EXT_INT_CODE # get interruption code
lgr %r1,%r6 # calculate index = code & 0xff lgr %r1,%r6 # calculate index = code & 0xff
nill %r1,0xff nill %r1,0xff
......
...@@ -11,8 +11,11 @@ ...@@ -11,8 +11,11 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel_stat.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/s390_ext.h> #include <asm/s390_ext.h>
#include <asm/irq.h>
/* /*
* Simple hash strategy: index = code & 0xff; * Simple hash strategy: index = code & 0xff;
...@@ -98,6 +101,11 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler, ...@@ -98,6 +101,11 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
return 0; return 0;
} }
void do_extint(void)
{
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
}
EXPORT_SYMBOL(register_external_interrupt); EXPORT_SYMBOL(register_external_interrupt);
EXPORT_SYMBOL(unregister_external_interrupt); EXPORT_SYMBOL(unregister_external_interrupt);
...@@ -34,12 +34,15 @@ ...@@ -34,12 +34,15 @@
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/kernel_stat.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/cpcmd.h> #include <asm/cpcmd.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/irq.h>
/* /*
* Machine setup.. * Machine setup..
...@@ -600,3 +603,40 @@ struct seq_operations cpuinfo_op = { ...@@ -600,3 +603,40 @@ struct seq_operations cpuinfo_op = {
.stop = c_stop, .stop = c_stop,
.show = show_cpuinfo, .show = show_cpuinfo,
}; };
/*
* show_interrupts is needed by /proc/interrupts.
*/
static const char *intrclass_names[] = {
"EXT",
"I/O",
};
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
seq_puts(p, " ");
for (j=0; j<NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "CPU%d ",j);
seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
seq_printf(p, "%s: ", intrclass_names[i]);
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
#else
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
seq_putc(p, '\n');
}
return 0;
}
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/kernel_stat.h>
#include <asm/hardirq.h> #include <asm/hardirq.h>
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/irq.h>
#include "airq.h" #include "airq.h"
#include "cio.h" #include "cio.h"
...@@ -608,6 +610,7 @@ do_IRQ (struct pt_regs regs) ...@@ -608,6 +610,7 @@ do_IRQ (struct pt_regs regs)
tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID; tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID;
irb = (struct irb *) __LC_IRB; irb = (struct irb *) __LC_IRB;
do { do {
kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
/* /*
* Non I/O-subchannel thin interrupts are processed differently * Non I/O-subchannel thin interrupts are processed differently
*/ */
......
...@@ -388,10 +388,8 @@ static int kstat_read_proc(char *page, char **start, off_t off, ...@@ -388,10 +388,8 @@ static int kstat_read_proc(char *page, char **start, off_t off,
system += kstat_cpu(i).cpustat.system; system += kstat_cpu(i).cpustat.system;
idle += kstat_cpu(i).cpustat.idle; idle += kstat_cpu(i).cpustat.idle;
iowait += kstat_cpu(i).cpustat.iowait; iowait += kstat_cpu(i).cpustat.iowait;
#if !defined(CONFIG_ARCH_S390)
for (j = 0 ; j < NR_IRQS ; j++) for (j = 0 ; j < NR_IRQS ; j++)
sum += kstat_cpu(i).irqs[j]; sum += kstat_cpu(i).irqs[j];
#endif
} }
len = sprintf(page, "cpu %u %u %u %u %u\n", len = sprintf(page, "cpu %u %u %u %u %u\n",
...@@ -412,7 +410,7 @@ static int kstat_read_proc(char *page, char **start, off_t off, ...@@ -412,7 +410,7 @@ static int kstat_read_proc(char *page, char **start, off_t off,
} }
len += sprintf(page + len, "intr %u", sum); len += sprintf(page + len, "intr %u", sum);
#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA) #if !defined(CONFIG_PPC64) && !defined(CONFIG_ALPHA)
for (i = 0 ; i < NR_IRQS ; i++) for (i = 0 ; i < NR_IRQS ; i++)
len += sprintf(page + len, " %u", kstat_irqs(i)); len += sprintf(page + len, " %u", kstat_irqs(i));
#endif #endif
...@@ -440,7 +438,6 @@ static int devices_read_proc(char *page, char **start, off_t off, ...@@ -440,7 +438,6 @@ static int devices_read_proc(char *page, char **start, off_t off,
return proc_calc_metrics(page, start, off, count, eof, len); return proc_calc_metrics(page, start, off, count, eof, len);
} }
#if !defined(CONFIG_ARCH_S390)
extern int show_interrupts(struct seq_file *p, void *v); extern int show_interrupts(struct seq_file *p, void *v);
static int interrupts_open(struct inode *inode, struct file *file) static int interrupts_open(struct inode *inode, struct file *file)
{ {
...@@ -466,7 +463,6 @@ static struct file_operations proc_interrupts_operations = { ...@@ -466,7 +463,6 @@ static struct file_operations proc_interrupts_operations = {
.llseek = seq_lseek, .llseek = seq_lseek,
.release = single_release, .release = single_release,
}; };
#endif
static int filesystems_read_proc(char *page, char **start, off_t off, static int filesystems_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
...@@ -646,9 +642,7 @@ void __init proc_misc_init(void) ...@@ -646,9 +642,7 @@ void __init proc_misc_init(void)
entry->proc_fops = &proc_kmsg_operations; entry->proc_fops = &proc_kmsg_operations;
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
create_seq_entry("partitions", 0, &proc_partitions_operations); create_seq_entry("partitions", 0, &proc_partitions_operations);
#if !defined(CONFIG_ARCH_S390)
create_seq_entry("interrupts", 0, &proc_interrupts_operations); create_seq_entry("interrupts", 0, &proc_interrupts_operations);
#endif
create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
......
...@@ -8,16 +8,13 @@ ...@@ -8,16 +8,13 @@
* the definition of irqs has changed in 2.5.46: * the definition of irqs has changed in 2.5.46:
* NR_IRQS is no longer the number of i/o * NR_IRQS is no longer the number of i/o
* interrupts (65536), but rather the number * interrupts (65536), but rather the number
* of interrupt classes (6). * of interrupt classes (2).
* Only external and i/o interrupts make much sense here (CH).
*/ */
enum interruption_class { enum interruption_class {
EXTERNAL_INTERRUPT, EXTERNAL_INTERRUPT,
IO_INTERRUPT, IO_INTERRUPT,
MACHINE_CHECK_INTERRUPT,
PROGRAM_INTERRUPT,
RESTART_INTERRUPT,
SUPERVISOR_CALL,
NR_IRQS, NR_IRQS,
}; };
......
...@@ -23,9 +23,7 @@ struct cpu_usage_stat { ...@@ -23,9 +23,7 @@ struct cpu_usage_stat {
struct kernel_stat { struct kernel_stat {
struct cpu_usage_stat cpustat; struct cpu_usage_stat cpustat;
#if !defined(CONFIG_ARCH_S390)
unsigned int irqs[NR_IRQS]; unsigned int irqs[NR_IRQS];
#endif
}; };
DECLARE_PER_CPU(struct kernel_stat, kstat); DECLARE_PER_CPU(struct kernel_stat, kstat);
...@@ -36,7 +34,6 @@ DECLARE_PER_CPU(struct kernel_stat, kstat); ...@@ -36,7 +34,6 @@ DECLARE_PER_CPU(struct kernel_stat, kstat);
extern unsigned long nr_context_switches(void); extern unsigned long nr_context_switches(void);
#if !defined(CONFIG_ARCH_S390)
/* /*
* Number of interrupts per specific IRQ source, since bootup * Number of interrupts per specific IRQ source, since bootup
*/ */
...@@ -50,6 +47,5 @@ static inline int kstat_irqs(int irq) ...@@ -50,6 +47,5 @@ static inline int kstat_irqs(int irq)
return sum; return sum;
} }
#endif
#endif /* _LINUX_KERNEL_STAT_H */ #endif /* _LINUX_KERNEL_STAT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment