[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