diff mbox series

[v2,09/10] opal/eeh: Add slot location info for frozen PEs.

Message ID 160207258792.2097386.5488556517605058368.stgit@jupiter
State New
Headers show
Series Add support to report EEH errors to BMC/FSP (eSEL) | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success Successfully applied on branch master (f901fcafae14d38e29f1cc11440086ee678785d0)
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot success Test snowpatch/job/snowpatch-skiboot on branch master
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot-dco success Signed-off-by present

Commit Message

Mahesh J Salgaonkar Oct. 7, 2020, 12:09 p.m. UTC
Locate and add slot location information (FRU details) for corresponding
frozen PE number in error log.

Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
---
 core/pci-opal.c |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 hw/phb3.c       |    8 ++++++++
 hw/phb4.c       |    7 +++++++
 include/pci.h   |    1 +
 4 files changed, 60 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/core/pci-opal.c b/core/pci-opal.c
index 34de05ddf..cf0a9ee4b 100644
--- a/core/pci-opal.c
+++ b/core/pci-opal.c
@@ -124,6 +124,48 @@  static void send_phb_freeze_event(struct phb *phb, void *diag_buffer)
 	phb->flags &= ~PCI_EEH_ERR_LOG_SEND;
 }
 
+/* Find the first pci device which macthes pe nummber */
+static struct pci_device *pe_to_pci_device(struct list_head *list,
+							uint64_t pe_num)
+{
+	struct pci_device *pd, *pd1;
+
+	/* Return the first device that matches pe number */
+	list_for_each(list, pd, link) {
+		if (pe_num == pd->phb->ops->get_pe_number(pd->phb, pd->bdfn))
+			return pd;
+
+		pd1 = pe_to_pci_device(&pd->children, pe_num);
+		if (pd1)
+			return pd1;
+	}
+	return NULL;
+}
+
+static void phb_add_pe_slot_loc_info(struct phb *phb, uint64_t pe_number,
+						struct errorlog *buf)
+{
+	struct pci_device *pd;
+	const char *loc = NULL;
+
+	pd = pe_to_pci_device(&phb->devices, pe_number);
+	if (!pd)
+		return;
+
+	/* Get the slot location code from parent PCI bridge device */
+	if (pd->primary_bus != 0)
+		pd = pd->parent;
+
+	/* Keep seraching parent node until we find ibm,slot-location-code */
+	while (pd) {
+		loc = dt_prop_get_def(pd->dn, "ibm,slot-location-code", NULL);
+		if (loc)
+			break;
+		pd = pd->parent;
+	}
+	log_add_callout_section(buf, loc, NULL, NULL);
+}
+
 static void send_phb_pe_freeze_event(struct phb *phb, uint64_t pe_number)
 {
 	struct errorlog *buf;
@@ -153,7 +195,8 @@  static void send_phb_pe_freeze_event(struct phb *phb, uint64_t pe_number)
 	} else
 		prerror("Failed to allocate size for phb diag data\n");
 
-	/* TODO: Add location info of slot with forzen PEs */
+	/* Add location info of slot with forzen PEs */
+	phb_add_pe_slot_loc_info(phb, pe_number, buf);
 
 	send_eeh_serviceable_event(phb, buf, diag_buffer);
 	bitmap_set_bit(*phb->pe_freeze_reported, pe_number);
diff --git a/hw/phb3.c b/hw/phb3.c
index 1bd753bae..67930c6c5 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -344,6 +344,13 @@  static int64_t phb3_get_reserved_pe_number(struct phb *phb __unused)
 	return PHB3_RESERVED_PE_NUM;
 }
 
+static int64_t phb3_get_pe_number(struct phb *phb, uint16_t bdfn)
+{
+	struct phb3 *p = phb_to_phb3(phb);
+
+	return be16_to_cpu(p->rte_cache[bdfn]);
+}
+
 static inline void phb3_enable_ecrc(struct phb *phb, bool enable)
 {
 	struct phb3 *p = phb_to_phb3(phb);
@@ -3867,6 +3874,7 @@  static const struct phb_ops phb3_ops = {
 	.cfg_write16		= phb3_pcicfg_write16,
 	.cfg_write32		= phb3_pcicfg_write32,
 	.get_reserved_pe_number	= phb3_get_reserved_pe_number,
+	.get_pe_number		= phb3_get_pe_number,
 	.device_init		= phb3_device_init,
 	.device_remove		= phb3_device_remove,
 	.ioda_reset		= phb3_ioda_reset,
diff --git a/hw/phb4.c b/hw/phb4.c
index a088a640e..1d6dad20b 100644
--- a/hw/phb4.c
+++ b/hw/phb4.c
@@ -608,6 +608,12 @@  static int64_t phb4_get_reserved_pe_number(struct phb *phb)
 	return PHB4_RESERVED_PE_NUM(p);
 }
 
+static int64_t phb4_get_pe_number(struct phb *phb, uint16_t bdfn)
+{
+	struct phb4 *p = phb_to_phb4(phb);
+
+	return be16_to_cpu(p->tbl_rtt[bdfn]);
+}
 
 static void phb4_root_port_init(struct phb *phb, struct pci_device *dev,
 				int ecap, int aercap)
@@ -4930,6 +4936,7 @@  static const struct phb_ops phb4_ops = {
 	.cfg_write16		= phb4_pcicfg_write16,
 	.cfg_write32		= phb4_pcicfg_write32,
 	.get_reserved_pe_number	= phb4_get_reserved_pe_number,
+	.get_pe_number		= phb4_get_pe_number,
 	.device_init		= phb4_device_init,
 	.device_remove		= NULL,
 	.ioda_reset		= phb4_ioda_reset,
diff --git a/include/pci.h b/include/pci.h
index 8da57a954..9f7b3089b 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -222,6 +222,7 @@  struct phb_ops {
 			       uint32_t offset, uint32_t data);
 
 	int64_t (*get_reserved_pe_number)(struct phb *phb);
+	int64_t (*get_pe_number)(struct phb *phb, uint16_t bdfn);
 
 	/*
 	 * Device init method is called after a device has been detected