void eeh_mark_slot (struct device_node *dn, int mode_flag)
{
dn = find_device_pe (dn);
+
+ /* Back up one, since config addrs might be shared */
+ if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+ dn = dn->parent;
+
PCI_DN(dn)->eeh_mode |= mode_flag;
__eeh_mark_slot (dn->child, mode_flag);
}
{
unsigned long flags;
spin_lock_irqsave(&confirm_error_lock, flags);
+
dn = find_device_pe (dn);
+
+ /* Back up one, since config addrs might be shared */
+ if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+ dn = dn->parent;
+
PCI_DN(dn)->eeh_mode &= ~mode_flag;
PCI_DN(dn)->eeh_check_count = 0;
__eeh_clear_slot (dn->child, mode_flag);
if (!pdn)
return;
- if (! pdn->eeh_is_bridge)
+ if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && (!pdn->eeh_is_bridge))
__restore_bars (pdn);
dn = pdn->node->child;
if (rc)
return rc;
- /* Walk over all functions on this device */
- rtas_configure_bridge(pe_dn);
- eeh_restore_bars(pe_dn);
+ /* New-style config addrs might be shared across multiple devices,
+ * Walk over all functions on this device */
+ if (pe_dn->eeh_pe_config_addr) {
+ struct device_node *pe = pe_dn->node;
+ pe = pe->parent->child;
+ while (pe) {
+ struct pci_dn *ppe = PCI_DN(pe);
+ if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
+ rtas_configure_bridge(ppe);
+ eeh_restore_bars(ppe);
+ }
+ pe = pe->sibling;
+ }
+ } else {
+ rtas_configure_bridge(pe_dn);
+ eeh_restore_bars(pe_dn);
+ }
/* Give the system 5 seconds to finish running the user-space
* hotplug shutdown scripts, e.g. ifdown for ethernet. Yes,