]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.arch/ppc64-eeh-msix-irq
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / ppc64-eeh-msix-irq
CommitLineData
2cb7cef9
BS
1From: Mike Mason <mmlnx@us.ibm.com>
2Date: Tue, 10 Feb 2009 11:12:21 +0000 (+0000)
3Subject: powerpc/eeh: Only disable/enable LSI interrupts in EEH
4Patch-mainline: 2.6.30-rc1
5Git-commit: 8535ef05a6904429ce72671c3035dbf05e6d5edf
6References: bnc#509497
7
8powerpc/eeh: Only disable/enable LSI interrupts in EEH
9
10The EEH code disables and enables interrupts during the
11device recovery process. This is unnecessary for MSI
12and MSI-X interrupts because they are effectively disabled
13by the DMA Stopped state when an EEH error occurs. The
14current code is also incorrect for MSI-X interrupts. It
15doesn't take into account that MSI-X interrupts are tracked
16in a different way than LSI/MSI interrupts. This patch
17ensures only LSI interrupts are disabled/enabled.
18
19Signed-off-by: Mike Mason <mmlnx@us.ibm.com>
20Acked-by: Linas Vepstas <linasvepstas@gmail.com>
21Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
22Acked-by: Jeff Mahoney <jeffm@suse.com>
23---
24
25 arch/powerpc/platforms/pseries/eeh_driver.c | 68 ++++++++++++++++++----------
26 1 file changed, 45 insertions(+), 23 deletions(-)
27
28--- a/arch/powerpc/platforms/pseries/eeh_driver.c
29+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
30@@ -79,6 +79,40 @@ static int irq_in_use(unsigned int irq)
31 return rc;
32 }
33
34+/**
35+ * eeh_disable_irq - disable interrupt for the recovering device
36+ */
37+static void eeh_disable_irq(struct pci_dev *dev)
38+{
39+ struct device_node *dn = pci_device_to_OF_node(dev);
40+
41+ /* Don't disable MSI and MSI-X interrupts. They are
42+ * effectively disabled by the DMA Stopped state
43+ * when an EEH error occurs.
44+ */
45+ if (dev->msi_enabled || dev->msix_enabled)
46+ return;
47+
48+ if (!irq_in_use(dev->irq))
49+ return;
50+
51+ PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
52+ disable_irq_nosync(dev->irq);
53+}
54+
55+/**
56+ * eeh_enable_irq - enable interrupt for the recovering device
57+ */
58+static void eeh_enable_irq(struct pci_dev *dev)
59+{
60+ struct device_node *dn = pci_device_to_OF_node(dev);
61+
62+ if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
63+ PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
64+ enable_irq(dev->irq);
65+ }
66+}
67+
68 /* ------------------------------------------------------- */
69 /**
70 * eeh_report_error - report pci error to each device driver
71@@ -98,11 +132,8 @@ static void eeh_report_error(struct pci_
72 if (!driver)
73 return;
74
75- if (irq_in_use (dev->irq)) {
76- struct device_node *dn = pci_device_to_OF_node(dev);
77- PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
78- disable_irq_nosync(dev->irq);
79- }
80+ eeh_disable_irq(dev);
81+
82 if (!driver->err_handler ||
83 !driver->err_handler->error_detected)
84 return;
85@@ -147,17 +178,14 @@ static void eeh_report_reset(struct pci_
86 {
87 enum pci_ers_result rc, *res = userdata;
88 struct pci_driver *driver = dev->driver;
89- struct device_node *dn = pci_device_to_OF_node(dev);
90
91 if (!driver)
92 return;
93
94 dev->error_state = pci_channel_io_normal;
95
96- if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
97- PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
98- enable_irq(dev->irq);
99- }
100+ eeh_enable_irq(dev);
101+
102 if (!driver->err_handler ||
103 !driver->err_handler->slot_reset)
104 return;
105@@ -176,17 +204,14 @@ static void eeh_report_reset(struct pci_
106 static void eeh_report_resume(struct pci_dev *dev, void *userdata)
107 {
108 struct pci_driver *driver = dev->driver;
109- struct device_node *dn = pci_device_to_OF_node(dev);
110
111 dev->error_state = pci_channel_io_normal;
112
113 if (!driver)
114 return;
115
116- if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
117- PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
118- enable_irq(dev->irq);
119- }
120+ eeh_enable_irq(dev);
121+
122 if (!driver->err_handler ||
123 !driver->err_handler->resume)
124 return;
125@@ -210,15 +235,12 @@ static void eeh_report_failure(struct pc
126 if (!driver)
127 return;
128
129- if (irq_in_use (dev->irq)) {
130- struct device_node *dn = pci_device_to_OF_node(dev);
131- PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
132- disable_irq_nosync(dev->irq);
133- }
134- if (!driver->err_handler)
135- return;
136- if (!driver->err_handler->error_detected)
137+ eeh_disable_irq(dev);
138+
139+ if (!driver->err_handler ||
140+ !driver->err_handler->error_detected)
141 return;
142+
143 driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
144 }
145