Skip to content

Commit 8a32599

Browse files
dhowellsWolfram Sang
authored and
Wolfram Sang
committed
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]>
1 parent d9a83d6 commit 8a32599

File tree

2 files changed

+243
-4
lines changed

2 files changed

+243
-4
lines changed

drivers/i2c/i2c-core.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,6 +2565,14 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
25652565
int try;
25662566
s32 res;
25672567

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+
25682576
flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
25692577

25702578
if (adapter->algo->smbus_xfer) {
@@ -2585,15 +2593,24 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
25852593
i2c_unlock_adapter(adapter);
25862594

25872595
if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
2588-
return res;
2596+
goto trace;
25892597
/*
25902598
* Fall back to i2c_smbus_xfer_emulated if the adapter doesn't
25912599
* implement native support for the SMBus operation.
25922600
*/
25932601
}
25942602

2595-
return i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
2596-
command, protocol, data);
2603+
res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
2604+
command, protocol, data);
2605+
2606+
trace:
2607+
/* If enabled, the reply tracepoint is conditional on read_write. */
2608+
trace_smbus_reply(adapter, addr, flags, read_write,
2609+
command, protocol, data);
2610+
trace_smbus_result(adapter, addr, flags, read_write,
2611+
command, protocol, res);
2612+
2613+
return res;
25972614
}
25982615
EXPORT_SYMBOL(i2c_smbus_xfer);
25992616

include/trace/events/i2c.h

Lines changed: 223 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* I2C message transfer tracepoints
1+
/* I2C and SMBUS message transfer tracepoints
22
*
33
* Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
44
* Written by David Howells ([email protected])
@@ -144,6 +144,228 @@ TRACE_EVENT_FN(i2c_result,
144144
i2c_transfer_trace_reg,
145145
i2c_transfer_trace_unreg);
146146

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+
));
368+
147369
#endif /* _TRACE_I2C_H */
148370

149371
/* This part must be outside protection */

0 commit comments

Comments
 (0)