aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2013-06-20 01:21:15 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-06-20 03:06:50 -0400
commitbe7e744607175fb1620f0390d20c880e16de163b (patch)
tree8c78f0acf8e04f06b36dc36017d62be40a6f6336 /arch/powerpc
parente9cc17d4ded2d10b332c7f3788d7817f7d9d01ef (diff)
powerpc/eeh: Enable EEH check for config access
The patch enables EEH check and let EEH core to process the EEH errors for PowerNV platform while accessing config space. Originally, the implementation already had mechanism to check EEH errors and tried to recover from them. However, we never let EEH core to handle the EEH errors. Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/platforms/powernv/pci.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 5edceb7f746d..577cbeadb0ea 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -33,6 +33,8 @@
33#include <asm/iommu.h> 33#include <asm/iommu.h>
34#include <asm/tce.h> 34#include <asm/tce.h>
35#include <asm/firmware.h> 35#include <asm/firmware.h>
36#include <asm/eeh_event.h>
37#include <asm/eeh.h>
36 38
37#include "powernv.h" 39#include "powernv.h"
38#include "pci.h" 40#include "pci.h"
@@ -260,6 +262,10 @@ static int pnv_pci_read_config(struct pci_bus *bus,
260{ 262{
261 struct pci_controller *hose = pci_bus_to_host(bus); 263 struct pci_controller *hose = pci_bus_to_host(bus);
262 struct pnv_phb *phb = hose->private_data; 264 struct pnv_phb *phb = hose->private_data;
265#ifdef CONFIG_EEH
266 struct device_node *busdn, *dn;
267 struct eeh_pe *phb_pe = NULL;
268#endif
263 u32 bdfn = (((uint64_t)bus->number) << 8) | devfn; 269 u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
264 s64 rc; 270 s64 rc;
265 271
@@ -292,8 +298,34 @@ static int pnv_pci_read_config(struct pci_bus *bus,
292 cfg_dbg("pnv_pci_read_config bus: %x devfn: %x +%x/%x -> %08x\n", 298 cfg_dbg("pnv_pci_read_config bus: %x devfn: %x +%x/%x -> %08x\n",
293 bus->number, devfn, where, size, *val); 299 bus->number, devfn, where, size, *val);
294 300
295 /* Check if the PHB got frozen due to an error (no response) */ 301 /*
302 * Check if the specified PE has been put into frozen
303 * state. On the other hand, we needn't do that while
304 * the PHB has been put into frozen state because of
305 * PHB-fatal errors.
306 */
307#ifdef CONFIG_EEH
308 phb_pe = eeh_phb_pe_get(hose);
309 if (phb_pe && (phb_pe->state & EEH_PE_ISOLATED))
310 return PCIBIOS_SUCCESSFUL;
311
312 if (phb->eeh_enabled) {
313 if (*val == EEH_IO_ERROR_VALUE(size)) {
314 busdn = pci_bus_to_OF_node(bus);
315 for (dn = busdn->child; dn; dn = dn->sibling) {
316 struct pci_dn *pdn = PCI_DN(dn);
317
318 if (pdn && pdn->devfn == devfn &&
319 eeh_dev_check_failure(of_node_to_eeh_dev(dn)))
320 return PCIBIOS_DEVICE_NOT_FOUND;
321 }
322 }
323 } else {
324 pnv_pci_config_check_eeh(phb, bus, bdfn);
325 }
326#else
296 pnv_pci_config_check_eeh(phb, bus, bdfn); 327 pnv_pci_config_check_eeh(phb, bus, bdfn);
328#endif
297 329
298 return PCIBIOS_SUCCESSFUL; 330 return PCIBIOS_SUCCESSFUL;
299} 331}
@@ -324,8 +356,14 @@ static int pnv_pci_write_config(struct pci_bus *bus,
324 default: 356 default:
325 return PCIBIOS_FUNC_NOT_SUPPORTED; 357 return PCIBIOS_FUNC_NOT_SUPPORTED;
326 } 358 }
359
327 /* Check if the PHB got frozen due to an error (no response) */ 360 /* Check if the PHB got frozen due to an error (no response) */
361#ifdef CONFIG_EEH
362 if (!phb->eeh_enabled)
363 pnv_pci_config_check_eeh(phb, bus, bdfn);
364#else
328 pnv_pci_config_check_eeh(phb, bus, bdfn); 365 pnv_pci_config_check_eeh(phb, bus, bdfn);
366#endif
329 367
330 return PCIBIOS_SUCCESSFUL; 368 return PCIBIOS_SUCCESSFUL;
331} 369}