Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: add tracepoints for I2C slave events

I2C slave events tracepoints can be enabled by:

echo 1 > /sys/kernel/tracing/events/i2c_slave/enable

and logs in /sys/kernel/tracing/trace will look like:

... i2c_slave: i2c-0 a=010 ret=0 WR_REQ []
... i2c_slave: i2c-0 a=010 ret=0 WR_RCV [02]
... i2c_slave: i2c-0 a=010 ret=0 WR_RCV [0c]
... i2c_slave: i2c-0 a=010 ret=0 STOP []
... i2c_slave: i2c-0 a=010 ret=0 RD_REQ [04]
... i2c_slave: i2c-0 a=010 ret=0 RD_PRO [b4]
... i2c_slave: i2c-0 a=010 ret=0 STOP []

formatted as:

i2c-<adapter_nr>
a=<addr>
ret=<ret> <- callback return value
<event>
[<data>]

trace printings can be selected by adding a filter like:

echo adapter_nr==1 >/sys/kernel/tracing/events/i2c_slave/filter

Signed-off-by: Jae Hyun Yoo <quic_jaehyoo@quicinc.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>

authored by

Jae Hyun Yoo and committed by
Wolfram Sang
d714fb25 3364c0ef

+84 -6
+15
drivers/i2c/i2c-core-slave.c
··· 14 14 15 15 #include "i2c-core.h" 16 16 17 + #define CREATE_TRACE_POINTS 18 + #include <trace/events/i2c_slave.h> 19 + 17 20 int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb) 18 21 { 19 22 int ret; ··· 81 78 return ret; 82 79 } 83 80 EXPORT_SYMBOL_GPL(i2c_slave_unregister); 81 + 82 + int i2c_slave_event(struct i2c_client *client, 83 + enum i2c_slave_event event, u8 *val) 84 + { 85 + int ret = client->slave_cb(client, event, val); 86 + 87 + if (trace_i2c_slave_enabled()) 88 + trace_i2c_slave(client, event, val, ret); 89 + 90 + return ret; 91 + } 92 + EXPORT_SYMBOL_GPL(i2c_slave_event); 84 93 85 94 /** 86 95 * i2c_detect_slave_mode - detect operation mode
+2 -6
include/linux/i2c.h
··· 392 392 int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb); 393 393 int i2c_slave_unregister(struct i2c_client *client); 394 394 bool i2c_detect_slave_mode(struct device *dev); 395 - 396 - static inline int i2c_slave_event(struct i2c_client *client, 397 - enum i2c_slave_event event, u8 *val) 398 - { 399 - return client->slave_cb(client, event, val); 400 - } 395 + int i2c_slave_event(struct i2c_client *client, 396 + enum i2c_slave_event event, u8 *val); 401 397 #else 402 398 static inline bool i2c_detect_slave_mode(struct device *dev) { return false; } 403 399 #endif
+67
include/trace/events/i2c_slave.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * I2C slave tracepoints 4 + * 5 + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 6 + */ 7 + #undef TRACE_SYSTEM 8 + #define TRACE_SYSTEM i2c_slave 9 + 10 + #if !defined(_TRACE_I2C_SLAVE_H) || defined(TRACE_HEADER_MULTI_READ) 11 + #define _TRACE_I2C_SLAVE_H 12 + 13 + #include <linux/i2c.h> 14 + #include <linux/tracepoint.h> 15 + 16 + TRACE_DEFINE_ENUM(I2C_SLAVE_READ_REQUESTED); 17 + TRACE_DEFINE_ENUM(I2C_SLAVE_WRITE_REQUESTED); 18 + TRACE_DEFINE_ENUM(I2C_SLAVE_READ_PROCESSED); 19 + TRACE_DEFINE_ENUM(I2C_SLAVE_WRITE_RECEIVED); 20 + TRACE_DEFINE_ENUM(I2C_SLAVE_STOP); 21 + 22 + #define show_event_type(type) \ 23 + __print_symbolic(type, \ 24 + { I2C_SLAVE_READ_REQUESTED, "RD_REQ" }, \ 25 + { I2C_SLAVE_WRITE_REQUESTED, "WR_REQ" }, \ 26 + { I2C_SLAVE_READ_PROCESSED, "RD_PRO" }, \ 27 + { I2C_SLAVE_WRITE_RECEIVED, "WR_RCV" }, \ 28 + { I2C_SLAVE_STOP, " STOP" }) 29 + 30 + TRACE_EVENT(i2c_slave, 31 + TP_PROTO(const struct i2c_client *client, enum i2c_slave_event event, 32 + __u8 *val, int cb_ret), 33 + TP_ARGS(client, event, val, cb_ret), 34 + TP_STRUCT__entry( 35 + __field(int, adapter_nr ) 36 + __field(int, ret ) 37 + __field(__u16, addr ) 38 + __field(__u16, len ) 39 + __field(enum i2c_slave_event, event ) 40 + __array(__u8, buf, 1) ), 41 + 42 + TP_fast_assign( 43 + __entry->adapter_nr = client->adapter->nr; 44 + __entry->addr = client->addr; 45 + __entry->event = event; 46 + __entry->ret = cb_ret; 47 + switch (event) { 48 + case I2C_SLAVE_READ_REQUESTED: 49 + case I2C_SLAVE_READ_PROCESSED: 50 + case I2C_SLAVE_WRITE_RECEIVED: 51 + __entry->len = 1; 52 + memcpy(__entry->buf, val, __entry->len); 53 + break; 54 + default: 55 + __entry->len = 0; 56 + break; 57 + } 58 + ), 59 + TP_printk("i2c-%d a=%03x ret=%d %s [%*phD]", 60 + __entry->adapter_nr, __entry->addr, __entry->ret, 61 + show_event_type(__entry->event), __entry->len, __entry->buf 62 + )); 63 + 64 + #endif /* _TRACE_I2C_SLAVE_H */ 65 + 66 + /* This part must be outside protection */ 67 + #include <trace/define_trace.h>