]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.arch/ppc-axon-missing-msi-workaround-5.diff
Imported linux-2.6.27.39 suse/xen patches.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / ppc-axon-missing-msi-workaround-5.diff
diff --git a/src/patches/suse-2.6.27.31/patches.arch/ppc-axon-missing-msi-workaround-5.diff b/src/patches/suse-2.6.27.31/patches.arch/ppc-axon-missing-msi-workaround-5.diff
deleted file mode 100644 (file)
index 29d11c4..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-From: Arnd Bergmann <arnd.bergmann@de.ibm.com>
-Subject: powerpc/cell/axon-msi: retry on missing interrupt
-References: bnc#445964,bnc#467633
-
-The MSI capture logic on the axon bridge can sometimes
-lose interrupts in case of high DMA and interrupt load,
-when it signals an MSI interrupt to the MPIC interrupt
-controller while we are already handling another MSI.
-
-Each MSI vector gets written into a FIFO buffer in main
-memory using DMA, and that DMA access is normally flushed
-by the actual interrupt packet on the IOIF. An MMIO
-register in the MSIC holds the position of the last
-entry in the FIFO buffer that was written. However,
-reading that position does not flush the DMA, so that
-we can observe stale data in the buffer.
-
-In a stress test, we have observed the DMA to arrive
-up to 14 microseconds after reading the register.
-We can reliably detect this conditioning by writing
-an invalid MSI vector into the FIFO buffer after
-reading from it, assuming that all MSIs we get
-are valid. After detecting an invalid MSI vector,
-we udelay(1) in the interrupt cascade for up to
-100 times before giving up.
-
-Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-Acked-by: John Jolly <jjolly@novell.com>
-
-commit 23e0e8afafd9ac065d81506524adf3339584044b
-Author: Arnd Bergmann <arnd@arndb.de>
-Date:   Fri Dec 12 09:19:50 2008 +0000
-
-    powerpc/cell/axon-msi: Fix MSI after kexec
-    
-    Commit d015fe995 'powerpc/cell/axon-msi: Retry on missing interrupt'
-    has turned a rare failure to kexec on QS22 into a reproducible
-    error, which we have now analysed.
-    
-    The problem is that after a kexec, the MSIC hardware still points
-    into the middle of the old ring buffer.  We set up the ring buffer
-    during reboot, but not the offset into it.  On older kernels, this
-    would cause a storm of thousands of spurious interrupts after a
-    kexec, which would most of the time get dropped silently.
-    
-    With the new code, we time out on each interrupt, waiting for
-    it to become valid.  If more interrupts come in that we time
-    out on, this goes on indefinitely, which eventually leads to
-    a hard crash.
-    
-    The solution in this commit is to read the current offset from
-    the MSIC when reinitializing it.  This now works correctly, as
-    expected.
-    
-    Reported-by: Dirk Herrendoerfer <d.herrendoerfer@de.ibm.com>
-    Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-    Acked-by: Michael Ellerman <michael@ellerman.id.au>
-    Signed-off-by: Paul Mackerras <paulus@samba.org>
-
-
----
- arch/powerpc/platforms/cell/axon_msi.c |   39 ++++++++++++++++++++++++++++-----
- 1 file changed, 34 insertions(+), 5 deletions(-)
-
---- a/arch/powerpc/platforms/cell/axon_msi.c
-+++ b/arch/powerpc/platforms/cell/axon_msi.c
-@@ -95,6 +95,7 @@ static void axon_msi_cascade(unsigned in
-       struct axon_msic *msic = get_irq_data(irq);
-       u32 write_offset, msi;
-       int idx;
-+      int retry = 0;
-       write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
-       pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
-@@ -102,7 +103,7 @@ static void axon_msi_cascade(unsigned in
-       /* write_offset doesn't wrap properly, so we have to mask it */
-       write_offset &= MSIC_FIFO_SIZE_MASK;
--      while (msic->read_offset != write_offset) {
-+      while (msic->read_offset != write_offset && retry < 100) {
-               idx  = msic->read_offset / sizeof(__le32);
-               msi  = le32_to_cpu(msic->fifo_virt[idx]);
-               msi &= 0xFFFF;
-@@ -110,13 +111,37 @@ static void axon_msi_cascade(unsigned in
-               pr_debug("axon_msi: woff %x roff %x msi %x\n",
-                         write_offset, msic->read_offset, msi);
-+              if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) {
-+                      generic_handle_irq(msi);
-+                      msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
-+              } else {
-+                      /*
-+                       * Reading the MSIC_WRITE_OFFSET_REG does not
-+                       * reliably flush the outstanding DMA to the
-+                       * FIFO buffer. Here we were reading stale
-+                       * data, so we need to retry.
-+                       */
-+                      udelay(1);
-+                      retry++;
-+                      pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
-+                      continue;
-+              }
-+
-+              if (retry) {
-+                      pr_debug("axon_msi: late irq 0x%x, retry %d\n",
-+                               msi, retry);
-+                      retry = 0;
-+              }
-+
-               msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
-               msic->read_offset &= MSIC_FIFO_SIZE_MASK;
-+      }
--              if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host)
--                      generic_handle_irq(msi);
--              else
--                      pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
-+      if (retry) {
-+              printk(KERN_WARNING "axon_msi: irq timed out\n");
-+
-+              msic->read_offset += MSIC_FIFO_ENTRY_SIZE;
-+              msic->read_offset &= MSIC_FIFO_SIZE_MASK;
-       }
-       desc->chip->eoi(irq);
-@@ -364,6 +389,7 @@ static int axon_msi_probe(struct of_devi
-                      dn->full_name);
-               goto out_free_fifo;
-       }
-+      memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
-       msic->irq_host = irq_alloc_host(dn, IRQ_HOST_MAP_NOMAP,
-                                       NR_IRQS, &msic_host_ops, 0);
-@@ -387,6 +413,9 @@ static int axon_msi_probe(struct of_devi
-                       MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE |
-                       MSIC_CTRL_FIFO_SIZE);
-+      msic->read_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG)
-+                              & MSIC_FIFO_SIZE_MASK;
-+
-       device->dev.platform_data = msic;
-       ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs;