@@ -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_reserved_pe_number)
+ pe_number = phb->ops->get_reserved_pe_number();
+ 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
@@ -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_reserved_pe_number = NULL,
.device_init = NULL,
.phb_final_fixup = npu_phb_final_fixup,
.presence_detect = NULL,
@@ -2304,6 +2304,11 @@ static uint8_t p7ioc_choose_bus(struct phb *phb __unused,
return al;
}
+static int64_t p7ioc_get_reserved_pe_number(void)
+{
+ return 127;
+}
+
/* p7ioc_phb_init_ioda_cache - Reset the IODA cache values
*/
static void p7ioc_phb_init_ioda_cache(struct p7ioc_phb *p)
@@ -2558,6 +2563,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_reserved_pe_number = p7ioc_get_reserved_pe_number,
.device_init = p7ioc_device_init,
.pci_reinit = p7ioc_pci_reinit,
.eeh_freeze_status = p7ioc_eeh_freeze_status,
@@ -295,6 +295,11 @@ static uint8_t phb3_choose_bus(struct phb *phb __unused,
return candidate;
}
+static int64_t phb3_get_reserved_pe_number(void)
+{
+ return PHB3_RESERVED_PE_NUM;
+}
+
static void phb3_root_port_init(struct phb *phb, struct pci_device *dev,
int ecap, int aercap)
{
@@ -3580,6 +3585,7 @@ static const struct phb_ops phb3_ops = {
.cfg_write16 = phb3_pcicfg_write16,
.cfg_write32 = phb3_pcicfg_write32,
.choose_bus = phb3_choose_bus,
+ .get_reserved_pe_number = phb3_get_reserved_pe_number,
.device_init = phb3_device_init,
.presence_detect = phb3_presence_detect,
.ioda_reset = phb3_ioda_reset,
@@ -254,6 +254,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_reserved_pe_number)(void);
/*
* Device init method is called after a device has been detected
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_reserved_pe_number() 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@linux.vnet.ibm.com> --- core/pci.c | 15 ++++++++++++--- hw/npu.c | 1 + hw/p7ioc-phb.c | 6 ++++++ hw/phb3.c | 6 ++++++ include/pci.h | 1 + 5 files changed, 26 insertions(+), 3 deletions(-)