diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-24 14:07:18 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-24 14:07:18 -0400 |
| commit | 07bc9dc1b01bad7084fed3d2659e5d83317869bc (patch) | |
| tree | a8285e1f3919d60d4420aa1b451e57fef35d9628 | |
| parent | b48a97be8e6c2afdba2f3b61fd88c3c7743fbd73 (diff) | |
| parent | ff3d79dc12c2ed38483f6c1e0f26fde430f27c9d (diff) | |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Ben Herrenschmidt:
"Here is a series of powerpc fixes. It's a bit big, mostly because of
the series of 11 "EEH" patches from Gavin. The EEH (Our IBM specific
PCI/PCIe Enhanced Error Handling) code had been rotting for a while
and this merge window saw a significant rework & fixing of it by Gavin
Shan.
However, that wasn't complete and left some open issues. There were
still a few corner cases that didn't work properly, for example in
relation to hotplug and devices without explicit error handlers. We
had some patches but they weren't quite good enough yet so I left them
off the 3.11 merge window.
Gavin since then fixed it all up, we ran quite a few rounds of testing
and it seems fairly solid (at least probably more than it has ever
been). This should probably have made -rc1 but both Gavin and I took
some vacation so it had to wait for -rc2.
The rest is more bug fixes, mostly to new features recently added, for
example, we missed the cpu table entry for one of the two models of P8
(we didn't realize they had different PVR [Processor Version Register]
values), some module CRC issues, etc..."
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (23 commits)
powerpc/perf: BHRB filter configuration should follow the task
powerpc/perf: Ignore separate BHRB privilege state filter request
powerpc/powernv: Mark pnv_pci_init_ioda2_phb() as __init
powerpc/mm: Use the correct SLB(LLP) encoding in tlbie instruction
powerpc/mm: Fix fallthrough bug in hpte_decode
powerpc/pseries: Fix a typo in pSeries_lpar_hpte_insert()
powerpc/eeh: Introdce flag to protect sysfs
powerpc/eeh: Fix unbalanced enable for IRQ
powerpc/eeh: Don't use pci_dev during BAR restore
powerpc/eeh: Use partial hotplug for EEH unaware drivers
powerpc/pci: Partial tree hotplug support
powerpc/eeh: Use safe list traversal when walking EEH devices
powerpc/eeh: Keep PE during hotplug
powerpc/pci/hotplug: Don't need to remove from EEH cache twice
powerpc/pci: Override pcibios_release_device()
powerpc/eeh: Export functions for hotplug
powerpc/eeh: Remove reference to PCI device
powerpc: Fix the corrupt r3 error during MCE handling.
powerpc/perf: Set PPC_FEATURE2_EBB when we register the power8 PMU
powerpc/pseries: Drop "select HOTPLUG"
...
26 files changed, 390 insertions, 169 deletions
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 09a8743143f3..d3e5e9bc8f94 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
| @@ -55,6 +55,8 @@ struct device_node; | |||
| 55 | #define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */ | 55 | #define EEH_PE_RECOVERING (1 << 1) /* Recovering PE */ |
| 56 | #define EEH_PE_PHB_DEAD (1 << 2) /* Dead PHB */ | 56 | #define EEH_PE_PHB_DEAD (1 << 2) /* Dead PHB */ |
| 57 | 57 | ||
| 58 | #define EEH_PE_KEEP (1 << 8) /* Keep PE on hotplug */ | ||
| 59 | |||
| 58 | struct eeh_pe { | 60 | struct eeh_pe { |
| 59 | int type; /* PE type: PHB/Bus/Device */ | 61 | int type; /* PE type: PHB/Bus/Device */ |
| 60 | int state; /* PE EEH dependent mode */ | 62 | int state; /* PE EEH dependent mode */ |
| @@ -72,8 +74,8 @@ struct eeh_pe { | |||
| 72 | struct list_head child; /* Child PEs */ | 74 | struct list_head child; /* Child PEs */ |
| 73 | }; | 75 | }; |
| 74 | 76 | ||
| 75 | #define eeh_pe_for_each_dev(pe, edev) \ | 77 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ |
| 76 | list_for_each_entry(edev, &pe->edevs, list) | 78 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) |
| 77 | 79 | ||
| 78 | /* | 80 | /* |
| 79 | * The struct is used to trace EEH state for the associated | 81 | * The struct is used to trace EEH state for the associated |
| @@ -82,7 +84,13 @@ struct eeh_pe { | |||
| 82 | * another tree except the currently existing tree of PCI | 84 | * another tree except the currently existing tree of PCI |
| 83 | * buses and PCI devices | 85 | * buses and PCI devices |
| 84 | */ | 86 | */ |
| 85 | #define EEH_DEV_IRQ_DISABLED (1<<0) /* Interrupt disabled */ | 87 | #define EEH_DEV_BRIDGE (1 << 0) /* PCI bridge */ |
| 88 | #define EEH_DEV_ROOT_PORT (1 << 1) /* PCIe root port */ | ||
| 89 | #define EEH_DEV_DS_PORT (1 << 2) /* Downstream port */ | ||
| 90 | #define EEH_DEV_IRQ_DISABLED (1 << 3) /* Interrupt disabled */ | ||
| 91 | #define EEH_DEV_DISCONNECTED (1 << 4) /* Removing from PE */ | ||
| 92 | |||
| 93 | #define EEH_DEV_SYSFS (1 << 8) /* Sysfs created */ | ||
| 86 | 94 | ||
| 87 | struct eeh_dev { | 95 | struct eeh_dev { |
| 88 | int mode; /* EEH mode */ | 96 | int mode; /* EEH mode */ |
| @@ -90,11 +98,13 @@ struct eeh_dev { | |||
| 90 | int config_addr; /* Config address */ | 98 | int config_addr; /* Config address */ |
| 91 | int pe_config_addr; /* PE config address */ | 99 | int pe_config_addr; /* PE config address */ |
| 92 | u32 config_space[16]; /* Saved PCI config space */ | 100 | u32 config_space[16]; /* Saved PCI config space */ |
| 101 | u8 pcie_cap; /* Saved PCIe capability */ | ||
| 93 | struct eeh_pe *pe; /* Associated PE */ | 102 | struct eeh_pe *pe; /* Associated PE */ |
| 94 | struct list_head list; /* Form link list in the PE */ | 103 | struct list_head list; /* Form link list in the PE */ |
| 95 | struct pci_controller *phb; /* Associated PHB */ | 104 | struct pci_controller *phb; /* Associated PHB */ |
| 96 | struct device_node *dn; /* Associated device node */ | 105 | struct device_node *dn; /* Associated device node */ |
| 97 | struct pci_dev *pdev; /* Associated PCI device */ | 106 | struct pci_dev *pdev; /* Associated PCI device */ |
| 107 | struct pci_bus *bus; /* PCI bus for partial hotplug */ | ||
| 98 | }; | 108 | }; |
| 99 | 109 | ||
| 100 | static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) | 110 | static inline struct device_node *eeh_dev_to_of_node(struct eeh_dev *edev) |
| @@ -193,8 +203,10 @@ int eeh_phb_pe_create(struct pci_controller *phb); | |||
| 193 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); | 203 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); |
| 194 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); | 204 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); |
| 195 | int eeh_add_to_parent_pe(struct eeh_dev *edev); | 205 | int eeh_add_to_parent_pe(struct eeh_dev *edev); |
| 196 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe); | 206 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev); |
| 197 | void eeh_pe_update_time_stamp(struct eeh_pe *pe); | 207 | void eeh_pe_update_time_stamp(struct eeh_pe *pe); |
| 208 | void *eeh_pe_traverse(struct eeh_pe *root, | ||
| 209 | eeh_traverse_func fn, void *flag); | ||
| 198 | void *eeh_pe_dev_traverse(struct eeh_pe *root, | 210 | void *eeh_pe_dev_traverse(struct eeh_pe *root, |
| 199 | eeh_traverse_func fn, void *flag); | 211 | eeh_traverse_func fn, void *flag); |
| 200 | void eeh_pe_restore_bars(struct eeh_pe *pe); | 212 | void eeh_pe_restore_bars(struct eeh_pe *pe); |
| @@ -209,10 +221,12 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, | |||
| 209 | unsigned long val); | 221 | unsigned long val); |
| 210 | int eeh_dev_check_failure(struct eeh_dev *edev); | 222 | int eeh_dev_check_failure(struct eeh_dev *edev); |
| 211 | void eeh_addr_cache_build(void); | 223 | void eeh_addr_cache_build(void); |
| 224 | void eeh_add_device_early(struct device_node *); | ||
| 212 | void eeh_add_device_tree_early(struct device_node *); | 225 | void eeh_add_device_tree_early(struct device_node *); |
| 226 | void eeh_add_device_late(struct pci_dev *); | ||
| 213 | void eeh_add_device_tree_late(struct pci_bus *); | 227 | void eeh_add_device_tree_late(struct pci_bus *); |
| 214 | void eeh_add_sysfs_files(struct pci_bus *); | 228 | void eeh_add_sysfs_files(struct pci_bus *); |
| 215 | void eeh_remove_bus_device(struct pci_dev *, int); | 229 | void eeh_remove_device(struct pci_dev *); |
| 216 | 230 | ||
| 217 | /** | 231 | /** |
| 218 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. | 232 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. |
| @@ -252,13 +266,17 @@ static inline unsigned long eeh_check_failure(const volatile void __iomem *token | |||
| 252 | 266 | ||
| 253 | static inline void eeh_addr_cache_build(void) { } | 267 | static inline void eeh_addr_cache_build(void) { } |
| 254 | 268 | ||
| 269 | static inline void eeh_add_device_early(struct device_node *dn) { } | ||
| 270 | |||
| 255 | static inline void eeh_add_device_tree_early(struct device_node *dn) { } | 271 | static inline void eeh_add_device_tree_early(struct device_node *dn) { } |
| 256 | 272 | ||
| 273 | static inline void eeh_add_device_late(struct pci_dev *dev) { } | ||
| 274 | |||
| 257 | static inline void eeh_add_device_tree_late(struct pci_bus *bus) { } | 275 | static inline void eeh_add_device_tree_late(struct pci_bus *bus) { } |
| 258 | 276 | ||
| 259 | static inline void eeh_add_sysfs_files(struct pci_bus *bus) { } | 277 | static inline void eeh_add_sysfs_files(struct pci_bus *bus) { } |
| 260 | 278 | ||
| 261 | static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { } | 279 | static inline void eeh_remove_device(struct pci_dev *dev) { } |
| 262 | 280 | ||
| 263 | #define EEH_POSSIBLE_ERROR(val, type) (0) | 281 | #define EEH_POSSIBLE_ERROR(val, type) (0) |
| 264 | #define EEH_IO_ERROR_VALUE(size) (-1UL) | 282 | #define EEH_IO_ERROR_VALUE(size) (-1UL) |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index ba713f166fa5..10be1dd01c6b 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
| @@ -96,10 +96,11 @@ static inline bool arch_irqs_disabled(void) | |||
| 96 | #endif | 96 | #endif |
| 97 | 97 | ||
| 98 | #define hard_irq_disable() do { \ | 98 | #define hard_irq_disable() do { \ |
| 99 | u8 _was_enabled = get_paca()->soft_enabled; \ | 99 | u8 _was_enabled; \ |
| 100 | __hard_irq_disable(); \ | 100 | __hard_irq_disable(); \ |
| 101 | get_paca()->soft_enabled = 0; \ | 101 | _was_enabled = local_paca->soft_enabled; \ |
| 102 | get_paca()->irq_happened |= PACA_IRQ_HARD_DIS; \ | 102 | local_paca->soft_enabled = 0; \ |
| 103 | local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \ | ||
| 103 | if (_was_ena | ||
