Patch from Zwane Mwaikambo <zwane@linuxpower.ca>

On SMP or preemptible kernels, every instance of show_interrupts() is oopsily
racy wrt request_irq() and free_irq().

Fix that up by taking the irq_desc_t's lock while walking the action list.


 arch/alpha/kernel/irq.c                   |   15 ++++++++++-----
 arch/arm/kernel/irq.c                     |   11 ++++++++---
 arch/cris/kernel/irq.c                    |    6 +++++-
 arch/i386/kernel/irq.c                    |    7 ++++++-
 arch/ia64/kernel/irq.c                    |    8 ++++++--
 arch/mips/baget/irq.c                     |    6 +++++-
 arch/mips/dec/irq.c                       |    6 +++++-
 arch/mips/ite-boards/generic/irq.c        |    9 ++++++++-
 arch/mips/kernel/irq.c                    |    8 ++++++--
 arch/mips/kernel/old-irq.c                |    6 +++++-
 arch/mips/mips-boards/atlas/atlas_int.c   |    7 ++++++-
 arch/mips/philips/nino/irq.c              |    6 +++++-
 arch/mips64/mips-boards/atlas/atlas_int.c |    7 ++++++-
 arch/mips64/mips-boards/malta/malta_int.c |   11 +++++++++--
 arch/mips64/sgi-ip22/ip22-int.c           |   11 +++++++++--
 arch/mips64/sgi-ip27/ip27-irq.c           |    6 +++++-
 arch/ppc/kernel/irq.c                     |    8 ++++++--
 arch/ppc64/kernel/irq.c                   |    6 +++++-
 arch/sh/kernel/irq.c                      |    8 ++++++--
 arch/sparc/kernel/irq.c                   |    6 +++++-
 arch/v850/kernel/irq.c                    |    9 ++++++---
 arch/x86_64/kernel/irq.c                  |    8 ++++++--
 22 files changed, 138 insertions(+), 37 deletions(-)

diff -puN arch/alpha/kernel/irq.c~show_interrupts-locking-fix arch/alpha/kernel/irq.c
--- 25/arch/alpha/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/alpha/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -515,6 +515,7 @@ show_interrupts(struct seq_file *p, void
 #endif
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 #ifdef CONFIG_SMP
 	seq_puts(p, "           ");
@@ -525,9 +526,10 @@ show_interrupts(struct seq_file *p, void
 #endif
 
 	for (i = 0; i < ACTUAL_NR_IRQS; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -538,15 +540,18 @@ show_interrupts(struct seq_file *p, void
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %c%s",
-			     (action->flags & SA_INTERRUPT)?'+':' ',
-			     action->name);
+			(action->flags & SA_INTERRUPT)?'+':' ',
+			action->name);
 
 		for (action=action->next; action; action = action->next) {
 			seq_printf(p, ", %c%s",
-				     (action->flags & SA_INTERRUPT)?'+':' ',
-				     action->name);
+				  (action->flags & SA_INTERRUPT)?'+':' ',
+				   action->name);
 		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #if CONFIG_SMP
 	seq_puts(p, "IPI: ");
diff -puN arch/arm/kernel/irq.c~show_interrupts-locking-fix arch/arm/kernel/irq.c
--- 25/arch/arm/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/arm/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -165,17 +165,22 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_controller_lock, flags);
 	    	action = irq_desc[i].action;
 		if (!action)
-			continue;
+			goto unlock;
+
 		seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
 		seq_printf(p, "  %s", action->name);
-		for (action = action->next; action; action = action->next) {
+		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
-		}
+
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_controller_lock, flags);
 	}
 
 #ifdef CONFIG_ARCH_ACORN
diff -puN arch/cris/kernel/irq.c~show_interrupts-locking-fix arch/cris/kernel/irq.c
--- 25/arch/cris/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/cris/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -228,11 +228,13 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0; i < NR_IRQS; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %10u %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -243,6 +245,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/i386/kernel/irq.c~show_interrupts-locking-fix arch/i386/kernel/irq.c
--- 25/arch/i386/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/i386/kernel/irq.c	2003-03-07 18:55:09.000000000 -0800
@@ -141,6 +141,7 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -149,9 +150,10 @@ int show_interrupts(struct seq_file *p, 
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -166,7 +168,10 @@ int show_interrupts(struct seq_file *p, 
 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
diff -puN arch/ia64/kernel/irq.c~show_interrupts-locking-fix arch/ia64/kernel/irq.c
--- 25/arch/ia64/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/ia64/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -154,6 +154,7 @@ int show_interrupts(struct seq_file *p, 
 	int i, j;
 	struct irqaction * action;
 	irq_desc_t *idesc;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -163,9 +164,10 @@ int show_interrupts(struct seq_file *p, 
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		idesc = irq_desc(i);
+		spin_lock_irqsave(&idesc->lock, flags);
 		action = idesc->action;
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -176,10 +178,12 @@ int show_interrupts(struct seq_file *p, 
 #endif
 		seq_printf(p, " %14s", idesc->handler->typename);
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
+		
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&idesc->lock, flags);
 	}
 	seq_puts(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)
diff -puN arch/mips64/mips-boards/atlas/atlas_int.c~show_interrupts-locking-fix arch/mips64/mips-boards/atlas/atlas_int.c
--- 25/arch/mips64/mips-boards/atlas/atlas_int.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips64/mips-boards/atlas/atlas_int.c	2003-03-07 18:30:28.000000000 -0800
@@ -95,11 +95,13 @@ int show_interrupts(struct seq_file *p, 
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -110,6 +112,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -239,6 +243,7 @@ void __init init_IRQ(void)
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -puN arch/mips64/mips-boards/malta/malta_int.c~show_interrupts-locking-fix arch/mips64/mips-boards/malta/malta_int.c
--- 25/arch/mips64/mips-boards/malta/malta_int.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips64/mips-boards/malta/malta_int.c	2003-03-07 18:30:28.000000000 -0800
@@ -125,11 +125,13 @@ int show_interrupts(struct seq_file *p, 
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 8; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -140,11 +142,14 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0; i < MALTAINT_END; i++, num++) {
+		local_irq_save(flags);
 		action = hw0_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -155,6 +160,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_puts(p, " [hw0]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/mips64/sgi-ip22/ip22-int.c~show_interrupts-locking-fix arch/mips64/sgi-ip22/ip22-int.c
--- 25/arch/mips64/sgi-ip22/ip22-int.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips64/sgi-ip22/ip22-int.c	2003-03-07 18:30:28.000000000 -0800
@@ -237,11 +237,13 @@ int show_interrupts(struct seq_file *p, 
 	int i;
 	int num = 0;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 16 ; i++, num++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_1;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -252,11 +254,14 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_puts(p, " [on-chip]\n");
+skip_1:
+		local_irq_restore(flags);
 	}
 	for (i = 0 ; i < 24 ; i++, num++) {
+		local_irq_save(flags);
 		action = local_irq_action[i];
 		if (!action) 
-			continue;
+			goto skip_2;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -267,6 +272,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_puts(p, " [local]\n");
+skip_2:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/mips64/sgi-ip27/ip27-irq.c~show_interrupts-locking-fix arch/mips64/sgi-ip27/ip27-irq.c
--- 25/arch/mips64/sgi-ip27/ip27-irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips64/sgi-ip27/ip27-irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -141,11 +141,13 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i],
 		               (action->flags & SA_INTERRUPT) ? '+' : ' ',
 		               action->name);
@@ -156,6 +158,8 @@ int show_interrupts(struct seq_file *p, 
 			                action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/mips/baget/irq.c~show_interrupts-locking-fix arch/mips/baget/irq.c
--- 25/arch/mips/baget/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips/baget/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -146,11 +146,13 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < BAGET_IRQ_NR ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -161,6 +163,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/mips/dec/irq.c~show_interrupts-locking-fix arch/mips/dec/irq.c
--- 25/arch/mips/dec/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips/dec/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -97,11 +97,13 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < 32; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action)
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 				i, kstat_cpu(0).irqs[i],
 				(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -112,6 +114,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/mips/ite-boards/generic/irq.c~show_interrupts-locking-fix arch/mips/ite-boards/generic/irq.c
--- 25/arch/mips/ite-boards/generic/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips/ite-boards/generic/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -222,6 +222,7 @@ int show_interrupts(struct seq_file *p, 
 {
         int i, j;
         struct irqaction * action;
+	unsigned long flags;
 
         seq_printf(p, "           ");
         for (j=0; j<smp_num_cpus; j++)
@@ -229,20 +230,25 @@ int show_interrupts(struct seq_file *p, 
 	seq_putc(p, '\n');
 
         for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
                 action = irq_desc[i].action;
+
                 if ( !action || !action->handler )
-                        continue;
+                        goto skip;
                 seq_printf(p, "%3d: ", i);		
                 seq_printf(p, "%10u ", kstat_irqs(i));
                 if ( irq_desc[i].handler )		
                         seq_printf(p, " %s ", irq_desc[i].handler->typename );
                 else
                         seq_puts(p, "  None      ");
+
                 seq_printf(p, "    %s",action->name);
                 for (action=action->next; action; action = action->next) {
                         seq_printf(p, ", %s", action->name);
                 }
                 seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
         }
         seq_printf(p, "BAD: %10lu\n", spurious_count);
         return 0;
@@ -437,6 +443,7 @@ void __init init_IRQ(void)
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &it8172_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 	/*
diff -puN arch/mips/kernel/irq.c~show_interrupts-locking-fix arch/mips/kernel/irq.c
--- 25/arch/mips/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -73,17 +73,19 @@ volatile unsigned long irq_err_count, sp
 int show_interrupts(struct seq_file *p, void *v)
 {
 	struct irqaction * action;
+	unsigned long flags;
 	int i;
-
+	
 	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++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -92,6 +94,8 @@ int show_interrupts(struct seq_file *p, 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -puN arch/mips/kernel/old-irq.c~show_interrupts-locking-fix arch/mips/kernel/old-irq.c
--- 25/arch/mips/kernel/old-irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips/kernel/old-irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -128,11 +128,13 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	for (i = 0 ; i < 32 ; i++) {
+		local_irq_save(flags);
 		action = irq_action[i];
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat_cpu(0).irqs[i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -143,6 +145,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/mips/mips-boards/atlas/atlas_int.c~show_interrupts-locking-fix arch/mips/mips-boards/atlas/atlas_int.c
--- 25/arch/mips/mips-boards/atlas/atlas_int.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips/mips-boards/atlas/atlas_int.c	2003-03-07 18:30:28.000000000 -0800
@@ -99,11 +99,13 @@ int show_interrupts(struct seq_file *p, 
 	int i;
 	int num = 0;
 	struct irqaction *action;
+	unsigned long flags;
 
 	for (i = 0; i < ATLASINT_END; i++, num++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat_cpu(0).irqs[num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -114,6 +116,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_printf(p, " [hw0]\n");
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
@@ -243,6 +247,7 @@ void __init init_IRQ(void)
 		irq_desc[i].action	= 0;
 		irq_desc[i].depth	= 1;
 		irq_desc[i].handler	= &atlas_irq_type;
+		spin_lock_init(&irq_desc[i].lock);
 	}
 
 #ifdef CONFIG_REMOTE_DEBUG
diff -puN arch/mips/philips/nino/irq.c~show_interrupts-locking-fix arch/mips/philips/nino/irq.c
--- 25/arch/mips/philips/nino/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/mips/philips/nino/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -119,11 +119,13 @@ int show_interrupts(struct seq_file *p, 
 {
     int i;
     struct irqaction *action;
+    unsigned long flags;
 
     for (i = 0; i < NR_IRQS; i++) {
+	local_irq_save(flags);
 	action = irq_action[i];
 	if (!action)
-	    continue;
+	    goto skip;
 	seq_printf(p, "%2d: %8d %c %s",
 		       i, kstat_cpu(0).irqs[i],
 		       (action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -134,6 +136,8 @@ int show_interrupts(struct seq_file *p, 
 			   action->name);
 	}
 	seq_putc(p, '\n');
+skip:
+	local_irq_restore(flags);
     }
     return 0;
 }
diff -puN arch/ppc64/kernel/irq.c~show_interrupts-locking-fix arch/ppc64/kernel/irq.c
--- 25/arch/ppc64/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/ppc64/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -341,6 +341,7 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++) {
@@ -350,9 +351,10 @@ int show_interrupts(struct seq_file *p, 
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action || !action->handler)
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++) {
@@ -371,6 +373,8 @@ int show_interrupts(struct seq_file *p, 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
 	return 0;
diff -puN arch/ppc/kernel/irq.c~show_interrupts-locking-fix arch/ppc/kernel/irq.c
--- 25/arch/ppc/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/ppc/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -346,6 +346,7 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -354,9 +355,10 @@ int show_interrupts(struct seq_file *p, 
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if ( !action || !action->handler )
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++)
@@ -373,8 +375,10 @@ int show_interrupts(struct seq_file *p, 
 		seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
 		seq_printf(p, "    %s", action->name);
 		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
+				seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 #ifdef CONFIG_TAU_INT
 	if (tau_initialized){
diff -puN arch/sh/kernel/irq.c~show_interrupts-locking-fix arch/sh/kernel/irq.c
--- 25/arch/sh/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/sh/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -90,6 +90,7 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
@@ -97,9 +98,10 @@ int show_interrupts(struct seq_file *p, 
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
-		if (!action) 
-			continue;
+		if (!action)
+			goto unlock;
 		seq_printf(p, "%3d: ",i);
 		seq_printf(p, "%10u ", kstat_irqs(i));
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
@@ -108,6 +110,8 @@ int show_interrupts(struct seq_file *p, 
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+unlock:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	return 0;
 }
diff -puN arch/sparc/kernel/irq.c~show_interrupts-locking-fix arch/sparc/kernel/irq.c
--- 25/arch/sparc/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/sparc/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -104,6 +104,7 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 #ifdef CONFIG_SMP
 	int j;
 #endif
@@ -114,9 +115,10 @@ int show_interrupts(struct seq_file *p, 
 		return show_sun4d_interrupts(p, v);
 	}
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		local_irq_save(flags);
 	        action = *(i + irq_action);
 		if (!action) 
-		        continue;
+		        goto skip;
 		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -136,6 +138,8 @@ int show_interrupts(struct seq_file *p, 
 				action->name);
 		}
 		seq_putc(p, '\n');
+skip:
+		local_irq_restore(flags);
 	}
 	return 0;
 }
diff -puN arch/v850/kernel/irq.c~show_interrupts-locking-fix arch/v850/kernel/irq.c
--- 25/arch/v850/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/v850/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -78,6 +78,7 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
@@ -87,10 +88,10 @@ int show_interrupts(struct seq_file *p, 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		int j, count, num;
 		const char *type_name = irq_desc[i].handler->typename;
-
+		spin_lock_irqsave(&irq_desc[j].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 
 		count = 0;
 		num = -1;
@@ -108,11 +109,13 @@ int show_interrupts(struct seq_file *p, 
 			seq_printf(p, " %*s%d", 14 - prec, type_name, num);
 		} else
 			seq_printf(p, " %14s", type_name);
+		
 		seq_printf(p, "  %s", action->name);
-
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[j].lock, flags);
 	}
 	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
diff -puN arch/x86_64/kernel/irq.c~show_interrupts-locking-fix arch/x86_64/kernel/irq.c
--- 25/arch/x86_64/kernel/irq.c~show_interrupts-locking-fix	2003-03-07 18:30:28.000000000 -0800
+++ 25-akpm/arch/x86_64/kernel/irq.c	2003-03-07 18:30:28.000000000 -0800
@@ -135,6 +135,7 @@ int show_interrupts(struct seq_file *p, 
 {
 	int i, j;
 	struct irqaction * action;
+	unsigned long flags;
 
 	seq_printf(p, "           ");
 	for (j=0; j<NR_CPUS; j++)
@@ -143,9 +144,10 @@ int show_interrupts(struct seq_file *p, 
 	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			continue;
+			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
@@ -156,11 +158,13 @@ int show_interrupts(struct seq_file *p, 
 				kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
-		seq_printf(p, "  %s", action->name);
 
+		seq_printf(p, "  %s", action->name);
 		for (action=action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
 		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	}
 	seq_printf(p, "NMI: ");
 	for (j = 0; j < NR_CPUS; j++)

_