Commit ab6b1810 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] seq_file version of /proc/interrupts

From: corbet@lwn.net (Jonathan Corbet)

This converts all architectures' /proc/interrupts implementation over to
seq_file.  We need this for SMP machines with ridiculous numbers of CPUs and
if you convert one arch, you have to convert them all...
parent b031787e
......@@ -529,19 +529,21 @@ show_interrupts(struct seq_file *p, void *v)
#ifdef CONFIG_SMP
int j;
#endif
int i;
int i = *(loff_t *) v;
struct irqaction * action;
unsigned long flags;
#ifdef CONFIG_SMP
if (i == 0) {
seq_puts(p, " ");
for (i = 0; i < NR_CPUS; i++)
if (cpu_online(i))
seq_printf(p, "CPU%d ", i);
seq_putc(p, '\n');
}
#endif
for (i = 0; i < ACTUAL_NR_IRQS; i++) {
if (i < ACTUAL_NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
......@@ -568,7 +570,7 @@ show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
unlock:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
} else if (i == ACTUAL_NR_IRQS) {
#ifdef CONFIG_SMP
seq_puts(p, "IPI: ");
for (i = 0; i < NR_CPUS; i++)
......@@ -577,6 +579,7 @@ show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
#endif
seq_printf(p, "ERR: %10lu\n", irq_err_count);
}
return 0;
}
......
......@@ -169,11 +169,11 @@ void disable_irq_wake(unsigned int irq)
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
struct irqaction * action;
unsigned long flags;
for (i = 0 ; i < NR_IRQS ; i++) {
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_controller_lock, flags);
action = irq_desc[i].action;
if (!action)
......@@ -187,12 +187,12 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
unlock:
spin_unlock_irqrestore(&irq_controller_lock, flags);
}
} else if (i == NR_IRQS) {
#ifdef CONFIG_ARCH_ACORN
show_fiq_list(p, v);
#endif
seq_printf(p, "Err: %10lu\n", irq_err_count);
}
return 0;
}
......
......@@ -135,10 +135,10 @@ void enable_irq(unsigned int irq)
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
struct irqaction * action;
for (i = 0 ; i < NR_IRQS ; i++) {
if (i < NR_IRQS) {
action = irq_desc[i].action;
if (!action)
continue;
......@@ -148,10 +148,10 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, ", %s", action->name);
}
seq_putc(p, '\n');
}
} else if (i == NR_IRQS) {
show_fiq_list(p, v);
seq_printf(p, "Err: %10lu\n", irq_err_count);
}
return 0;
}
......
......@@ -89,11 +89,11 @@ static struct irqaction *irq_action[NR_IRQS];
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
struct irqaction * action;
unsigned long flags;
for (i = 0; i < NR_IRQS; i++) {
if (i < NR_IRQS) {
local_irq_save(flags);
action = irq_action[i];
if (!action)
......
......@@ -228,9 +228,9 @@ asmlinkage void process_int(int vec, struct pt_regs *fp)
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
for (i = 0; i < NR_IRQS; i++) {
if (i < NR_IRQS) {
if (irq_list[i]) {
seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
seq_printf(p, "%s\n", irq_list[i]->devname);
......
......@@ -280,9 +280,9 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
for (i = 0; i < NR_IRQS; i++) {
if (i < NR_IRQS) {
if (irq_list[i]) {
seq_printf(p, "%3d: %10u ",i,irq_list[i]->count);
seq_printf(p, "%s\n", irq_list[i]->devname);
......
......@@ -138,17 +138,19 @@ atomic_t irq_mis_count;
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int i = *(loff_t *) v, j;
struct irqaction * action;
unsigned long flags;
if (i == 0) {
seq_printf(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++) {
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
......@@ -170,7 +172,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
} else if (i == NR_IRQS) {
seq_printf(p, "NMI: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
......@@ -189,9 +191,13 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
#endif
#endif
}
return 0;
}
#ifdef CONFIG_SMP
inline void synchronize_irq(unsigned int irq)
{
......
......@@ -160,18 +160,20 @@ atomic_t irq_mis_count;
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int j, i = *(loff_t *) v;
struct irqaction * action;
irq_desc_t *idesc;
unsigned long flags;
if (i == 0) {
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++) {
if (i < NR_IRQS) {
idesc = irq_descp(i);
spin_lock_irqsave(&idesc->lock, flags);
action = idesc->action;
......@@ -194,7 +196,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&idesc->lock, flags);
}
} else if (i == NR_IRQS) {
seq_puts(p, "NMI: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
......@@ -213,6 +215,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
#endif
#endif
}
return 0;
}
......
......@@ -253,18 +253,17 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
/* autovector interrupts */
if (mach_default_handler) {
for (i = 0; i < SYS_IRQS; i++) {
if (i < SYS_IRQS) {
seq_printf(p, "auto %2d: %10u ", i,
i ? kstat_cpu(0).irqs[i] : num_spurious);
seq_puts(p, " ");
seq_printf(p, "%s\n", irq_list[i].devname);
}
}
} else if (i == SYS_IRQS)
mach_get_irq_list(p, v);
return 0;
}
......
......@@ -254,9 +254,9 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
for (i = 0; i < NR_IRQS; i++) {
if (i < NR_IRQS) {
if (irq_list[i].flags & IRQ_FLG_STD)
continue;
......@@ -269,7 +269,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "%s\n", irq_list[i].devname);
}
if (mach_get_irq_list)
if (i == NR_IRQS && mach_get_irq_list)
mach_get_irq_list(p, v);
return(0);
}
......
......@@ -198,9 +198,9 @@ EXPORT_SYMBOL(free_irq);
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
for (i = 0; i < NR_IRQS; i++) {
if (i < NR_IRQS) {
if (int_irq_list[i].flags & IRQ_FLG_STD)
continue;
......@@ -211,6 +211,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, " ");
seq_printf(p, "%s\n", int_irq_list[i].devname);
}
if (i == NR_IRQS)
seq_printf(p, " : %10u spurious\n", num_spurious);
return 0;
......
......@@ -278,9 +278,9 @@ void M68360_disable_irq(unsigned int irq)
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
for (i = 0; i < NR_IRQS; i++) {
if (i < NR_IRQS) {
if (int_irq_list[i].flags & IRQ_FLG_STD)
continue;
......@@ -291,6 +291,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, " ");
seq_printf(p, "%s\n", int_irq_list[i].devname);
}
if (i == NR_IRQS)
seq_printf(p, " : %10u spurious\n", num_spurious);
return 0;
......
......@@ -85,17 +85,19 @@ atomic_t irq_err_count;
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int i = *(loff_t *) v, j;
struct irqaction * action;
unsigned long flags;
if (i == 0) {
seq_printf(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++) {
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
......@@ -117,10 +119,10 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
} else if (i == NR_IRQS) {
seq_putc(p, '\n');
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
}
return 0;
}
......
......@@ -215,29 +215,30 @@ EXPORT_SYMBOL(enable_irq);
int show_interrupts(struct seq_file *p, void *v)
{
#ifdef CONFIG_PROC_FS
unsigned int regnr = 0;
unsigned int regnr = *(loff_t *) v, i;
if (regnr == 0) {
seq_puts(p, " ");
#ifdef CONFIG_SMP
for (regnr = 0; regnr < NR_CPUS; regnr++)
for (i = 0; i < NR_CPUS; i++)
#endif
seq_printf(p, " CPU%02d ", regnr);
seq_printf(p, " CPU%02d ", i);
#ifdef PARISC_IRQ_CR16_COUNTS
seq_printf(p, "[min/avg/max] (CPU cycle counts)");
#endif
seq_putc(p, '\n');
}
/* We don't need *irqsave lock variants since this is
** only allowed to change while in the base context.
*/
spin_lock(&irq_lock);
for (regnr = 0; regnr < NR_IRQ_REGS; regnr++) {
unsigned int i;
if (regnr < NR_IRQ_REGS) {
struct irq_region *region = irq_region[regnr];
if (!region || !region->action)
continue;
goto skip;
for (i = 0; i <= MAX_CPU_IRQ; i++) {
struct irqaction *action = &region->action[i];
......@@ -286,9 +287,9 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
}
}
skip:
spin_unlock(&irq_lock);
seq_putc(p, '\n');
#endif /* CONFIG_PROC_FS */
return 0;
}
......
......@@ -346,17 +346,19 @@ void enable_irq(unsigned int irq)
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int i = *(loff_t *) v, j;
struct irqaction * action;
unsigned long flags;
if (i == 0) {
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++) {
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if ( !action || !action->handler )
......@@ -381,7 +383,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
} else if (i == NR_IRQS) {
#ifdef CONFIG_TAU_INT
if (tau_initialized){
seq_puts(p, "TAU: ");
......@@ -397,6 +399,7 @@ int show_interrupts(struct seq_file *p, void *v)
atomic_read(&ipi_recv), atomic_read(&ipi_sent));
#endif
seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
}
return 0;
}
......
......@@ -323,18 +323,20 @@ EXPORT_SYMBOL(enable_irq);
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int i = *(loff_t *) v, j;
struct irqaction * action;
unsigned long flags;
if (i == 0) {
seq_printf(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++) {
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action || !action->handler)
......@@ -359,7 +361,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
} else if (i == NR_IRQS)
seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
return 0;
}
......
......@@ -617,17 +617,17 @@ static const char *intrclass_names[] = {
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int i = *(loff_t *) v, j;
if (i == 0) {
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++) {
if (i < NR_IRQS) {
seq_printf(p, "%s: ", intrclass_names[i]);
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
......
......@@ -93,17 +93,19 @@ struct hw_interrupt_type no_irq_type = {
#if defined(CONFIG_PROC_FS)
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int i = *(loff_t *) v, j;
struct irqaction * action;
unsigned long flags;
if (i == 0) {
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 < ACTUAL_NR_IRQS ; i++) {
if (i < ACTUAL_NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
......
......@@ -102,7 +102,7 @@ struct irqaction *irq_action[NR_IRQS] = {
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
struct irqaction * action;
unsigned long flags;
#ifdef CONFIG_SMP
......@@ -114,7 +114,7 @@ int show_interrupts(struct seq_file *p, void *v)
return show_sun4d_interrupts(p, v);
}
for (i = 0 ; i < NR_IRQS ; i++) {
if (i < NR_IRQS) {
local_irq_save(flags);
action = *(i + irq_action);
if (!action)
......
......@@ -75,13 +75,13 @@ spinlock_t sun4d_imsk_lock = SPIN_LOCK_UNLOCKED;
int show_sun4d_interrupts(struct seq_file *p, void *v)
{
int i, j = 0, k = 0, sbusl;
int i = *(loff_t *) v, j = 0, k = 0, sbusl;
struct irqaction * action;
#ifdef CONFIG_SMP
int x;
#endif
for (i = 0 ; i < NR_IRQS ; i++) {
if (i < NR_IRQS) {
sbusl = pil_to_sbus[i];
if (!sbusl) {
action = *(i + irq_action);
......
......@@ -128,14 +128,14 @@ static void register_irq_proc (unsigned int irq);
int show_interrupts(struct seq_file *p, void *v)
{
unsigned long flags;
int i;
int i = *(loff_t *) v;
struct irqaction *action;
#ifdef CONFIG_SMP
int j;
#endif
spin_lock_irqsave(&irq_action_lock, flags);
for (i = 0; i < (NR_IRQS + 1); i++) {
if (i <= NR_IRQS) {
if (!(action = *(i + irq_action)))
continue;
seq_printf(p, "%3d: ", i);
......
......@@ -81,16 +81,18 @@ volatile unsigned long irq_err_count, spurious_count;
int show_interrupts(struct seq_file *p, void *v)
{
int i;
int i = *(loff_t *) v;
struct irqaction * action;
unsigned long flags;
if (i == 0) {
seq_puts(p, " ");
for (i=0; i < 1 /*smp_num_cpus*/; i++)
seq_printf(p, "CPU%d ", i);
seq_putc(p, '\n');
}
for (i = 0 ; i < NR_IRQS ; i++) {
if (i < NR_IRQS) {
int j, count, num;
const char *type_name = irq_desc[i].handler->typename;
spin_lock_irqsave(&irq_desc[j].lock, flags);
......@@ -121,7 +123,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[j].lock, flags);
}
} else if (i == NR_IRQS)
seq_printf(p, "ERR: %10lu\n", irq_err_count);
return 0;
}
......
......@@ -138,17 +138,19 @@ atomic_t irq_mis_count;
int show_interrupts(struct seq_file *p, void *v)
{
int i, j;
int i = *(loff_t *) v, j;
struct irqaction * action;
unsigned long flags;
if (i == 0) {
seq_printf(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++) {
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
......@@ -170,7 +172,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
} else if (i == NR_IRQS) {
seq_printf(p, "NMI: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
......@@ -189,6 +191,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
#endif
#endif
}
return 0;
}
......
......@@ -473,30 +473,46 @@ static int devices_read_proc(char *page, char **start, off_t off,
return proc_calc_metrics(page, start, off, count, eof, len);
}
extern int show_interrupts(struct seq_file *p, void *v);
static int interrupts_open(struct inode *inode, struct file *file)
/*
* /proc/interrupts
*/
static void *int_seq_start(struct seq_file *f, loff_t *pos)
{
unsigned size = 4096 * (1 + num_online_cpus() / 8);
char *buf = kmalloc(size, GFP_KERNEL);
struct seq_file *m;
int res;
return (*pos <= NR_IRQS) ? pos : NULL;
}
if (!buf)
return -ENOMEM;
res = single_open(file, show_interrupts, NULL);
if (!res) {
m = file->private_data;
m->buf = buf;
m->size = size;
} else
kfree(buf);
return res;
static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
{
(*pos)++;
if (*pos > NR_IRQS)
return NULL;
return pos;
}
static void int_seq_stop(struct seq_file *f, void *v)
{
/* Nothing to do */
}
extern int show_interrupts(struct seq_file *f, void *v); /* In arch code */
static struct seq_operations int_seq_ops = {
.start = int_seq_start,
.next = int_seq_next,
.stop = int_seq_stop,
.show = show_interrupts
};
int interrupts_open(struct inode *inode, struct file *filp)
{
return seq_open(filp, &int_seq_ops);
}
static struct file_operations proc_interrupts_operations = {
.open = interrupts_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.release = seq_release,
};
static int filesystems_read_proc(char *page, char **start, off_t off,
......
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