[Skiboot] [PATCH v11 09/23] core/pci: Fix wrong reserved PE# in enumeration

Gavin Shan gwshan at linux.vnet.ibm.com
Fri May 20 16:32:11 AEST 2016


When scanning to non-existing PCI device, EEH (frozen) error is
usually happening. We clear the unexpected frozen PE state after
it. The reserved PE number is assumed to be 0 wrongly. So the
frozen state on the reserved PE number isn't cleared properly.

This introduces struct phb_ops::get_info() to retrieve the reserved
PE number from platforms. Then the EEH frozen state checking and
clearing are applied to the reserved PE number.

Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
---
 core/pci.c     | 15 ++++++++++++---
 hw/npu.c       |  1 +
 hw/p7ioc-phb.c | 15 +++++++++++++++
 hw/phb3.c      | 16 ++++++++++++++++
 include/pci.h  |  7 +++++++
 5 files changed, 51 insertions(+), 3 deletions(-)

diff --git a/core/pci.c b/core/pci.c
index 9b238d0..5178fd1 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -274,11 +274,19 @@ static struct pci_device *pci_scan_one(struct phb *phb, struct pci_device *paren
  */
 static void pci_check_clear_freeze(struct phb *phb)
 {
-	int64_t rc;
 	uint8_t freeze_state;
 	uint16_t pci_error_type, sev;
+	int64_t pe_number, rc;
+
+	/* Retrieve the reserved PE number */
+	pe_number = OPAL_PARAMETER;
+	if (phb->ops->get_info)
+		pe_number = phb->ops->get_info(phb, PHB_INFO_RESERVED_PE_NUM);
+	if (pe_number < 0)
+		return;
 
-	rc = phb->ops->eeh_freeze_status(phb, 0, &freeze_state,
+	/* Retrieve the frozen state */
+	rc = phb->ops->eeh_freeze_status(phb, pe_number, &freeze_state,
 					 &pci_error_type, &sev, NULL);
 	if (rc)
 		return;
@@ -290,7 +298,8 @@ static void pci_check_clear_freeze(struct phb *phb)
 		PCIERR(phb, 0, "Fatal probe in %s error !\n", __func__);
 		return;
 	}
-	phb->ops->eeh_freeze_clear(phb, 0, OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+	phb->ops->eeh_freeze_clear(phb, pe_number,
+				   OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
 }
 
 /* pci_enable_bridge - Called before scanning a bridge
diff --git a/hw/npu.c b/hw/npu.c
index 79b232a..1732eae 100644
--- a/hw/npu.c
+++ b/hw/npu.c
@@ -1103,6 +1103,7 @@ static const struct phb_ops npu_ops = {
 	.cfg_write16		= npu_dev_cfg_write16,
 	.cfg_write32		= npu_dev_cfg_write32,
 	.choose_bus		= NULL,
+	.get_info		= NULL,
 	.device_init		= NULL,
 	.phb_final_fixup	= npu_phb_final_fixup,
 	.presence_detect	= NULL,
diff --git a/hw/p7ioc-phb.c b/hw/p7ioc-phb.c
index bad7d0a..f574a24 100644
--- a/hw/p7ioc-phb.c
+++ b/hw/p7ioc-phb.c
@@ -2304,6 +2304,20 @@ static uint8_t p7ioc_choose_bus(struct phb *phb __unused,
 	return al;
 }
 
+static int64_t p7ioc_get_info(struct phb *phb __unused, int ind)
+{
+	int64_t rc;
+
+	switch (ind) {
+	case PHB_INFO_RESERVED_PE_NUM:
+		rc = 127;
+	default:
+		rc = OPAL_PARAMETER;
+	}
+
+	return rc;
+}
+
 /* p7ioc_phb_init_ioda_cache - Reset the IODA cache values
  */
 static void p7ioc_phb_init_ioda_cache(struct p7ioc_phb *p)
@@ -2558,6 +2572,7 @@ static const struct phb_ops p7ioc_phb_ops = {
 	.cfg_write16		= p7ioc_pcicfg_write16,
 	.cfg_write32		= p7ioc_pcicfg_write32,
 	.choose_bus		= p7ioc_choose_bus,
+	.get_info		= p7ioc_get_info,
 	.device_init		= p7ioc_device_init,
 	.pci_reinit		= p7ioc_pci_reinit,
 	.eeh_freeze_status	= p7ioc_eeh_freeze_status,
diff --git a/hw/phb3.c b/hw/phb3.c
index ab9d117..9fa2bb2 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -295,6 +295,21 @@ static uint8_t phb3_choose_bus(struct phb *phb __unused,
 	return candidate;
 }
 
+static int64_t phb3_get_info(struct phb *phb __unused, int ind)
+{
+	int64_t rc;
+
+	switch (ind) {
+	case PHB_INFO_RESERVED_PE_NUM:
+		rc = PHB3_RESERVED_PE_NUM;
+		break;
+	default:
+		rc = OPAL_PARAMETER;
+	}
+
+	return rc;
+}
+
 static void phb3_root_port_init(struct phb *phb, struct pci_device *dev,
 				int ecap, int aercap)
 {
@@ -3580,6 +3595,7 @@ static const struct phb_ops phb3_ops = {
 	.cfg_write16		= phb3_pcicfg_write16,
 	.cfg_write32		= phb3_pcicfg_write32,
 	.choose_bus		= phb3_choose_bus,
+	.get_info		= phb3_get_info,
 	.device_init		= phb3_device_init,
 	.presence_detect	= phb3_presence_detect,
 	.ioda_reset		= phb3_ioda_reset,
diff --git a/include/pci.h b/include/pci.h
index aec4808..9e85518 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -231,6 +231,12 @@ struct pci_lsi_state {
 struct phb;
 extern int last_phb_id;
 
+enum phb_info {
+	PHB_INFO_MIN = 0,
+	PHB_INFO_RESERVED_PE_NUM,
+	PHB_INFO_MAX
+};
+
 struct phb_ops {
 	/*
 	 * Config space ops
@@ -254,6 +260,7 @@ struct phb_ops {
 	uint8_t (*choose_bus)(struct phb *phb, struct pci_device *bridge,
 			      uint8_t candidate, uint8_t *max_bus,
 			      bool *use_max);
+	int64_t (*get_info)(struct phb *phb, int ind);
 
 	/*
 	 * Device init method is called after a device has been detected
-- 
2.1.0



More information about the Skiboot mailing list