diff options
author | Linas Vepstas <linas@linas.org> | 2005-11-04 01:55:19 +0100 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-10 05:30:39 +0100 |
commit | 7684b40cb53ba00cc51271f1c42897b776c48fbc (patch) | |
tree | 19155abfd3b76d13b55dfb6fdf1a46e4a8c0a048 | |
parent | [PATCH] powerpc: IOMMU: don't ioremap null addresses (diff) | |
download | linux-7684b40cb53ba00cc51271f1c42897b776c48fbc.tar.xz linux-7684b40cb53ba00cc51271f1c42897b776c48fbc.zip |
[PATCH] powerpc: Save device BARs much earlier in the boot sequence
241-eeh-save-bars-earlier.patch
Save the PCI device bars *before* any PCI probing is done.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
(cherry picked from 76c902b919098860f3d4e125f847abcc4cb1782a commit)
-rw-r--r-- | arch/powerpc/kernel/rtas_pci.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_cache.c | 3 | ||||
-rw-r--r-- | include/asm-powerpc/pci-bridge.h | 8 | ||||
-rw-r--r-- | include/asm-powerpc/ppc-pci.h | 3 |
5 files changed, 14 insertions, 18 deletions
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 45b8109951fe..5579f6559912 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -72,7 +72,7 @@ static int of_device_available(struct device_node * dn) return 0; } -static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) +int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) { int returnval = -1; unsigned long buid, addr; diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 02bc1f9d20b9..9e597cb7e659 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -106,6 +106,8 @@ static DEFINE_PER_CPU(unsigned long, false_positives); static DEFINE_PER_CPU(unsigned long, ignored_failures); static DEFINE_PER_CPU(unsigned long, slot_resets); +#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) + /* --------------------------------------------------------------- */ /* Below lies the EEH event infrastructure */ @@ -620,7 +622,7 @@ void eeh_restore_bars(struct pci_dn *pdn) if (!pdn) return; - if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && (!pdn->eeh_is_bridge)) + if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) __restore_bars (pdn); dn = pdn->node->child; @@ -638,18 +640,15 @@ void eeh_restore_bars(struct pci_dn *pdn) * PCI devices are added individuallly; but, for the restore, * an entire slot is reset at a time. */ -void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn) +static void eeh_save_bars(struct pci_dn *pdn) { int i; - if (!pdev || !pdn ) + if (!pdn ) return; for (i = 0; i < 16; i++) - pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]); - - if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) - pdn->eeh_is_bridge = 1; + rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]); } void @@ -699,6 +698,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) int enable; struct pci_dn *pdn = PCI_DN(dn); + pdn->class_code = *class_code; pdn->eeh_mode = 0; pdn->eeh_check_count = 0; pdn->eeh_freeze_count = 0; @@ -781,6 +781,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) dn->full_name); } + eeh_save_bars(pdn); return NULL; } @@ -915,7 +916,6 @@ void eeh_add_device_late(struct pci_dev *dev) pdn->pcidev = dev; pci_addr_cache_insert_device (dev); - eeh_save_bars(dev, pdn); } EXPORT_SYMBOL_GPL(eeh_add_device_late); diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index ff6c938f424b..71b2187581a3 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c @@ -304,10 +304,7 @@ void __init pci_addr_cache_build(void) pci_addr_cache_insert_device(dev); - /* Save the BAR's; firmware doesn't restore these after EEH reset */ dn = pci_device_to_OF_node(dev); - eeh_save_bars(dev, PCI_DN(dn)); - pci_dev_get (dev); /* matching put is in eeh_remove_device() */ PCI_DN(dn)->pcidev = dev; } diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h index a81bc363f350..b0d816fe2e27 100644 --- a/include/asm-powerpc/pci-bridge.h +++ b/include/asm-powerpc/pci-bridge.h @@ -61,9 +61,10 @@ struct pci_controller; struct iommu_table; struct pci_dn { - int busno; /* for pci devices */ - int bussubno; /* for pci devices */ - int devfn; /* for pci devices */ + int busno; /* pci bus number */ + int bussubno; /* pci subordinate bus number */ + int devfn; /* pci device and function number */ + int class_code; /* pci device class */ #ifdef CONFIG_PPC_PSERIES int eeh_mode; /* See eeh.h for possible EEH_MODEs */ @@ -71,7 +72,6 @@ struct pci_dn { int eeh_pe_config_addr; /* new-style partition endpoint address */ int eeh_check_count; /* # times driver ignored error */ int eeh_freeze_count; /* # times this device froze up. */ - int eeh_is_bridge; /* device is pci-to-pci bridge */ #endif int pci_ext_config_space; /* for pci devices */ struct pci_controller *phb; /* for pci devices */ diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 1a2db61694f2..f80482c7231f 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -58,8 +58,6 @@ void pci_addr_cache_remove_device(struct pci_dev *dev); void pci_addr_cache_build(void); struct pci_dev *pci_get_device_by_addr(unsigned long addr); -void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn); - /** * eeh_slot_error_detail -- record and EEH error condition to the log * @severity: 1 if temporary, 2 if permanent failure. @@ -103,6 +101,7 @@ void eeh_restore_bars(struct pci_dn *); void rtas_configure_bridge(struct pci_dn *); int rtas_write_config(struct pci_dn *, int where, int size, u32 val); +int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); /** * mark and clear slots: find "partition endpoint" PE and set or |