diff mbox

Only disable/enable LSI interrupts in EEH

Message ID 4991EDB5.8070803@us.ibm.com (mailing list archive)
State Accepted, archived
Delegated to: Benjamin Herrenschmidt
Headers show

Commit Message

Mike Mason Feb. 10, 2009, 9:12 p.m. UTC
I'm resubmitting this patch with a couple changes
suggested by Michael Ellerman.  1) the new functions
should be static, and 2) some people may object to
including unrelated formating changes.

Comments

Michael Ellerman Feb. 10, 2009, 11:39 p.m. UTC | #1
On Tue, 2009-02-10 at 13:12 -0800, Mike Mason wrote:
> I'm resubmitting this patch with a couple changes
> suggested by Michael Ellerman.  1) the new functions
> should be static, and 2) some people may object to
> including unrelated formating changes.
> 
> =========================================================
> 
> 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>


Looks good. Assuming you've tested it :)

Acked-by: Michael Ellerman <michael@ellerman.id.au>
Mike Mason Feb. 12, 2009, 4:06 p.m. UTC | #2
Michael Ellerman wrote:
> On Tue, 2009-02-10 at 13:12 -0800, Mike Mason wrote:
>> I'm resubmitting this patch with a couple changes
>> suggested by Michael Ellerman.  1) the new functions
>> should be static, and 2) some people may object to
>> including unrelated formating changes.
>>
>> =========================================================
>>
>> 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>
> 
> 
> Looks good. Assuming you've tested it :)

Yes, it's been tested with network devices that use LSI, MSI and MSI-X interrupts.  All recovered fine.

> 
> Acked-by: Michael Ellerman <michael@ellerman.id.au>
> 
>
diff mbox

Patch

=========================================================

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>


--- arch/powerpc/platforms/pseries/eeh_driver.c-orig	2009-02-10 07:12:31.000000000 -0800
+++ arch/powerpc/platforms/pseries/eeh_driver.c	2009-02-10 08:19:54.000000000 -0800
@@ -76,6 +76,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
@@ -95,11 +129,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;
@@ -144,15 +175,12 @@  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;
 
-	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;
@@ -171,17 +199,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;
@@ -205,15 +230,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);
 }