[Skiboot] [PATCH v2 1/2] opal/xscom: Move the delay inside xscom_reset() function.

Mahesh J Salgaonkar mahesh at linux.vnet.ibm.com
Fri Dec 8 21:49:35 AEDT 2017


From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

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 at linux.vnet.ibm.com>
---
Changes in V2:
- Add a bool argument to xscom_reset() to give the control to caller whether to
  delay is required or not after reset.
---
 hw/xscom.c |   39 +++++++++++++++++++++------------------
 1 file 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;



More information about the Skiboot mailing list