]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.arch/ppc64-eeh-msix-irq
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.arch / ppc64-eeh-msix-irq
1 From: Mike Mason <mmlnx@us.ibm.com>
2 Date: Tue, 10 Feb 2009 11:12:21 +0000 (+0000)
3 Subject: powerpc/eeh: Only disable/enable LSI interrupts in EEH
4 Patch-mainline: 2.6.30-rc1
5 Git-commit: 8535ef05a6904429ce72671c3035dbf05e6d5edf
6 References: bnc#509497
7
8 powerpc/eeh: Only disable/enable LSI interrupts in EEH
9
10 The EEH code disables and enables interrupts during the
11 device recovery process. This is unnecessary for MSI
12 and MSI-X interrupts because they are effectively disabled
13 by the DMA Stopped state when an EEH error occurs. The
14 current code is also incorrect for MSI-X interrupts. It
15 doesn't take into account that MSI-X interrupts are tracked
16 in a different way than LSI/MSI interrupts. This patch
17 ensures only LSI interrupts are disabled/enabled.
18
19 Signed-off-by: Mike Mason <mmlnx@us.ibm.com>
20 Acked-by: Linas Vepstas <linasvepstas@gmail.com>
21 Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
22 Acked-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