diff options
author | Linas Vepstas <linas@linas.org> | 2005-11-03 19:55:19 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-09 23:30:39 -0500 |
commit | 7684b40cb53ba00cc51271f1c42897b776c48fbc (patch) | |
tree | 19155abfd3b76d13b55dfb6fdf1a46e4a8c0a048 | |
parent | d177c207ba16b1db31283e2d1fee7ad4a863584b (diff) |
[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) | |||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) | 75 | int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val) |
76 | { | 76 | { |
77 | int returnval = -1; | 77 | int returnval = -1; |
78 | unsigned long buid, addr; | 78 | 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); | |||
106 | static DEFINE_PER_CPU(unsigned long, ignored_failures); | 106 | static DEFINE_PER_CPU(unsigned long, ignored_failures); |
107 | static DEFINE_PER_CPU(unsigned long, slot_resets); | 107 | static DEFINE_PER_CPU(unsigned long, slot_resets); |
108 | 108 | ||
109 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) | ||
110 | |||
109 | /* --------------------------------------------------------------- */ | 111 | /* --------------------------------------------------------------- */ |
110 | /* Below lies the EEH event infrastructure */ | 112 | /* Below lies the EEH event infrastructure */ |
111 | 113 | ||
@@ -620,7 +622,7 @@ void eeh_restore_bars(struct pci_dn *pdn) | |||
620 | if (!pdn) | 622 | if (!pdn) |
621 | return; | 623 | return; |
622 | 624 | ||
623 | if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && (!pdn->eeh_is_bridge)) | 625 | if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) |
624 | __restore_bars (pdn); | 626 | __restore_bars (pdn); |
625 | 627 | ||
626 | dn = pdn->node->child; | 628 | dn = pdn->node->child; |
@@ -638,18 +640,15 @@ void eeh_restore_bars(struct pci_dn *pdn) | |||
638 | * PCI devices are added individuallly; but, for the restore, | 640 | * PCI devices are added individuallly; but, for the restore, |
639 | * an entire slot is reset at a time. | 641 | * an entire slot is reset at a time. |
640 | */ | 642 | */ |
641 | void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn) | 643 | static void eeh_save_bars(struct pci_dn *pdn) |
642 | { | 644 | { |
643 | int i; | 645 | int i; |
644 | 646 | ||
645 | if (!pdev || !pdn ) | 647 | if (!pdn ) |
646 | return; | 648 | return; |
647 | 649 | ||
648 | for (i = 0; i < 16; i++) | 650 | for (i = 0; i < 16; i++) |
649 | pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]); | 651 | rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]); |
650 | |||
651 | if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
652 | pdn->eeh_is_bridge = 1; | ||
653 | } | 652 | } |
654 | 653 | ||
655 | void | 654 | void |
@@ -699,6 +698,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
699 | int enable; | 698 | int enable; |
700 | struct pci_dn *pdn = PCI_DN(dn); | 699 | struct pci_dn *pdn = PCI_DN(dn); |
701 | 700 | ||
701 | pdn->class_code = *class_code; | ||
702 | pdn->eeh_mode = 0; | 702 | pdn->eeh_mode = 0; |
703 | pdn->eeh_check_count = 0; | 703 | pdn->eeh_check_count = 0; |
704 | pdn->eeh_freeze_count = 0; | 704 | pdn->eeh_freeze_count = 0; |
@@ -781,6 +781,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
781 | dn->full_name); | 781 | dn->full_name); |
782 | } | 782 | } |
783 | 783 | ||
784 | eeh_save_bars(pdn); | ||
784 | return NULL; | 785 | return NULL; |
785 | } | 786 | } |
786 | 787 | ||
@@ -915,7 +916,6 @@ void eeh_add_device_late(struct pci_dev *dev) | |||
915 | pdn->pcidev = dev; | 916 | pdn->pcidev = dev; |
916 | 917 | ||
917 | pci_addr_cache_insert_device (dev); | 918 | pci_addr_cache_insert_device (dev); |
918 | eeh_save_bars(dev, pdn); | ||
919 | } | 919 | } |
920 | EXPORT_SYMBOL_GPL(eeh_add_device_late); | 920 | EXPORT_SYMBOL_GPL(eeh_add_device_late); |
921 | 921 | ||
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) | |||
304 | 304 | ||
305 | pci_addr_cache_insert_device(dev); | 305 | pci_addr_cache_insert_device(dev); |
306 | 306 | ||
307 | /* Save the BAR's; firmware doesn't restore these after EEH reset */ | ||
308 | dn = pci_device_to_OF_node(dev); | 307 | dn = pci_device_to_OF_node(dev); |
309 | eeh_save_bars(dev, PCI_DN(dn)); | ||
310 | |||
311 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ | 308 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ |
312 | PCI_DN(dn)->pcidev = dev; | 309 | PCI_DN(dn)->pcidev = dev; |
313 | } | 310 | } |
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; | |||
61 | struct iommu_table; | 61 | struct iommu_table; |
62 | 62 | ||
63 | struct pci_dn { | 63 | struct pci_dn { |
64 | int busno; /* for pci devices */ | 64 | int busno; /* pci bus number */ |
65 | int bussubno; /* for pci devices */ | 65 | int bussubno; /* pci subordinate bus number */ |
66 | int devfn; /* for pci devices */ | 66 | int devfn; /* pci device and function number */ |
67 | int class_code; /* pci device class */ | ||
67 | 68 | ||
68 | #ifdef CONFIG_PPC_PSERIES | 69 | #ifdef CONFIG_PPC_PSERIES |
69 | int eeh_mode; /* See eeh.h for possible EEH_MODEs */ | 70 | int eeh_mode; /* See eeh.h for possible EEH_MODEs */ |
@@ -71,7 +72,6 @@ struct pci_dn { | |||
71 | int eeh_pe_config_addr; /* new-style partition endpoint address */ | 72 | int eeh_pe_config_addr; /* new-style partition endpoint address */ |
72 | int eeh_check_count; /* # times driver ignored error */ | 73 | int eeh_check_count; /* # times driver ignored error */ |
73 | int eeh_freeze_count; /* # times this device froze up. */ | 74 | int eeh_freeze_count; /* # times this device froze up. */ |
74 | int eeh_is_bridge; /* device is pci-to-pci bridge */ | ||
75 | #endif | 75 | #endif |
76 | int pci_ext_config_space; /* for pci devices */ | 76 | int pci_ext_config_space; /* for pci devices */ |
77 | struct pci_controller *phb; /* for pci devices */ | 77 | 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); | |||
58 | void pci_addr_cache_build(void); | 58 | void pci_addr_cache_build(void); |
59 | struct pci_dev *pci_get_device_by_addr(unsigned long addr); | 59 | struct pci_dev *pci_get_device_by_addr(unsigned long addr); |
60 | 60 | ||
61 | void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn); | ||
62 | |||
63 | /** | 61 | /** |
64 | * eeh_slot_error_detail -- record and EEH error condition to the log | 62 | * eeh_slot_error_detail -- record and EEH error condition to the log |
65 | * @severity: 1 if temporary, 2 if permanent failure. | 63 | * @severity: 1 if temporary, 2 if permanent failure. |
@@ -103,6 +101,7 @@ void eeh_restore_bars(struct pci_dn *); | |||
103 | void rtas_configure_bridge(struct pci_dn *); | 101 | void rtas_configure_bridge(struct pci_dn *); |
104 | 102 | ||
105 | int rtas_write_config(struct pci_dn *, int where, int size, u32 val); | 103 | int rtas_write_config(struct pci_dn *, int where, int size, u32 val); |
104 | int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); | ||
106 | 105 | ||
107 | /** | 106 | /** |
108 | * mark and clear slots: find "partition endpoint" PE and set or | 107 | * mark and clear slots: find "partition endpoint" PE and set or |