[kernel] r9251 - in dists/etch/linux-2.6/debian: . patches/bugfix/hppa patches/series

Dann Frazier dannf at alioth.debian.org
Fri Aug 3 21:20:29 UTC 2007


Author: dannf
Date: Fri Aug  3 21:20:29 2007
New Revision: 9251

Log:
* [hppa] remove misuse of global_ack_eiem, fixing a race condition that
  resulted in frequent lockups on SMP systems. See: #435878

Added:
   dists/etch/linux-2.6/debian/patches/bugfix/hppa/
   dists/etch/linux-2.6/debian/patches/bugfix/hppa/remove-global_ack_eiem.patch
   dists/etch/linux-2.6/debian/patches/series/14-extra
Modified:
   dists/etch/linux-2.6/debian/changelog

Modified: dists/etch/linux-2.6/debian/changelog
==============================================================================
--- dists/etch/linux-2.6/debian/changelog	(original)
+++ dists/etch/linux-2.6/debian/changelog	Fri Aug  3 21:20:29 2007
@@ -5,8 +5,10 @@
     RFCOMM TTY layer. Thanks to Mikko Rapeli. (closes: #394742)
   * Add support for AMD/ATI SB700 hardware, see #429622
   * Add pci ids for Intel ICH9 controllers, see #435877
+  * [hppa] remove misuse of global_ack_eiem, fixing a race condition that
+    resulted in frequent lockups on SMP systems. See: #435878
 
- -- dann frazier <dannf at debian.org>  Fri, 03 Aug 2007 14:32:45 -0600
+ -- dann frazier <dannf at debian.org>  Fri, 03 Aug 2007 15:17:22 -0600
 
 linux-2.6 (2.6.18.dfsg.1-13) stable; urgency=high
 

Added: dists/etch/linux-2.6/debian/patches/bugfix/hppa/remove-global_ack_eiem.patch
==============================================================================
--- (empty file)
+++ dists/etch/linux-2.6/debian/patches/bugfix/hppa/remove-global_ack_eiem.patch	Fri Aug  3 21:20:29 2007
@@ -0,0 +1,110 @@
+From: Grant Grundler <grundler at parisc-linux.org>
+Date: Sun, 10 Jun 2007 22:31:41 +0000 (-0600)
+Subject: [PARISC] remove global_ack_eiem
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fkyle%2Fparisc-2.6.git;a=commitdiff_plain;h=462b529f91b618f4bd144bbc6184f616dfb58a1e
+
+[PARISC] remove global_ack_eiem
+
+Kudos to Thibaut Varene for spotting the (mis)use of appropriately named
+global_ack_eiem. This took a long time to figure out and both insight
+from myself, Kyle McMartin, and James Bottomley were required to narrow
+down which bit of code could have this race condition.
+
+The symptom was interrupts stopped getting delivered while some workload
+was generating IO interrupts on two different CPUs. One of the interrupt
+sources would get masked off and stay unmasked. Problem was global_ack_eiem
+was accessed with read/modified/write sequence and not protected by
+a spinlock.
+
+PA-RISC doesn't need a global ack flag though. External Interrupts
+are _always_ delivered to a single CPU (except for "global broadcast
+interrupt" which AFAIK currently is not used.) So we don't have to worry
+about any given IRQ vector getting delivered to more than one CPU.
+
+Tested on a500 and rp34xx boxen. rsync to/from gsyprf11 (a500)
+would lock up the box since NIC (tg3) interrupt and SCSI (sym2)
+were on "opposite" CPUs (2 CPU system). Put them on the same CPU
+or apply this patch and 10GB of data would rsync completely.
+
+Please apply the following critical patch.
+
+thanks,
+grant
+
+Signed-off-by: Grant Grundler <grundler at parisc-linux.org>
+Acked-by: Thibaut VARENE <T-Bone at parisc-linux.org>
+Signed-off-by: Kyle McMartin <kyle at parisc-linux.org>
+---
+
+diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
+index c5c9125..76ce5e3 100644
+--- a/arch/parisc/kernel/irq.c
++++ b/arch/parisc/kernel/irq.c
+@@ -46,14 +46,10 @@ extern irqreturn_t ipi_interrupt(int, void *);
+ static volatile unsigned long cpu_eiem = 0;
+ 
+ /*
+-** ack bitmap ... habitually set to 1, but reset to zero
++** local ACK bitmap ... habitually set to 1, but reset to zero
+ ** between ->ack() and ->end() of the interrupt to prevent
+ ** re-interruption of a processing interrupt.
+ */
+-static volatile unsigned long global_ack_eiem = ~0UL;
+-/*
+-** Local bitmap, same as above but for per-cpu interrupts
+-*/
+ static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
+ 
+ static void cpu_disable_irq(unsigned int irq)
+@@ -94,13 +90,11 @@ void cpu_ack_irq(unsigned int irq)
+ 	int cpu = smp_processor_id();
+ 
+ 	/* Clear in EIEM so we can no longer process */
+-	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+-		per_cpu(local_ack_eiem, cpu) &= ~mask;
+-	else
+-		global_ack_eiem &= ~mask;
++	per_cpu(local_ack_eiem, cpu) &= ~mask;
+ 
+ 	/* disable the interrupt */
+-	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
++	set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
++
+ 	/* and now ack it */
+ 	mtctl(mask, 23);
+ }
+@@ -111,13 +105,10 @@ void cpu_end_irq(unsigned int irq)
+ 	int cpu = smp_processor_id();
+ 
+ 	/* set it in the eiems---it's no longer in process */
+-	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
+-		per_cpu(local_ack_eiem, cpu) |= mask;
+-	else
+-		global_ack_eiem |= mask;
++	per_cpu(local_ack_eiem, cpu) |= mask;
+ 
+ 	/* enable the interrupt */
+-	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
++	set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
+ }
+ 
+ #ifdef CONFIG_SMP
+@@ -354,8 +345,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
+ 	local_irq_disable();
+ 	irq_enter();
+ 
+-	eirr_val = mfctl(23) & cpu_eiem & global_ack_eiem &
+-		per_cpu(local_ack_eiem, cpu);
++	eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu);
+ 	if (!eirr_val)
+ 		goto set_out;
+ 	irq = eirr_to_irq(eirr_val);
+@@ -381,7 +371,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
+ 	return;
+ 
+  set_out:
+-	set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
++	set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
+ 	goto out;
+ }
+ 

Added: dists/etch/linux-2.6/debian/patches/series/14-extra
==============================================================================
--- (empty file)
+++ dists/etch/linux-2.6/debian/patches/series/14-extra	Fri Aug  3 21:20:29 2007
@@ -0,0 +1 @@
++ bugfix/hppa/remove-global_ack_eiem.patch hppa



More information about the Kernel-svn-changes mailing list