aboutsummaryrefslogtreecommitdiff
path: root/hw/phb3.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/phb3.c')
-rw-r--r--hw/phb3.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/hw/phb3.c b/hw/phb3.c
index fd89d16..ebac9d6 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -1964,8 +1964,19 @@ static void phb3_setup_for_link_up(struct phb3 *p)
}
}
+static int64_t phb3_retry_state(struct phb3 *p)
+{
+ if (p->retry_state <= PHB3_STATE_FUNCTIONAL)
+ return OPAL_WRONG_STATE;
+
+ p->delay_tgt_tb = 0;
+ p->state = p->retry_state;
+ return p->phb.ops->poll(&p->phb);
+}
+
static int64_t phb3_sm_link_poll(struct phb3 *p)
{
+ int64_t rc;
uint64_t reg;
/* This is the state machine to wait for the link to come
@@ -1992,6 +2003,10 @@ static int64_t phb3_sm_link_poll(struct phb3 *p)
} else if (p->retries-- == 0) {
PHBDBG(p, "Timeout waiting for electrical link\n");
PHBDBG(p, "DLP train control: 0x%016llx\n", reg);
+ rc = phb3_retry_state(p);
+ if (rc >= OPAL_SUCCESS)
+ return rc;
+
/* No link, we still mark the PHB as functional */
p->state = PHB3_STATE_FUNCTIONAL;
return OPAL_SUCCESS;
@@ -2013,6 +2028,10 @@ static int64_t phb3_sm_link_poll(struct phb3 *p)
if (p->retries-- == 0) {
PHBDBG(p, "Timeout waiting for link up\n");
PHBDBG(p, "DLP train control: 0x%016llx\n", reg);
+ rc = phb3_retry_state(p);
+ if (rc >= OPAL_SUCCESS)
+ return rc;
+
/* No link, we still mark the PHB as functional */
p->state = PHB3_STATE_FUNCTIONAL;
return OPAL_SUCCESS;
@@ -2127,12 +2146,17 @@ static int64_t phb3_sm_fundamental_reset(struct phb3 *p)
switch(p->state) {
case PHB3_STATE_FUNCTIONAL:
- PHBINF(p, "Performing PERST...\n");
-
/* Prepare for link going down */
phb3_setup_for_link_down(p);
+ /* Fall-through */
+ case PHB3_STATE_FRESET_START:
+ if (p->state == PHB3_STATE_FRESET_START) {
+ PHBDBG(p, "Slot freset: Retrying\n");
+ p->retry_state = 0;
+ }
/* Assert PERST */
+ PHBINF(p, "Performing PERST...\n");
reg = in_be64(p->regs + PHB_RESET);
reg &= ~0x2000000000000000ul;
out_be64(p->regs + PHB_RESET, reg);
@@ -2176,6 +2200,8 @@ static int64_t phb3_fundamental_reset(struct phb *phb)
return OPAL_HARDWARE;
}
+ /* Allow to retry fundamental reset */
+ p->retry_state = PHB3_STATE_FRESET_START;
p->flags |= PHB3_CFG_BLOCKED;
return phb3_sm_fundamental_reset(p);
}
@@ -2456,6 +2482,7 @@ static int64_t phb3_poll(struct phb *phb)
case PHB3_STATE_HRESET_DELAY:
case PHB3_STATE_HRESET_DELAY2:
return phb3_sm_hot_reset(p);
+ case PHB3_STATE_FRESET_START:
case PHB3_STATE_FRESET_ASSERT_DELAY:
case PHB3_STATE_FRESET_DEASSERT_DELAY:
return phb3_sm_fundamental_reset(p);