Commit 3914ac7b authored by Linas Vepstas's avatar Linas Vepstas Committed by Paul Mackerras

[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: default avatarLinas Vepstas <linas@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
(cherry picked from 216810296bb97d39da8e176822e9de78d2f00187 commit)
parent b6495c0c
...@@ -223,6 +223,11 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag) ...@@ -223,6 +223,11 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
void eeh_mark_slot (struct device_node *dn, int mode_flag) void eeh_mark_slot (struct device_node *dn, int mode_flag)
{ {
dn = find_device_pe (dn); 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_mode |= mode_flag;
__eeh_mark_slot (dn->child, mode_flag); __eeh_mark_slot (dn->child, mode_flag);
} }
...@@ -244,7 +249,13 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag) ...@@ -244,7 +249,13 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&confirm_error_lock, flags); spin_lock_irqsave(&confirm_error_lock, flags);
dn = find_device_pe (dn); 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_mode &= ~mode_flag;
PCI_DN(dn)->eeh_check_count = 0; PCI_DN(dn)->eeh_check_count = 0;
__eeh_clear_slot (dn->child, mode_flag); __eeh_clear_slot (dn->child, mode_flag);
...@@ -609,7 +620,7 @@ void eeh_restore_bars(struct pci_dn *pdn) ...@@ -609,7 +620,7 @@ void eeh_restore_bars(struct pci_dn *pdn)
if (!pdn) if (!pdn)
return; return;
if (! pdn->eeh_is_bridge) if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && (!pdn->eeh_is_bridge))
__restore_bars (pdn); __restore_bars (pdn);
dn = pdn->node->child; dn = pdn->node->child;
......
...@@ -213,9 +213,23 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) ...@@ -213,9 +213,23 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
if (rc) if (rc)
return rc; return rc;
/* Walk over all functions on this device */ /* New-style config addrs might be shared across multiple devices,
rtas_configure_bridge(pe_dn); * Walk over all functions on this device */
eeh_restore_bars(pe_dn); 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 /* Give the system 5 seconds to finish running the user-space
* hotplug shutdown scripts, e.g. ifdown for ethernet. Yes, * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment