aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2014-07-17 00:41:43 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-05 01:41:43 -0400
commitbb593c0049fd6b6e420a6f68c5a688e14782dba1 (patch)
tree844f038aca08d97c89fb02b8b167f19fea2d141c /arch/powerpc/platforms
parentf18440fb7e4f95d2a8f882d3d27c8777101fac12 (diff)
powerpc/eeh: Aux PE data for error log
The patch allows PE (struct eeh_pe) instance to have auxillary data, whose size is configurable on basis of platform. For PowerNV, the auxillary data will be used to cache PHB diag-data for that PE (frozen PE or fenced PHB). In turn, we can retrieve the diag-data at any later points. It's useful for the case of VFIO PCI devices where the error log should be cached, and then be retrieved by the guest at later point. Also, it can avoid PHB diag-data overwritting if another frozen PE reported and the previous diag-data isn't fetched by guest. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c42
-rw-r--r--arch/powerpc/platforms/powernv/eeh-powernv.c3
2 files changed, 31 insertions, 14 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 4909e5f3adda..f4d0259a63c3 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -239,20 +239,16 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option)
239 return ret; 239 return ret;
240} 240}
241 241
242static void ioda_eeh_phb_diag(struct pci_controller *hose) 242static void ioda_eeh_phb_diag(struct eeh_pe *pe)
243{ 243{
244 struct pnv_phb *phb = hose->private_data; 244 struct pnv_phb *phb = pe->phb->private_data;
245 long rc; 245 long rc;
246 246
247 rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, 247 rc = opal_pci_get_phb_diag_data2(phb->opal_id, pe->data,
248 PNV_PCI_DIAG_BUF_SIZE); 248 PNV_PCI_DIAG_BUF_SIZE);
249 if (rc != OPAL_SUCCESS) { 249 if (rc != OPAL_SUCCESS)
250 pr_warn("%s: Failed to get diag-data for PHB#%x (%ld)\n", 250 pr_warn("%s: Failed to get diag-data for PHB#%x (%ld)\n",
251 __func__, hose->global_number, rc); 251 __func__, pe->phb->global_number, rc);
252 return;
253 }
254
255 pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
256} 252}
257 253
258/** 254/**
@@ -323,7 +319,7 @@ static int ioda_eeh_get_state(struct eeh_pe *pe)
323 result |= EEH_STATE_DMA_ENABLED; 319 result |= EEH_STATE_DMA_ENABLED;
324 } else if (!(pe->state & EEH_PE_ISOLATED)) { 320 } else if (!(pe->state & EEH_PE_ISOLATED)) {
325 eeh_pe_state_mark(pe, EEH_PE_ISOLATED); 321 eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
326 ioda_eeh_phb_diag(hose); 322 ioda_eeh_phb_diag(pe);
327 } 323 }
328 324
329 return result; 325 return result;
@@ -373,7 +369,7 @@ static int ioda_eeh_get_state(struct eeh_pe *pe)
373 (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) && 369 (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
374 !(pe->state & EEH_PE_ISOLATED)) { 370 !(pe->state & EEH_PE_ISOLATED)) {
375 eeh_pe_state_mark(pe, EEH_PE_ISOLATED); 371 eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
376 ioda_eeh_phb_diag(hose); 372 ioda_eeh_phb_diag(pe);
377 } 373 }
378 374
379 return result; 375 return result;
@@ -589,6 +585,24 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option)
589} 585}
590 586
591/** 587/**
588 * ioda_eeh_get_log - Retrieve error log
589 * @pe: frozen PE
590 * @severity: permanent or temporary error
591 * @drv_log: device driver log
592 * @len: length of device driver log
593 *
594 * Retrieve error log, which contains log from device driver
595 * and firmware.
596 */
597int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
598 char *drv_log, unsigned long len)
599{
600 pnv_pci_dump_phb_diag_data(pe->phb, pe->data);
601
602 return 0;
603}
604
605/**
592 * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE 606 * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
593 * @pe: EEH PE 607 * @pe: EEH PE
594 * 608 *
@@ -805,7 +819,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
805 "detected, location: %s\n", 819 "detected, location: %s\n",
806 hose->global_number, 820 hose->global_number,
807 eeh_pe_loc_get(phb_pe)); 821 eeh_pe_loc_get(phb_pe));
808 ioda_eeh_phb_diag(hose); 822 ioda_eeh_phb_diag(phb_pe);
823 pnv_pci_dump_phb_diag_data(hose, phb_pe->data);
809 ret = EEH_NEXT_ERR_NONE; 824 ret = EEH_NEXT_ERR_NONE;
810 } 825 }
811 826
@@ -853,7 +868,7 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
853 ret == EEH_NEXT_ERR_FENCED_PHB) && 868 ret == EEH_NEXT_ERR_FENCED_PHB) &&
854 !((*pe)->state & EEH_PE_ISOLATED)) { 869 !((*pe)->state & EEH_PE_ISOLATED)) {
855 eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); 870 eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
856 ioda_eeh_phb_diag(hose); 871 ioda_eeh_phb_diag(*pe);
857 } 872 }
858 873
859 /* 874 /*
@@ -899,6 +914,7 @@ struct pnv_eeh_ops ioda_eeh_ops = {
899 .set_option = ioda_eeh_set_option, 914 .set_option = ioda_eeh_set_option,
900 .get_state = ioda_eeh_get_state, 915 .get_state = ioda_eeh_get_state,
901 .reset = ioda_eeh_reset, 916 .reset = ioda_eeh_reset,
917 .get_log = ioda_eeh_get_log,
902 .configure_bridge = ioda_eeh_configure_bridge, 918 .configure_bridge = ioda_eeh_configure_bridge,
903 .next_error = ioda_eeh_next_error 919 .next_error = ioda_eeh_next_error
904}; 920};
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 4a113f3c9171..fd7a16f855ed 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -326,7 +326,7 @@ static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait)
326 * Retrieve the temporary or permanent error from the PE. 326 * Retrieve the temporary or permanent error from the PE.
327 */ 327 */
328static int powernv_eeh_get_log(struct eeh_pe *pe, int severity, 328static int powernv_eeh_get_log(struct eeh_pe *pe, int severity,
329 char *drv_log, unsigned long len) 329 char *drv_log, unsigned long len)
330{ 330{
331 struct pci_controller *hose = pe->phb; 331 struct pci_controller *hose = pe->phb;
332 struct pnv_phb *phb = hose->private_data; 332 struct pnv_phb *phb = hose->private_data;
@@ -430,6 +430,7 @@ static int __init eeh_powernv_init(void)
430{ 430{
431 int ret = -EINVAL; 431 int ret = -EINVAL;
432 432
433 eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE);
433 ret = eeh_ops_register(&powernv_eeh_ops); 434 ret = eeh_ops_register(&powernv_eeh_ops);
434 if (!ret) 435 if (!ret)
435 pr_info("EEH: PowerNV platform initialized\n"); 436 pr_info("EEH: PowerNV platform initialized\n");