[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