aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-07-21 00:42:35 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-05 02:33:39 -0400
commit98fd7002878385bd542def73eac34acc75f683ee (patch)
tree9a38feddddadf9f19b78b9f537b7fc06c27dbec8 /arch/powerpc
parent5828790931901329c5e2c5ec0baf1c3c2b74967f (diff)
powerpc/powernv: Handle compound PE in config accessors
The PCI config accessors check for PE frozen state and clear it if EEH isn't functional. The patch handles compound PE in config accessors if PHB supports it. For consistency, all PEs will be put into frozen state if any one in compound group gets frozen by hardware. Signed-off-by: Gavin Shan <gwshan@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.c87
1 files changed, 59 insertions, 28 deletions
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index de376584a96d..b854b57ed5e1 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -337,43 +337,52 @@ void pnv_pci_dump_phb_diag_data(struct pci_controller *hose,
337static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no) 337static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
338{ 338{
339 unsigned long flags, rc; 339 unsigned long flags, rc;
340 int has_diag; 340 int has_diag, ret = 0;
341 341
342 spin_lock_irqsave(&phb->lock, flags); 342 spin_lock_irqsave(&phb->lock, flags);
343 343
344 /* Fetch PHB diag-data */
344 rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, 345 rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
345 PNV_PCI_DIAG_BUF_SIZE); 346 PNV_PCI_DIAG_BUF_SIZE);
346 has_diag = (rc == OPAL_SUCCESS); 347 has_diag = (rc == OPAL_SUCCESS);
347 348
348 rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, 349 /* If PHB supports compound PE, to handle it */
350 if (phb->unfreeze_pe) {
351 ret = phb->unfreeze_pe(phb,
352 pe_no,
349 OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); 353 OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
350 if (rc) { 354 } else {
351 pr_warning("PCI %d: Failed to clear EEH freeze state" 355 rc = opal_pci_eeh_freeze_clear(phb->opal_id,
352 " for PE#%d, err %ld\n", 356 pe_no,
353 phb->hose->global_number, pe_no, rc); 357 OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
354 358 if (rc) {
355 /* For now, let's only display the diag buffer when we fail to clear 359 pr_warn("%s: Failure %ld clearing frozen "
356 * the EEH status. We'll do more sensible things later when we have 360 "PHB#%x-PE#%x\n",
357 * proper EEH support. We need to make sure we don't pollute ourselves 361 __func__, rc, phb->hose->global_number,
358 * with the normal errors generated when probing empty slots 362 pe_no);
359 */ 363 ret = -EIO;
360 if (has_diag) 364 }
361 pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
362 else
363 pr_warning("PCI %d: No diag data available\n",
364 phb->hose->global_number);
365 } 365 }
366 366
367 /*
368 * For now, let's only display the diag buffer when we fail to clear
369 * the EEH status. We'll do more sensible things later when we have
370 * proper EEH support. We need to make sure we don't pollute ourselves
371 * with the normal errors generated when probing empty slots
372 */
373 if (has_diag && ret)
374 pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
375
367 spin_unlock_irqrestore(&phb->lock, flags); 376 spin_unlock_irqrestore(&phb->lock, flags);
368} 377}
369 378
370static void pnv_pci_config_check_eeh(struct pnv_phb *phb, 379static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
371 struct device_node *dn) 380 struct device_node *dn)
372{ 381{
373 s64 rc;
374 u8 fstate; 382 u8 fstate;
375 __be16 pcierr; 383 __be16 pcierr;
376 u32 pe_no; 384 int pe_no;
385 s64 rc;
377 386
378 /* 387 /*
379 * Get the PE#. During the PCI probe stage, we might not 388 * Get the PE#. During the PCI probe stage, we might not
@@ -388,20 +397,42 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb,
388 pe_no = phb->ioda.reserved_pe; 397 pe_no = phb->ioda.reserved_pe;
389 } 398 }
390 399
391 /* Read freeze status */ 400 /*
392 rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr, 401 * Fetch frozen state. If the PHB support compound PE,
393 NULL); 402 * we need handle that case.
394 if (rc) { 403 */
395 pr_warning("%s: Can't read EEH status (PE#%d) for " 404 if (phb->get_pe_state) {
396 "%s, err %lld\n", 405 fstate = phb->get_pe_state(phb, pe_no);
397 __func__, pe_no, dn->full_name, rc); 406 } else {
398 return; 407 rc = opal_pci_eeh_freeze_status(phb->opal_id,
408 pe_no,
409 &fstate,
410 &pcierr,
411 NULL);
412 if (rc) {
413 pr_warn("%s: Failure %lld getting PHB#%x-PE#%x state\n",
414 __func__, rc, phb->hose->global_number, pe_no);
415 return;
416 }
399 } 417 }
418
400 cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n", 419 cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
401 (PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn), 420 (PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn),
402 pe_no, fstate); 421 pe_no, fstate);
403 if (fstate != 0) 422
423 /* Clear the frozen state if applicable */
424 if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE ||
425 fstate == OPAL_EEH_STOPPED_DMA_FREEZE ||
426 fstate == OPAL_EEH_STOPPED_MMIO_DMA_FREEZE) {
427 /*
428 * If PHB supports compound PE, freeze it for
429 * consistency.
430 */
431 if (phb->freeze_pe)
432 phb->freeze_pe(phb, pe_no);
433
404 pnv_pci_handle_eeh_config(phb, pe_no); 434 pnv_pci_handle_eeh_config(phb, pe_no);
435 }
405} 436}
406 437
407int pnv_pci_cfg_read(struct device_node *dn, 438int pnv_pci_cfg_read(struct device_node *dn,