aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorLinas Vepstas <linas@linas.org>2005-11-03 19:55:01 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-09 23:30:23 -0500
commit3914ac7b0e672131dc2ac8b415ada79c4ccbbb31 (patch)
tree10ea50e28257b6495cd2cb1e4f64e22fee88f20f /arch/powerpc
parentb6495c0c8f100b882d85774f44529519befefba9 (diff)
[PATCH] powerpc: handle multifunction PCI devices properly
239-eeh-multifunction-consolidate.patch New-style firmware will often place multiple different functions under a non-EEH-aware parent. However, these devices might share a common PE "partition endpoint" and config address, ad thus any EEH events will affect all of the devices in common. This patch makes the effort to find all of these common devices and handle them together. Signed-off-by: Linas Vepstas <linas@austin.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org> (cherry picked from 216810296bb97d39da8e176822e9de78d2f00187 commit)
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c13
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c20
2 files changed, 29 insertions, 4 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index b0fa76d0c78a..02bc1f9d20b9 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -223,6 +223,11 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
223void eeh_mark_slot (struct device_node *dn, int mode_flag) 223void eeh_mark_slot (struct device_node *dn, int mode_flag)
224{ 224{
225 dn = find_device_pe (dn); 225 dn = find_device_pe (dn);
226
227 /* Back up one, since config addrs might be shared */
228 if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
229 dn = dn->parent;
230
226 PCI_DN(dn)->eeh_mode |= mode_flag; 231 PCI_DN(dn)->eeh_mode |= mode_flag;
227 __eeh_mark_slot (dn->child, mode_flag); 232 __eeh_mark_slot (dn->child, mode_flag);
228} 233}
@@ -244,7 +249,13 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
244{ 249{
245 unsigned long flags; 250 unsigned long flags;
246 spin_lock_irqsave(&confirm_error_lock, flags); 251 spin_lock_irqsave(&confirm_error_lock, flags);
252
247 dn = find_device_pe (dn); 253 dn = find_device_pe (dn);
254
255 /* Back up one, since config addrs might be shared */
256 if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
257 dn = dn->parent;
258
248 PCI_DN(dn)->eeh_mode &= ~mode_flag; 259 PCI_DN(dn)->eeh_mode &= ~mode_flag;
249 PCI_DN(dn)->eeh_check_count = 0; 260 PCI_DN(dn)->eeh_check_count = 0;
250 __eeh_clear_slot (dn->child, mode_flag); 261 __eeh_clear_slot (dn->child, mode_flag);
@@ -609,7 +620,7 @@ void eeh_restore_bars(struct pci_dn *pdn)
609 if (!pdn) 620 if (!pdn)
610 return; 621 return;
611 622
612 if (! pdn->eeh_is_bridge) 623 if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && (!pdn->eeh_is_bridge))
613 __restore_bars (pdn); 624 __restore_bars (pdn);
614 625
615 dn = pdn->node->child; 626 dn = pdn->node->child;
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 242b2923360d..1c97c89597fb 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -213,9 +213,23 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
213 if (rc) 213 if (rc)
214 return rc; 214 return rc;
215 215
216 /* Walk over all functions on this device */ 216 /* New-style config addrs might be shared across multiple devices,
217 rtas_configure_bridge(pe_dn); 217 * Walk over all functions on this device */
218 eeh_restore_bars(pe_dn); 218 if (pe_dn->eeh_pe_config_addr) {
219 struct device_node *pe = pe_dn->node;
220 pe = pe->parent->child;
221 while (pe) {
222 struct pci_dn *ppe = PCI_DN(pe);
223 if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
224 rtas_configure_bridge(ppe);
225 eeh_restore_bars(ppe);
226 }
227 pe = pe->sibling;
228 }
229 } else {
230 rtas_configure_bridge(pe_dn);
231 eeh_restore_bars(pe_dn);
232 }
219 233
220 /* Give the system 5 seconds to finish running the user-space 234 /* Give the system 5 seconds to finish running the user-space
221 * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes, 235 * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes,