diff options
author | Linas Vepstas <linas@linas.org> | 2005-11-03 18:55:01 -0600 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-10 15:30:23 +1100 |
commit | 3914ac7b0e672131dc2ac8b415ada79c4ccbbb31 (patch) | |
tree | 10ea50e28257b6495cd2cb1e4f64e22fee88f20f /arch/powerpc/platforms/pseries/eeh.c | |
parent | b6495c0c8f100b882d85774f44529519befefba9 (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/platforms/pseries/eeh.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index b0fa76d0c78..02bc1f9d20b 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) 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); } @@ -244,7 +249,13 @@ void eeh_clear_slot (struct device_node *dn, int 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); @@ -609,7 +620,7 @@ void eeh_restore_bars(struct pci_dn *pdn) 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; |