aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2017-12-08 16:19:35 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-12-11 19:30:46 -0600
commit363f328fbc597a5996fc3b28e509c09f2869888f (patch)
tree0d8051cf2cdf71b5fdfacf87e9d8c9f611660180 /hw
parent5cee066746d238feef51dd7b0359c3456b089748 (diff)
downloadskiboot-363f328fbc597a5996fc3b28e509c09f2869888f.zip
skiboot-363f328fbc597a5996fc3b28e509c09f2869888f.tar.gz
skiboot-363f328fbc597a5996fc3b28e509c09f2869888f.tar.bz2
opal/xscom: Move the delay inside xscom_reset() function.
So caller of xscom_reset() does not have to bother about adding a delay separately. Instead caller can control whether to add a delay or not using second argument to xscom_reset(). Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/xscom.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/hw/xscom.c b/hw/xscom.c
index 5b3bd88..d98f5ef 100644
--- a/hw/xscom.c
+++ b/hw/xscom.c
@@ -92,10 +92,11 @@ static uint64_t xscom_wait_done(void)
return mfspr(SPR_HMER);
}
-static void xscom_reset(uint32_t gcid)
+static void xscom_reset(uint32_t gcid, bool need_delay)
{
u64 hmer;
uint32_t recv_status_reg, log_reg, err_reg;
+ struct timespec ts;
/* Clear errors in HMER */
mtspr(SPR_HMER, HMER_CLR_MASK);
@@ -126,6 +127,21 @@ static void xscom_reset(uint32_t gcid)
hmer = xscom_wait_done();
if (hmer & SPR_HMER_XSCOM_FAIL)
goto fail;
+
+ if (need_delay) {
+ /*
+ * Its observed that sometimes immediate retry of
+ * XSCOM operation returns wrong data. Adding a
+ * delay for XSCOM reset to be effective. Delay of
+ * 10 ms is found to be working fine experimentally.
+ * FIXME: Replace 10ms delay by exact delay needed
+ * or other alternate method to confirm XSCOM reset
+ * completion, after checking from HW folks.
+ */
+ ts.tv_sec = 0;
+ ts.tv_nsec = 10 * 1000;
+ nanosleep_nopoll(&ts, NULL);
+ }
return;
fail:
/* Fatal error resetting XSCOM */
@@ -140,7 +156,6 @@ static void xscom_reset(uint32_t gcid)
static int64_t xscom_handle_error(uint64_t hmer, uint32_t gcid, uint32_t pcb_addr,
bool is_write, int64_t retries)
{
- struct timespec ts;
unsigned int stat = GETFIELD(SPR_HMER_XSCOM_STATUS, hmer);
int64_t rc = OPAL_HARDWARE;
@@ -158,20 +173,8 @@ static int64_t xscom_handle_error(uint64_t hmer, uint32_t gcid, uint32_t pcb_add
prlog(PR_NOTICE, "XSCOM: Busy even after %d retries, "
"resetting XSCOM now. Total retries = %lld\n",
XSCOM_BUSY_RESET_THRESHOLD, retries);
- xscom_reset(gcid);
-
- /*
- * Its observed that sometimes immediate retry of
- * XSCOM operation returns wrong data. Adding a
- * delay for XSCOM reset to be effective. Delay of
- * 10 ms is found to be working fine experimentally.
- * FIXME: Replace 10ms delay by exact delay needed
- * or other alternate method to confirm XSCOM reset
- * completion, after checking from HW folks.
- */
- ts.tv_sec = 0;
- ts.tv_nsec = 10 * 1000;
- nanosleep_nopoll(&ts, NULL);
+ xscom_reset(gcid, true);
+
}
/* Log error if we have retried enough and its still busy */
@@ -183,7 +186,7 @@ static int64_t xscom_handle_error(uint64_t hmer, uint32_t gcid, uint32_t pcb_add
return OPAL_XSCOM_BUSY;
case 2: /* CPU is asleep, reset XSCOM engine and return */
- xscom_reset(gcid);
+ xscom_reset(gcid, false);
return OPAL_XSCOM_CHIPLET_OFF;
case 3: /* Partial good */
rc = OPAL_XSCOM_PARTIAL_GOOD;
@@ -208,7 +211,7 @@ static int64_t xscom_handle_error(uint64_t hmer, uint32_t gcid, uint32_t pcb_add
is_write ? "write" : "read", gcid, pcb_addr, stat);
/* We need to reset the XSCOM or we'll hang on the next access */
- xscom_reset(gcid);
+ xscom_reset(gcid, false);
/* Non recovered ... just fail */
return rc;