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

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 <dhowells@redhat.com>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

authored by

David Howells and committed by
Wolfram Sang
8a325997 d9a83d62

+243 -4
+20 -3
drivers/i2c/i2c-core.c
··· 2565 2565 int try; 2566 2566 s32 res; 2567 2567 2568 + /* If enabled, the following two tracepoints are conditional on 2569 + * read_write and protocol. 2570 + */ 2571 + trace_smbus_write(adapter, addr, flags, read_write, 2572 + command, protocol, data); 2573 + trace_smbus_read(adapter, addr, flags, read_write, 2574 + command, protocol); 2575 + 2568 2576 flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB; 2569 2577 2570 2578 if (adapter->algo->smbus_xfer) { ··· 2593 2585 i2c_unlock_adapter(adapter); 2594 2586 2595 2587 if (res != -EOPNOTSUPP || !adapter->algo->master_xfer) 2596 - return res; 2588 + goto trace; 2597 2589 /* 2598 2590 * Fall back to i2c_smbus_xfer_emulated if the adapter doesn't 2599 2591 * implement native support for the SMBus operation. 2600 2592 */ 2601 2593 } 2602 2594 2603 - return i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, 2604 - command, protocol, data); 2595 + res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, 2596 + command, protocol, data); 2597 + 2598 + trace: 2599 + /* If enabled, the reply tracepoint is conditional on read_write. */ 2600 + trace_smbus_reply(adapter, addr, flags, read_write, 2601 + command, protocol, data); 2602 + trace_smbus_result(adapter, addr, flags, read_write, 2603 + command, protocol, res); 2604 + 2605 + return res; 2605 2606 } 2606 2607 EXPORT_SYMBOL(i2c_smbus_xfer); 2607 2608
+223 -1
include/trace/events/i2c.h
··· 1 - /* I2C message transfer tracepoints 1 + /* I2C and SMBUS message transfer tracepoints 2 2 * 3 3 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) ··· 143 143 ), 144 144 i2c_transfer_trace_reg, 145 145 i2c_transfer_trace_unreg); 146 + 147 + /* 148 + * i2c_smbus_xfer() write data or procedure call request 149 + */ 150 + TRACE_EVENT_CONDITION(smbus_write, 151 + TP_PROTO(const struct i2c_adapter *adap, 152 + u16 addr, unsigned short flags, 153 + char read_write, u8 command, int protocol, 154 + const union i2c_smbus_data *data), 155 + TP_ARGS(adap, addr, flags, read_write, command, protocol, data), 156 + TP_CONDITION(read_write == I2C_SMBUS_WRITE || 157 + protocol == I2C_SMBUS_PROC_CALL || 158 + protocol == I2C_SMBUS_BLOCK_PROC_CALL), 159 + TP_STRUCT__entry( 160 + __field(int, adapter_nr ) 161 + __field(__u16, addr ) 162 + __field(__u16, flags ) 163 + __field(__u8, command ) 164 + __field(__u8, len ) 165 + __field(__u32, protocol ) 166 + __array(__u8, buf, I2C_SMBUS_BLOCK_MAX + 2) ), 167 + TP_fast_assign( 168 + __entry->adapter_nr = adap->nr; 169 + __entry->addr = addr; 170 + __entry->flags = flags; 171 + __entry->command = command; 172 + __entry->protocol = protocol; 173 + 174 + switch (protocol) { 175 + case I2C_SMBUS_BYTE_DATA: 176 + __entry->len = 1; 177 + goto copy; 178 + case I2C_SMBUS_WORD_DATA: 179 + case I2C_SMBUS_PROC_CALL: 180 + __entry->len = 2; 181 + goto copy; 182 + case I2C_SMBUS_BLOCK_DATA: 183 + case I2C_SMBUS_BLOCK_PROC_CALL: 184 + case I2C_SMBUS_I2C_BLOCK_DATA: 185 + __entry->len = data->block[0] + 1; 186 + copy: 187 + memcpy(__entry->buf, data->block, __entry->len); 188 + break; 189 + case I2C_SMBUS_QUICK: 190 + case I2C_SMBUS_BYTE: 191 + case I2C_SMBUS_I2C_BLOCK_BROKEN: 192 + default: 193 + __entry->len = 0; 194 + } 195 + ), 196 + TP_printk("i2c-%d a=%03x f=%04x c=%x %s l=%u [%*phD]", 197 + __entry->adapter_nr, 198 + __entry->addr, 199 + __entry->flags, 200 + __entry->command, 201 + __print_symbolic(__entry->protocol, 202 + { I2C_SMBUS_QUICK, "QUICK" }, 203 + { I2C_SMBUS_BYTE, "BYTE" }, 204 + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, 205 + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, 206 + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, 207 + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, 208 + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, 209 + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, 210 + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }), 211 + __entry->len, 212 + __entry->len, __entry->buf 213 + )); 214 + 215 + /* 216 + * i2c_smbus_xfer() read data request 217 + */ 218 + TRACE_EVENT_CONDITION(smbus_read, 219 + TP_PROTO(const struct i2c_adapter *adap, 220 + u16 addr, unsigned short flags, 221 + char read_write, u8 command, int protocol), 222 + TP_ARGS(adap, addr, flags, read_write, command, protocol), 223 + TP_CONDITION(!(read_write == I2C_SMBUS_WRITE || 224 + protocol == I2C_SMBUS_PROC_CALL || 225 + protocol == I2C_SMBUS_BLOCK_PROC_CALL)), 226 + TP_STRUCT__entry( 227 + __field(int, adapter_nr ) 228 + __field(__u16, flags ) 229 + __field(__u16, addr ) 230 + __field(__u8, command ) 231 + __field(__u32, protocol ) 232 + __array(__u8, buf, I2C_SMBUS_BLOCK_MAX + 2) ), 233 + TP_fast_assign( 234 + __entry->adapter_nr = adap->nr; 235 + __entry->addr = addr; 236 + __entry->flags = flags; 237 + __entry->command = command; 238 + __entry->protocol = protocol; 239 + ), 240 + TP_printk("i2c-%d a=%03x f=%04x c=%x %s", 241 + __entry->adapter_nr, 242 + __entry->addr, 243 + __entry->flags, 244 + __entry->command, 245 + __print_symbolic(__entry->protocol, 246 + { I2C_SMBUS_QUICK, "QUICK" }, 247 + { I2C_SMBUS_BYTE, "BYTE" }, 248 + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, 249 + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, 250 + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, 251 + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, 252 + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, 253 + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, 254 + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }) 255 + )); 256 + 257 + /* 258 + * i2c_smbus_xfer() read data or procedure call reply 259 + */ 260 + TRACE_EVENT_CONDITION(smbus_reply, 261 + TP_PROTO(const struct i2c_adapter *adap, 262 + u16 addr, unsigned short flags, 263 + char read_write, u8 command, int protocol, 264 + const union i2c_smbus_data *data), 265 + TP_ARGS(adap, addr, flags, read_write, command, protocol, data), 266 + TP_CONDITION(read_write == I2C_SMBUS_READ), 267 + TP_STRUCT__entry( 268 + __field(int, adapter_nr ) 269 + __field(__u16, addr ) 270 + __field(__u16, flags ) 271 + __field(__u8, command ) 272 + __field(__u8, len ) 273 + __field(__u32, protocol ) 274 + __array(__u8, buf, I2C_SMBUS_BLOCK_MAX + 2) ), 275 + TP_fast_assign( 276 + __entry->adapter_nr = adap->nr; 277 + __entry->addr = addr; 278 + __entry->flags = flags; 279 + __entry->command = command; 280 + __entry->protocol = protocol; 281 + 282 + switch (protocol) { 283 + case I2C_SMBUS_BYTE: 284 + case I2C_SMBUS_BYTE_DATA: 285 + __entry->len = 1; 286 + goto copy; 287 + case I2C_SMBUS_WORD_DATA: 288 + case I2C_SMBUS_PROC_CALL: 289 + __entry->len = 2; 290 + goto copy; 291 + case I2C_SMBUS_BLOCK_DATA: 292 + case I2C_SMBUS_BLOCK_PROC_CALL: 293 + case I2C_SMBUS_I2C_BLOCK_DATA: 294 + __entry->len = data->block[0] + 1; 295 + copy: 296 + memcpy(__entry->buf, data->block, __entry->len); 297 + break; 298 + case I2C_SMBUS_QUICK: 299 + case I2C_SMBUS_I2C_BLOCK_BROKEN: 300 + default: 301 + __entry->len = 0; 302 + } 303 + ), 304 + TP_printk("i2c-%d a=%03x f=%04x c=%x %s l=%u [%*phD]", 305 + __entry->adapter_nr, 306 + __entry->addr, 307 + __entry->flags, 308 + __entry->command, 309 + __print_symbolic(__entry->protocol, 310 + { I2C_SMBUS_QUICK, "QUICK" }, 311 + { I2C_SMBUS_BYTE, "BYTE" }, 312 + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, 313 + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, 314 + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, 315 + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, 316 + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, 317 + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, 318 + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }), 319 + __entry->len, 320 + __entry->len, __entry->buf 321 + )); 322 + 323 + /* 324 + * i2c_smbus_xfer() result 325 + */ 326 + TRACE_EVENT(smbus_result, 327 + TP_PROTO(const struct i2c_adapter *adap, 328 + u16 addr, unsigned short flags, 329 + char read_write, u8 command, int protocol, 330 + int res), 331 + TP_ARGS(adap, addr, flags, read_write, command, protocol, res), 332 + TP_STRUCT__entry( 333 + __field(int, adapter_nr ) 334 + __field(__u16, addr ) 335 + __field(__u16, flags ) 336 + __field(__u8, read_write ) 337 + __field(__u8, command ) 338 + __field(__s16, res ) 339 + __field(__u32, protocol ) 340 + ), 341 + TP_fast_assign( 342 + __entry->adapter_nr = adap->nr; 343 + __entry->addr = addr; 344 + __entry->flags = flags; 345 + __entry->read_write = read_write; 346 + __entry->command = command; 347 + __entry->protocol = protocol; 348 + __entry->res = res; 349 + ), 350 + TP_printk("i2c-%d a=%03x f=%04x c=%x %s %s res=%d", 351 + __entry->adapter_nr, 352 + __entry->addr, 353 + __entry->flags, 354 + __entry->command, 355 + __print_symbolic(__entry->protocol, 356 + { I2C_SMBUS_QUICK, "QUICK" }, 357 + { I2C_SMBUS_BYTE, "BYTE" }, 358 + { I2C_SMBUS_BYTE_DATA, "BYTE_DATA" }, 359 + { I2C_SMBUS_WORD_DATA, "WORD_DATA" }, 360 + { I2C_SMBUS_PROC_CALL, "PROC_CALL" }, 361 + { I2C_SMBUS_BLOCK_DATA, "BLOCK_DATA" }, 362 + { I2C_SMBUS_I2C_BLOCK_BROKEN, "I2C_BLOCK_BROKEN" }, 363 + { I2C_SMBUS_BLOCK_PROC_CALL, "BLOCK_PROC_CALL" }, 364 + { I2C_SMBUS_I2C_BLOCK_DATA, "I2C_BLOCK_DATA" }), 365 + __entry->read_write == I2C_SMBUS_WRITE ? "wr" : "rd", 366 + __entry->res 367 + )); 146 368 147 369 #endif /* _TRACE_I2C_H */ 148 370