[Skiboot] [PATCH v2 09/10] opal/eeh: Add slot location info for frozen PEs.
Mahesh Salgaonkar
mahesh at linux.ibm.com
Wed Oct 7 23:09:47 AEDT 2020
Locate and add slot location information (FRU details) for corresponding
frozen PE number in error log.
Signed-off-by: Mahesh Salgaonkar <mahesh at 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 --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
More information about the Skiboot
mailing list