[Skiboot] [PATCH 04/10] i2c,trace: Add I2C operation trace events

Oliver O'Halloran oohall at gmail.com
Mon Oct 12 13:53:08 AEDT 2020


Add support for tracing I2C transactions performed by skiboot. This covers
both internally initiated I2C ops and those that requested by the kernel
via the OPAL API.

Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
 core/i2c.c                  | 32 ++++++++++++++++++++++++++++++++
 external/trace/dump_trace.c | 33 +++++++++++++++++++++++++++++++++
 include/i2c.h               |  9 +--------
 include/trace_types.h       | 12 ++++++++++++
 4 files changed, 78 insertions(+), 8 deletions(-)

diff --git a/core/i2c.c b/core/i2c.c
index fd9308126d64..b4313d430f3e 100644
--- a/core/i2c.c
+++ b/core/i2c.c
@@ -13,6 +13,7 @@
 #include <timebase.h>
 #include <processor.h>
 #include <timer.h>
+#include <trace.h>
 
 static LIST_HEAD(i2c_bus_list);
 
@@ -38,6 +39,34 @@ struct i2c_bus *i2c_find_bus_by_id(uint32_t opal_id)
 	return NULL;
 }
 
+static inline void i2c_trace_req(struct i2c_request *req, int rc)
+{
+	struct trace_i2c t;
+
+	memset(&t, 0, sizeof(t));
+
+	t.bus = req->bus->opal_id;
+	t.type = req->op | (req->offset_bytes << 4);
+	t.i2c_addr = req->dev_addr;
+	t.smbus_reg = req->offset & 0xffff; // FIXME: log whole offset
+	t.size = req->rw_len;
+	t.rc = rc;
+
+	/* FIXME: trace should not be a union... */
+	trace_add((void *)&t, TRACE_I2C, sizeof(t));
+}
+
+int64_t i2c_queue_req(struct i2c_request *req)
+{
+	int64_t ret = req->bus->queue_req(req);
+
+	i2c_trace_req(req, OPAL_ASYNC_COMPLETION);
+
+	if (!ret)
+		req->req_state = i2c_req_queued;
+	return ret;
+}
+
 static void opal_i2c_request_complete(int rc, struct i2c_request *req)
 {
 	uint64_t token = (uint64_t)(unsigned long)req->user_data;
@@ -45,6 +74,8 @@ static void opal_i2c_request_complete(int rc, struct i2c_request *req)
 	opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL,
 			cpu_to_be64(token),
 			cpu_to_be64(rc));
+	i2c_trace_req(req, rc);
+
 	free(req);
 }
 
@@ -177,6 +208,7 @@ int64_t i2c_request_sync(struct i2c_request *req)
 		req->req_state = i2c_req_new;
 	}
 
+	i2c_trace_req(req, rc);
 	count = 0;
 	for (i = 0; i < req->rw_len && count < sizeof(buf); i++) {
 		count += snprintf(buf+count, sizeof(buf)-count, "%02x",
diff --git a/external/trace/dump_trace.c b/external/trace/dump_trace.c
index c68eea894715..f54dfa08130d 100644
--- a/external/trace/dump_trace.c
+++ b/external/trace/dump_trace.c
@@ -149,6 +149,36 @@ static void dump_uart(struct trace_uart *t)
 	}
 }
 
+static void dump_i2c(struct trace_i2c *t)
+{
+	uint16_t type = be16_to_cpu(t->type);
+
+	printf("I2C: bus: %d dev: %02x len: %x ",
+			be16_to_cpu(t->bus),
+			be16_to_cpu(t->i2c_addr),
+			be16_to_cpu(t->size)
+			);
+
+	switch (type & 0x3) {
+	case 0:
+		printf("read");
+		break;
+	case 1:
+		printf("write");
+		break;
+	case 2:
+		printf("smbus read from %x", be16_to_cpu(t->smbus_reg));
+		break;
+	case 3:
+		printf("smbus write to %x", be16_to_cpu(t->smbus_reg));
+		break;
+	default:
+		printf("u wot?");
+	}
+
+	printf(", rc = %hd\n", (int16_t) be16_to_cpu(t->rc));
+}
+
 static void load_traces(struct trace_reader *trs, int count)
 {
 	struct trace_entry *te;
@@ -189,6 +219,9 @@ static void print_trace(union trace *t)
 	case TRACE_UART:
 		dump_uart(&t->uart);
 		break;
+	case TRACE_I2C:
+		dump_i2c(&t->i2c);
+		break;
 	default:
 		printf("UNKNOWN(%u) CPU %u length %u\n",
 		       t->hdr.type, be16_to_cpu(t->hdr.cpu),
diff --git a/include/i2c.h b/include/i2c.h
index c4ad805d4451..2c67a0ea22ea 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -61,14 +61,7 @@ struct i2c_request {
 extern void i2c_add_bus(struct i2c_bus *bus);
 extern struct i2c_bus *i2c_find_bus_by_id(uint32_t opal_id);
 
-static inline int64_t i2c_queue_req(struct i2c_request *req)
-{
-	int64_t ret = req->bus->queue_req(req);
-
-	if (!ret)
-		req->req_state = i2c_req_queued;
-	return ret;
-}
+int64_t i2c_queue_req(struct i2c_request *req);
 
 static inline uint64_t i2c_run_req(struct i2c_request *req)
 {
diff --git a/include/trace_types.h b/include/trace_types.h
index 5942a1fa46ed..4ebf5a0a8357 100644
--- a/include/trace_types.h
+++ b/include/trace_types.h
@@ -16,6 +16,7 @@
 #define TRACE_FSP_MSG	4	/* FSP message sent/received */
 #define TRACE_FSP_EVENT	5	/* FSP driver event */
 #define TRACE_UART	6	/* UART driver traces */
+#define TRACE_I2C	7	/* I2C driver traces */
 
 /* One per cpu, plus one for NMIs */
 struct tracebuf {
@@ -107,6 +108,16 @@ struct trace_uart {
 	__be16 in_count;
 };
 
+struct trace_i2c {
+	struct trace_hdr hdr;
+	u16 bus;
+	u16 type;
+	u16 i2c_addr;
+	u16 smbus_reg;
+	u16 size;
+	s16 rc;
+};
+
 union trace {
 	struct trace_hdr hdr;
 	/* Trace types go here... */
@@ -116,6 +127,7 @@ union trace {
 	struct trace_fsp_msg fsp_msg;
 	struct trace_fsp_event fsp_evt;
 	struct trace_uart uart;
+	struct trace_i2c i2c;
 };
 
 #endif /* __TRACE_TYPES_H */
-- 
2.26.2



More information about the Skiboot mailing list