diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 13 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_driver.c | 20 |
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) | |||
223 | void eeh_mark_slot (struct device_node *dn, int mode_flag) | 223 | void 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, |