-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
i2c: Add message transfer tracepoints for SMBUS [ver #2]
The SMBUS tracepoints can be enabled thusly: echo 1 >/sys/kernel/debug/tracing/events/i2c/enable and will dump messages that can be viewed in /sys/kernel/debug/tracing/trace that look like: ... smbus_read: i2c-0 a=051 f=0000 c=fa BYTE_DATA ... smbus_reply: i2c-0 a=051 f=0000 c=fa BYTE_DATA l=1 [39] ... smbus_result: i2c-0 a=051 f=0000 c=fa BYTE_DATA rd res=0 formatted as: i2c-<adapter-nr> a=<addr> f=<flags> c=<command> <protocol-name> <rd|wr> res=<result> l=<data-len> [<data-block>] The adapters to be traced can be selected by something like: echo adapter_nr==1 >/sys/kernel/debug/tracing/events/i2c/filter Note that this shares the same filter and enablement as i2c. Signed-off-by: David Howells <[email protected]> Reviewed-by: Steven Rostedt <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
- Loading branch information
Showing
2 changed files
with
243 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* I2C message transfer tracepoints | ||
/* I2C and SMBUS message transfer tracepoints | ||
* | ||
* Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. | ||
* Written by David Howells ([email protected]) | ||
|
@@ -144,6 +144,228 @@ TRACE_EVENT_FN(i2c_result, | |
i2c_transfer_trace_reg, | ||
i2c_transfer_trace_unreg); | ||
|
||
/* | ||
* i2c_smbus_xfer() write data or procedure call request | ||
*/ | ||
TRACE_EVENT_CONDITION(smbus_write, | ||
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), | ||
TP_ARGS(adap, addr, flags, read_write, command, protocol, data), | ||
TP_CONDITION(read_write == I2C_SMBUS_WRITE || | ||
protocol == I2C_SMBUS_PROC_CALL || | ||
protocol == I2C_SMBUS_BLOCK_PROC_CALL), | ||
TP_STRUCT__entry( | ||
__field(int, adapter_nr ) | ||
__field(__u16, addr ) | ||
__field(__u16, flags ) | ||
__field(__u8, command ) | ||
__field(__u8, len ) | ||
__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; | ||
|
||
switch (protocol) { | ||
case I2C_SMBUS_BYTE_DATA: | ||
__entry->len = 1; | ||
goto copy; | ||
case I2C_SMBUS_WORD_DATA: | ||
case I2C_SMBUS_PROC_CALL: | ||
__entry->len = 2; | ||
goto copy; | ||
case I2C_SMBUS_BLOCK_DATA: | ||
case I2C_SMBUS_BLOCK_PROC_CALL: | ||
case I2C_SMBUS_I2C_BLOCK_DATA: | ||
__entry->len = data->block[0] + 1; | ||
copy: | ||
memcpy(__entry->buf, data->block, __entry->len); | ||
break; | ||
case I2C_SMBUS_QUICK: | ||
case I2C_SMBUS_BYTE: | ||
case I2C_SMBUS_I2C_BLOCK_BROKEN: | ||
default: | ||
__entry->len = 0; | ||
} | ||
), | ||
TP_printk("i2c-%d a=%03x f=%04x c=%x %s l=%u [%*phD]", | ||
__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" }), | ||
__entry->len, | ||
__entry->len, __entry->buf | ||
)); | ||
|
||
/* | ||
* i2c_smbus_xfer() read data request | ||
*/ | ||
TRACE_EVENT_CONDITION(smbus_read, | ||
TP_PROTO(const struct i2c_adapter *adap, | ||
u16 addr, unsigned short flags, | ||
char read_write, u8 command, int protocol), | ||
TP_ARGS(adap, addr, flags, read_write, command, protocol), | ||
TP_CONDITION(!(read_write == I2C_SMBUS_WRITE || | ||
protocol == I2C_SMBUS_PROC_CALL || | ||
protocol == I2C_SMBUS_BLOCK_PROC_CALL)), | ||
TP_STRUCT__entry( | ||
__field(int, adapter_nr ) | ||
__field(__u16, flags ) | ||
__field(__u16, addr ) | ||
__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=%03x f=%04x 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 data or procedure call reply | ||
*/ | ||
TRACE_EVENT_CONDITION(smbus_reply, | ||
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), | ||
TP_ARGS(adap, addr, flags, read_write, command, protocol, data), | ||
TP_CONDITION(read_write == I2C_SMBUS_READ), | ||
TP_STRUCT__entry( | ||
__field(int, adapter_nr ) | ||
__field(__u16, addr ) | ||
__field(__u16, flags ) | ||
__field(__u8, command ) | ||
__field(__u8, len ) | ||
__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; | ||
|
||
switch (protocol) { | ||
case I2C_SMBUS_BYTE: | ||
case I2C_SMBUS_BYTE_DATA: | ||
__entry->len = 1; | ||
goto copy; | ||
case I2C_SMBUS_WORD_DATA: | ||
case I2C_SMBUS_PROC_CALL: | ||
__entry->len = 2; | ||
goto copy; | ||
case I2C_SMBUS_BLOCK_DATA: | ||
case I2C_SMBUS_BLOCK_PROC_CALL: | ||
case I2C_SMBUS_I2C_BLOCK_DATA: | ||
__entry->len = data->block[0] + 1; | ||
copy: | ||
memcpy(__entry->buf, data->block, __entry->len); | ||
break; | ||
case I2C_SMBUS_QUICK: | ||
case I2C_SMBUS_I2C_BLOCK_BROKEN: | ||
default: | ||
__entry->len = 0; | ||
} | ||
), | ||
TP_printk("i2c-%d a=%03x f=%04x c=%x %s l=%u [%*phD]", | ||
__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" }), | ||
__entry->len, | ||
__entry->len, __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, | ||
int res), | ||
TP_ARGS(adap, addr, flags, read_write, command, protocol, res), | ||
TP_STRUCT__entry( | ||
__field(int, adapter_nr ) | ||
__field(__u16, addr ) | ||
__field(__u16, flags ) | ||
__field(__u8, read_write ) | ||
__field(__u8, command ) | ||
__field(__s16, res ) | ||
__field(__u32, protocol ) | ||
), | ||
TP_fast_assign( | ||
__entry->adapter_nr = adap->nr; | ||
__entry->addr = addr; | ||
__entry->flags = flags; | ||
__entry->read_write = read_write; | ||
__entry->command = command; | ||
__entry->protocol = protocol; | ||
__entry->res = res; | ||
), | ||
TP_printk("i2c-%d a=%03x f=%04x c=%x %s %s res=%d", | ||
__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" }), | ||
__entry->read_write == I2C_SMBUS_WRITE ? "wr" : "rd", | ||
__entry->res | ||
)); | ||
|
||
#endif /* _TRACE_I2C_H */ | ||
|
||
/* This part must be outside protection */ | ||
|