aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
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,