]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.arch/ppc64-eeh-msix-irq
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / ppc64-eeh-msix-irq
diff --git a/src/patches/suse-2.6.27.31/patches.arch/ppc64-eeh-msix-irq b/src/patches/suse-2.6.27.31/patches.arch/ppc64-eeh-msix-irq
new file mode 100644 (file)
index 0000000..0436ab8
--- /dev/null
@@ -0,0 +1,145 @@
+From: Mike Mason <mmlnx@us.ibm.com>
+Date: Tue, 10 Feb 2009 11:12:21 +0000 (+0000)
+Subject: powerpc/eeh: Only disable/enable LSI interrupts in EEH
+Patch-mainline: 2.6.30-rc1
+Git-commit: 8535ef05a6904429ce72671c3035dbf05e6d5edf
+References: bnc#509497
+
+powerpc/eeh: Only disable/enable LSI interrupts in EEH
+
+The EEH code disables and enables interrupts during the
+device recovery process.  This is unnecessary for MSI
+and MSI-X interrupts because they are effectively disabled
+by the DMA Stopped state when an EEH error occurs.  The
+current code is also incorrect for MSI-X interrupts.  It
+doesn't take into account that MSI-X interrupts are tracked
+in a different way than LSI/MSI interrupts.  This patch
+ensures only LSI interrupts are disabled/enabled.
+
+Signed-off-by: Mike Mason <mmlnx@us.ibm.com>
+Acked-by: Linas Vepstas <linasvepstas@gmail.com>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Acked-by: Jeff Mahoney <jeffm@suse.com>
+---
+
+ arch/powerpc/platforms/pseries/eeh_driver.c |   68 ++++++++++++++++++----------
+ 1 file changed, 45 insertions(+), 23 deletions(-)
+
+--- a/arch/powerpc/platforms/pseries/eeh_driver.c
++++ b/arch/powerpc/platforms/pseries/eeh_driver.c
+@@ -79,6 +79,40 @@ static int irq_in_use(unsigned int irq)
+       return rc;
+ }
++/**
++ * eeh_disable_irq - disable interrupt for the recovering device
++ */
++static void eeh_disable_irq(struct pci_dev *dev)
++{
++      struct device_node *dn = pci_device_to_OF_node(dev);
++
++      /* Don't disable MSI and MSI-X interrupts. They are
++       * effectively disabled by the DMA Stopped state
++       * when an EEH error occurs.
++      */
++      if (dev->msi_enabled || dev->msix_enabled)
++              return;
++
++      if (!irq_in_use(dev->irq))
++              return;
++
++      PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
++      disable_irq_nosync(dev->irq);
++}
++
++/**
++ * eeh_enable_irq - enable interrupt for the recovering device
++ */
++static void eeh_enable_irq(struct pci_dev *dev)
++{
++      struct device_node *dn = pci_device_to_OF_node(dev);
++
++      if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
++              PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
++              enable_irq(dev->irq);
++      }
++}
++
+ /* ------------------------------------------------------- */
+ /**
+  * eeh_report_error - report pci error to each device driver
+@@ -98,11 +132,8 @@ static void eeh_report_error(struct pci_
+       if (!driver)
+               return;
+-      if (irq_in_use (dev->irq)) {
+-              struct device_node *dn = pci_device_to_OF_node(dev);
+-              PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
+-              disable_irq_nosync(dev->irq);
+-      }
++      eeh_disable_irq(dev);
++
+       if (!driver->err_handler ||
+           !driver->err_handler->error_detected)
+               return;
+@@ -147,17 +178,14 @@ static void eeh_report_reset(struct pci_
+ {
+       enum pci_ers_result rc, *res = userdata;
+       struct pci_driver *driver = dev->driver;
+-      struct device_node *dn = pci_device_to_OF_node(dev);
+       if (!driver)
+               return;
+       dev->error_state = pci_channel_io_normal;
+-      if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+-              PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+-              enable_irq(dev->irq);
+-      }
++      eeh_enable_irq(dev);
++
+       if (!driver->err_handler ||
+           !driver->err_handler->slot_reset)
+               return;
+@@ -176,17 +204,14 @@ static void eeh_report_reset(struct pci_
+ static void eeh_report_resume(struct pci_dev *dev, void *userdata)
+ {
+       struct pci_driver *driver = dev->driver;
+-      struct device_node *dn = pci_device_to_OF_node(dev);
+       dev->error_state = pci_channel_io_normal;
+       if (!driver)
+               return;
+-      if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+-              PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+-              enable_irq(dev->irq);
+-      }
++      eeh_enable_irq(dev);
++
+       if (!driver->err_handler ||
+           !driver->err_handler->resume)
+               return;
+@@ -210,15 +235,12 @@ static void eeh_report_failure(struct pc
+       if (!driver)
+               return;
+-      if (irq_in_use (dev->irq)) {
+-              struct device_node *dn = pci_device_to_OF_node(dev);
+-              PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
+-              disable_irq_nosync(dev->irq);
+-      }
+-      if (!driver->err_handler)
+-              return;
+-      if (!driver->err_handler->error_detected)
++      eeh_disable_irq(dev);
++
++      if (!driver->err_handler ||
++          !driver->err_handler->error_detected)
+               return;
++
+       driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
+ }