Here's a tentative patch on top of the previous one to split the messages. I haven't tested the I2C side yet and cannot test the SMBUS write. Each is split four ways: (1) i2c/smbus_write - Show write request before submitting (2) i2c/smbus_read - Show read request before submitting (3) i2c/smbus_reply - Show read reply after submitting (if no failure) (4) i2c/smbus_result - Show operation result So this might give you something like: ... i2c_write: i2c-5 #0 f=00 a=44 l=2 [0800] ... i2c_read: i2c-5 #1 f=01 a=44 l=1 ... i2c_reply: i2c-5 #1 f=01 a=44 l=1 [fe] ... i2c_result: n=2 ret=2 from a single __i2c_transfer() given an array of two messages. Or: ... smbus_read: i2c-0 a=51 f=00 c=fc BYTE_DATA ... smbus_reply: i2c-0 a=51 f=00 c=fc BYTE_DATA [41ff01000...] ... smbus_result: i2c-0 a=51 f=00 c=fc BYTE_DATA rd res=0 from a single i2c_smbus_xfer(). David --- commit 31d5367657a64453d48b89b09296f7ebc6a5ee94 Author: David Howells <dhowells@xxxxxxxxxx> Date: Fri Dec 13 17:13:19 2013 +0000 i2c: Split traces diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2128e106ca97..0dbf0dcff6ce 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1726,6 +1726,19 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) unsigned long orig_jiffies; int ret, try; + /* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets + * enabled. This is an efficient way of keeping the for-loop from + * being executed when not needed. + */ + if (static_key_false(&i2c_trace_msg)) { + int i; + for (i = 0; i < num; i++) + if (msgs[i].flags & I2C_M_RD) + trace_i2c_read(adap, &msgs[i], i); + else + trace_i2c_write(adap, &msgs[i], i); + } + /* Retry automatically on arbitration loss */ orig_jiffies = jiffies; for (ret = 0, try = 0; try <= adap->retries; try++) { @@ -1736,14 +1749,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) break; } - /* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets - * enabled. This is an efficient way of keeping the for-loop from - * being executed when not needed. - */ if (static_key_false(&i2c_trace_msg)) { int i; - for (i = 0; i < num; i++) - trace_i2c_transfer(adap, &msgs[i], ret); + for (i = 0; i < ret; i++) + if (msgs[i].flags & I2C_M_RD) + trace_i2c_reply(adap, &msgs[i], i); + trace_i2c_result(adap, i, ret); } return ret; @@ -2541,6 +2552,11 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, int try; s32 res; + if (read_write == I2C_SMBUS_WRITE) + trace_smbus_write(adapter, addr, flags, command, protocol, data); + else + trace_smbus_read(adapter, addr, flags, command, protocol); + flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB; if (adapter->algo->smbus_xfer) { @@ -2572,8 +2588,11 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, command, protocol, data); trace: - trace_smbus_transfer(adapter, addr, flags, read_write, - command, protocol, data, res); + if (read_write == I2C_SMBUS_READ) + trace_smbus_reply(adapter, addr, flags, + command, protocol, data); + trace_smbus_result(adapter, addr, flags, read_write, + command, protocol, res); return res; } diff --git a/include/trace/events/i2c.h b/include/trace/events/i2c.h index ed366e145c8d..ca19f4948290 100644 --- a/include/trace/events/i2c.h +++ b/include/trace/events/i2c.h @@ -23,42 +23,259 @@ extern void i2c_transfer_trace_reg(void); extern void i2c_transfer_trace_unreg(void); -TRACE_EVENT_FN(i2c_transfer, +/* + * __i2c_transfer() write request + */ +TRACE_EVENT_FN(i2c_write, TP_PROTO(const struct i2c_adapter *adap, const struct i2c_msg *msg, - int ret), - TP_ARGS(adap, msg, ret), + int num), + TP_ARGS(adap, msg, num), TP_STRUCT__entry( - __field( int, adapter_nr ) + __field(int, adapter_nr ) + __field(__u16, msg_nr ) __field(__u16, addr ) __field(__u16, flags ) __field(__u16, len ) - __field(__s16, ret ) __dynamic_array(__u8, buf, msg->len) ), TP_fast_assign( __entry->adapter_nr = adap->nr; + __entry->msg_nr = num; + __entry->addr = msg->addr; + __entry->flags = msg->flags; + __entry->len = msg->len; + memcpy(__get_dynamic_array(buf), msg->buf, msg->len); + ), + TP_printk("i2c-%d #%u f=%02x a=%02x l=%u [%*phN]", + __entry->adapter_nr, + __entry->msg_nr, + __entry->flags, + __entry->addr, + __entry->len, + __entry->len, __get_dynamic_array(buf) + ), + i2c_transfer_trace_reg, + i2c_transfer_trace_unreg); + +/* + * __i2c_transfer() read request + */ +TRACE_EVENT_FN(i2c_read, + TP_PROTO(const struct i2c_adapter *adap, const struct i2c_msg *msg, + int num), + TP_ARGS(adap, msg, num), + TP_STRUCT__entry( + __field(int, adapter_nr ) + __field(__u16, msg_nr ) + __field(__u16, addr ) + __field(__u16, flags ) + __field(__u16, len ) + ), + TP_fast_assign( + __entry->adapter_nr = adap->nr; + __entry->msg_nr = num; + __entry->addr = msg->addr; + __entry->flags = msg->flags; + __entry->len = msg->len; + ), + TP_printk("i2c-%d #%u f=%02x a=%02x l=%u", + __entry->adapter_nr, + __entry->msg_nr, + __entry->flags, + __entry->addr, + __entry->len + ), + i2c_transfer_trace_reg, + i2c_transfer_trace_unreg); + +/* + * __i2c_transfer() read reply + */ +TRACE_EVENT_FN(i2c_reply, + TP_PROTO(const struct i2c_adapter *adap, const struct i2c_msg *msg, + int num), + TP_ARGS(adap, msg, num), + TP_STRUCT__entry( + __field(int, adapter_nr ) + __field(__u16, msg_nr ) + __field(__u16, addr ) + __field(__u16, flags ) + __field(__u16, len ) + __dynamic_array(__u8, buf, msg->len) ), + TP_fast_assign( + __entry->adapter_nr = adap->nr; + __entry->msg_nr = num; __entry->addr = msg->addr; __entry->flags = msg->flags; __entry->len = msg->len; - __entry->ret = ret; memcpy(__get_dynamic_array(buf), msg->buf, msg->len); ), - TP_printk("i2c-%d f=%02x a=%02x l=%u ret=%d [%*phN]", + TP_printk("i2c-%d #%u f=%02x a=%02x l=%u [%*phN]", __entry->adapter_nr, + __entry->msg_nr, __entry->flags, __entry->addr, __entry->len, - __entry->ret, __entry->len, __get_dynamic_array(buf) ), i2c_transfer_trace_reg, i2c_transfer_trace_unreg); -TRACE_EVENT(smbus_transfer, +/* + * __i2c_transfer() result + */ +TRACE_EVENT_FN(i2c_result, + TP_PROTO(const struct i2c_adapter *adap, int num, int ret), + TP_ARGS(adap, num, ret), + TP_STRUCT__entry( + __field(int, adapter_nr ) + __field(__u16, nr_msgs ) + __field(__s16, ret ) + ), + TP_fast_assign( + __entry->adapter_nr = adap->nr; + __entry->nr_msgs = num; + __entry->ret = ret; + ), + TP_printk("i2c-%d n=%u ret=%d", + __entry->adapter_nr, + __entry->nr_msgs, + __entry->ret + ), + i2c_transfer_trace_reg, + i2c_transfer_trace_unreg); + +/* + * i2c_smbus_xfer() write request + */ +TRACE_EVENT(smbus_write, + TP_PROTO(const struct i2c_adapter *adap, + u16 addr, unsigned short flags, + u8 command, int protocol, + const union i2c_smbus_data *data), + TP_ARGS(adap, addr, flags, command, protocol, data), + TP_STRUCT__entry( + __field(int, adapter_nr ) + __field(__u16, addr ) + __field(__u16, flags ) + __field(__u8, command ) + __field(__u32, protocol ) + __array(__u8, buf, I2C_SMBUS_BLOCK_MAX + 2) ), + TP_fast_assign( + __entry->adapter_nr = adap->nr; + __entry->addr = addr; + __entry->flags = flags; + __entry->command = command; + __entry->protocol = protocol; + memcpy(__entry->buf, data->block, I2C_SMBUS_BLOCK_MAX + 2); + ), + TP_printk("i2c-%d a=%02x f=%02x c=%x %s [%*phN]", + __entry->adapter_nr, + __entry->addr, + __entry->flags, + __entry->command, + __print_symbolic(__entry->protocol, + { I2C_SMBUS_QUICK, "QUICK" }, + { I2C_SMBUS_BYTE, "BYTE" }, + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }), + I2C_SMBUS_BLOCK_MAX + 2, __entry->buf + )); + +/* + * i2c_smbus_xfer() read request + */ +TRACE_EVENT(smbus_read, + TP_PROTO(const struct i2c_adapter *adap, + u16 addr, unsigned short flags, + u8 command, int protocol), + TP_ARGS(adap, addr, flags, command, protocol), + TP_STRUCT__entry( + __field(int, adapter_nr ) + __field(__u16, addr ) + __field(__u16, flags ) + __field(__u8, command ) + __field(__u32, protocol ) + __array(__u8, buf, I2C_SMBUS_BLOCK_MAX + 2) ), + TP_fast_assign( + __entry->adapter_nr = adap->nr; + __entry->addr = addr; + __entry->flags = flags; + __entry->command = command; + __entry->protocol = protocol; + ), + TP_printk("i2c-%d a=%02x f=%02x c=%x %s", + __entry->adapter_nr, + __entry->addr, + __entry->flags, + __entry->command, + __print_symbolic(__entry->protocol, + { I2C_SMBUS_QUICK, "QUICK" }, + { I2C_SMBUS_BYTE, "BYTE" }, + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }) + )); + +/* + * i2c_smbus_xfer() read reply + */ +TRACE_EVENT(smbus_reply, + TP_PROTO(const struct i2c_adapter *adap, + u16 addr, unsigned short flags, + u8 command, int protocol, + const union i2c_smbus_data *data), + TP_ARGS(adap, addr, flags, command, protocol, data), + TP_STRUCT__entry( + __field(int, adapter_nr ) + __field(__u16, addr ) + __field(__u16, flags ) + __field(__u8, command ) + __field(__u32, protocol ) + __array(__u8, buf, I2C_SMBUS_BLOCK_MAX + 2) ), + TP_fast_assign( + __entry->adapter_nr = adap->nr; + __entry->addr = addr; + __entry->flags = flags; + __entry->command = command; + __entry->protocol = protocol; + memcpy(__entry->buf, data->block, I2C_SMBUS_BLOCK_MAX + 2); + ), + TP_printk("i2c-%d a=%02x f=%02x c=%x %s [%*phN]", + __entry->adapter_nr, + __entry->addr, + __entry->flags, + __entry->command, + __print_symbolic(__entry->protocol, + { I2C_SMBUS_QUICK, "QUICK" }, + { I2C_SMBUS_BYTE, "BYTE" }, + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }), + I2C_SMBUS_BLOCK_MAX + 2, __entry->buf + )); + +/* + * i2c_smbus_xfer() result + */ +TRACE_EVENT(smbus_result, TP_PROTO(const struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int protocol, - const union i2c_smbus_data *data, int res), - TP_ARGS(adap, addr, flags, read_write, command, protocol, data, res), + int res), + TP_ARGS(adap, addr, flags, read_write, command, protocol, res), TP_STRUCT__entry( __field(int, adapter_nr ) __field(__u16, addr ) @@ -67,7 +284,7 @@ TRACE_EVENT(smbus_transfer, __field(__u8, command ) __field(__s16, res ) __field(__u32, protocol ) - __array(__u8, buf, I2C_SMBUS_BLOCK_MAX + 2) ), + ), TP_fast_assign( __entry->adapter_nr = adap->nr; __entry->addr = addr; @@ -76,17 +293,24 @@ TRACE_EVENT(smbus_transfer, __entry->command = command; __entry->protocol = protocol; __entry->res = res; - memcpy(__entry->buf, data->block, I2C_SMBUS_BLOCK_MAX + 2); ), - TP_printk("i2c-%d f=%02x a=%02x r=%x c=%x p=%x res=%d [%*phN]", + TP_printk("i2c-%d a=%02x f=%02x c=%x %s %s res=%d", __entry->adapter_nr, - __entry->flags, __entry->addr, - __entry->read_write, + __entry->flags, __entry->command, - __entry->protocol, - __entry->res, - I2C_SMBUS_BLOCK_MAX + 2, __entry->buf + __print_symbolic(__entry->protocol, + { I2C_SMBUS_QUICK, "QUICK" }, + { I2C_SMBUS_BYTE, "BYTE" }, + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }), + __entry->read_write == I2C_SMBUS_WRITE ? "wr" : "rd", + __entry->res )); #endif /* _TRACE_I2C_H */ -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html