@@ -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;
}
@@ -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 */