[Skiboot] [PATCH 3/4] core/i2c: split i2c_request_send()

Oliver O'Halloran oohall at gmail.com
Tue Mar 26 19:18:18 AEDT 2019


Split the i2c_request_send() method into two methods: i2c_request_send()
which allocates and populates and i2c_request structure, and
i2c_request_sync() which take a request structure and blocks until it
completes.

This allows code that allocates a i2c_request structure elsewhere to
make use of the existing busy-wait and request retry logic. Fix the
return types to use int64_t while we're here since these are returning
OPAL_API error codes.

Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
 core/i2c.c    | 97 ++++++++++++++++++++++++++++-----------------------
 include/i2c.h |  3 +-
 2 files changed, 55 insertions(+), 45 deletions(-)

diff --git a/core/i2c.c b/core/i2c.c
index e78b6b616494..07303e7539b6 100644
--- a/core/i2c.c
+++ b/core/i2c.c
@@ -140,6 +140,56 @@ opal_call(OPAL_I2C_REQUEST, opal_i2c_request, 3);
 #define MAX_NACK_RETRIES		 2
 #define REQ_COMPLETE_POLLING		 5  /* Check if req is complete
 					       in 5ms interval */
+int64_t i2c_request_sync(struct i2c_request *req)
+{
+	uint64_t timer_period = msecs_to_tb(5), timer_count;
+	uint64_t time_to_wait = 0;
+	int64_t rc, waited, retries;
+
+	for (retries = 0; retries <= MAX_NACK_RETRIES; retries++) {
+		waited = 0;
+		timer_count = 0;
+
+		i2c_queue_req(req);
+
+		do {
+			time_to_wait = i2c_run_req(req);
+			if (!time_to_wait)
+				time_to_wait = REQ_COMPLETE_POLLING;
+			time_wait(time_to_wait);
+			waited += time_to_wait;
+			timer_count += time_to_wait;
+			if (timer_count > timer_period) {
+				/*
+				 * The above request may be relying on
+				 * timers to complete, yet there may
+				 * not be called, especially during
+				 * opal init. We could be looping here
+				 * forever. So explicitly check the
+				 * timers once in a while
+				 */
+				check_timers(false);
+				timer_count = 0;
+			}
+		} while (req->req_state != i2c_req_done);
+
+		lwsync();
+		rc = req->result;
+
+		/* retry on NACK, otherwise exit */
+		if (rc != OPAL_I2C_NACK_RCVD)
+			break;
+		req->req_state = i2c_req_new;
+	}
+
+	prlog(PR_DEBUG, "I2C: %s req op=%x offset=%x buf=%016llx buflen=%d "
+	      "delay=%lu/%lld rc=%lld\n",
+	      (rc) ? "!!!!" : "----", req->op, req->offset,
+	      *(uint64_t*) req->rw_buf, req->rw_len, tb_to_msecs(waited), req->timeout, rc);
+
+	return rc;
+}
+
 /**
  * i2c_request_send - send request to i2c bus synchronously
  * @bus_id: i2c bus id
@@ -155,15 +205,13 @@ opal_call(OPAL_I2C_REQUEST, opal_i2c_request, 3);
  *
  * Returns: Zero on success otherwise a negative error code
  */
-int i2c_request_send(int bus_id, int dev_addr, int read_write,
+int64_t i2c_request_send(int bus_id, int dev_addr, int read_write,
 		     uint32_t offset, uint32_t offset_bytes, void* buf,
 		     size_t buflen, int timeout)
 {
-	int rc, waited, retries;
 	struct i2c_request *req;
 	struct i2c_bus *bus;
-	uint64_t time_to_wait = 0;
-	uint64_t timer_period = msecs_to_tb(5), timer_count;
+	int64_t rc;
 
 	bus = i2c_find_bus_by_id(bus_id);
 	if (!bus) {
@@ -197,46 +245,7 @@ int i2c_request_send(int bus_id, int dev_addr, int read_write,
 	req->rw_len     = buflen;
 	req->timeout    = timeout;
 
-	for (retries = 0; retries <= MAX_NACK_RETRIES; retries++) {
-		waited = 0;
-		timer_count = 0;
-
-		i2c_queue_req(req);
-
-		do {
-			time_to_wait = i2c_run_req(req);
-			if (!time_to_wait)
-				time_to_wait = REQ_COMPLETE_POLLING;
-			time_wait(time_to_wait);
-			waited += time_to_wait;
-			timer_count += time_to_wait;
-			if (timer_count > timer_period) {
-				/*
-				 * The above request may be relying on
-				 * timers to complete, yet there may
-				 * not be called, especially during
-				 * opal init. We could be looping here
-				 * forever. So explicitly check the
-				 * timers once in a while
-				 */
-				check_timers(false);
-				timer_count = 0;
-			}
-		} while (req->req_state != i2c_req_done);
-
-		lwsync();
-		rc = req->result;
-
-		/* retry on NACK, otherwise exit */
-		if (rc != OPAL_I2C_NACK_RCVD)
-			break;
-		req->req_state = i2c_req_new;
-	}
-
-	prlog(PR_DEBUG, "I2C: %s req op=%x offset=%x buf=%016llx buflen=%d "
-	      "delay=%lu/%d rc=%d\n",
-	      (rc) ? "!!!!" : "----", req->op, req->offset,
-	      *(uint64_t*) buf, req->rw_len, tb_to_msecs(waited), timeout, rc);
+	rc = i2c_request_sync(req);
 
 	free(req);
 	if (rc)
diff --git a/include/i2c.h b/include/i2c.h
index 484176f93508..e5306837fe36 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -98,7 +98,8 @@ static inline int i2c_check_quirk(struct i2c_request *req, int *rc)
 }
 
 /* I2C synchronous request API */
-int i2c_request_send(int bus_id, int dev_addr, int read_write,
+int64_t i2c_request_sync(struct i2c_request *req);
+int64_t i2c_request_send(int bus_id, int dev_addr, int read_write,
 		     uint32_t offset, uint32_t offset_bytes, void* buf,
 		     size_t buflen, int timeout);
 
-- 
2.20.1



More information about the Skiboot mailing list