Hi,
On some machines like IBM thinkpads all interrupts are sharing one irq
line. As a side effect, powertop is somewhat lost. To solve this, I've
made a hack to report the number of interrupts by irq and by irq
handler.
The aim of this was to do something quickly so it has probably not its
place upstream. If someone has better ideas or has comments, please
share it.
Also, how to support this patch in powertop is left as an exercise to
the reader :)
Regards,
Arnaud
---
fs/proc/proc_misc.c | 47 47 + 0 - 0 !
include/linux/interrupt.h | 1 1 + 0 - 0 !
kernel/irq/handle.c | 4 3 + 1 - 0 !
kernel/irq/manage.c | 1 1 + 0 - 0 !
4 files changed, 52 insertions(+), 1 deletion(-)
Index: linux-2.6.21/fs/proc/proc_misc.c
===================================================================
--- linux-2.6.21.orig/fs/proc/proc_misc.c 2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21/fs/proc/proc_misc.c 2007-05-27 16:32:53.000000000 +0200
@@ -600,6 +600,52 @@ static const struct file_operations proc
.release = seq_release,
};
+/*
+ * /proc/irq_stats
+ */
+
+int show_irq_stats(struct seq_file *p, void *v) /* In arch code ? */
+{
+ int i = *(loff_t *) v;
+ struct irqaction * action;
+ unsigned long flags;
+
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto skip;
+ for (; action; action = action->next) {
+ seq_printf(p, "%3d: ",i);
+ seq_printf(p, "%10u ", action->stats);
+ seq_printf(p, " %s", action->name);
+ seq_putc(p, '\n');
+ }
+skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+ return 0;
+}
+
+static struct seq_operations irq_stats_seq_ops = {
+ .start = int_seq_start,
+ .next = int_seq_next,
+ .stop = int_seq_stop,
+ .show = show_irq_stats
+};
+
+static int irq_stats_open(struct inode *inode, struct file *filp)
+{
+ return seq_open(filp, &irq_stats_seq_ops);
+}
+
+static const struct file_operations proc_irq_stats_operations = {
+ .open = irq_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int filesystems_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -708,6 +754,7 @@ void __init proc_misc_init(void)
#endif
create_seq_entry("stat", 0, &proc_stat_operations);
create_seq_entry("interrupts", 0, &proc_interrupts_operations);
+ create_seq_entry("irq_stats", 0, &proc_irq_stats_operations);
#ifdef CONFIG_SLAB
create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
#ifdef CONFIG_DEBUG_SLAB_LEAK
Index: linux-2.6.21/include/linux/interrupt.h
===================================================================
--- linux-2.6.21.orig/include/linux/interrupt.h 2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21/include/linux/interrupt.h 2007-05-27 14:18:35.000000000 +0200
@@ -80,6 +80,7 @@ struct irqaction {
struct irqaction *next;
int irq;
struct proc_dir_entry *dir;
+ unsigned int stats;
};
extern irqreturn_t no_action(int cpl, void *dev_id);
Index: linux-2.6.21/kernel/irq/handle.c
===================================================================
--- linux-2.6.21.orig/kernel/irq/handle.c 2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21/kernel/irq/handle.c 2007-05-27 14:21:03.000000000 +0200
@@ -139,8 +139,10 @@ irqreturn_t handle_IRQ_event(unsigned in
do {
ret = action->handler(irq, action->dev_id);
- if (ret == IRQ_HANDLED)
+ if (ret == IRQ_HANDLED) {
status |= action->flags;
+ action->stats++;
+ }
retval |= ret;
action = action->next;
} while (action);
Index: linux-2.6.21/kernel/irq/manage.c
===================================================================
--- linux-2.6.21.orig/kernel/irq/manage.c 2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21/kernel/irq/manage.c 2007-05-27 16:37:50.000000000 +0200
@@ -365,6 +365,7 @@ int setup_irq(unsigned int irq, struct i
spin_unlock_irqrestore(&desc->lock, flags);
new->irq = irq;
+ new->stats = 0;
register_irq_proc(irq);
new->dir = NULL;
register_handler_proc(irq, new);
_______________________________________________
Power mailing list
[email protected]
http://www.bughost.org/mailman/listinfo/power