aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_trace.h
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-11-04 06:45:59 -0500
committerTakashi Iwai <tiwai@suse.de>2014-11-04 08:09:14 -0500
commitf5914908a5b7b2338f210e56827a1ef35585dc6d (patch)
tree27349a1680e4d09f0ee3f604579c8146c3ad97b0 /sound/core/pcm_trace.h
parentd507941beb1ef98c19e2902007aee4faf36f854f (diff)
ALSA: pcm: Replace PCM hwptr tracking with tracepoints
ALSA PCM core has a mechanism tracking the PCM hwptr updates for analyzing XRUNs. But its log is limited (up to 10) and its log output is a kernel message, which is hard to handle. In this patch, the hwptr logging is moved to the tracing infrastructure instead of its own. Not only the hwptr updates but also XRUN and hwptr errors are recorded on the trace log, so that user can see such events at the exact timing. The new "snd_pcm" entry will appear in the tracing events: # ls -F /sys/kernel/debug/tracing/events/snd_pcm enable filter hw_ptr_error/ hwptr/ xrun/ The hwptr is for the regular hwptr update events. An event trace looks like: aplay-26187 [004] d..3 4012.834761: hwptr: pcmC0D0p/sub0: POS: pos=488, old=0, base=0, period=1024, buf=16384 "POS" shows the hwptr update by the explicit position update call and "IRQ" means the hwptr update by the interrupt, i.e. snd_pcm_period_elapsed() call. The "pos" is the passed ring-buffer offset by the caller, "old" is the previous hwptr, "base" is the hwptr base position, "period" and "buf" are period- and buffer-size of the target PCM substream. (Note that the hwptr position displayed here isn't the ring-buffer offset. It increments up to the PCM position boundary.) The XRUN event appears similarly, but without "pos" field. The hwptr error events appear with the PCM identifier and its reason string, such as "Lost interrupt?". The XRUN and hwptr error reports on kernel message are still left, can be turned on/off via xrun_debug proc like before. But the bit 3, 4, 5 and 6 bits of xrun_debug proc are dropped by this patch. Also, along with the change, the message strings have been reformatted to be a bit more consistent. Last but not least, the hwptr reporting is enabled only when CONFIG_SND_PCM_XRUN_DEBUG is set. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/pcm_trace.h')
-rw-r--r--sound/core/pcm_trace.h110
1 files changed, 110 insertions, 0 deletions
diff --git a/sound/core/pcm_trace.h b/sound/core/pcm_trace.h
new file mode 100644
index 000000000000..b63b654da5ff
--- /dev/null
+++ b/sound/core/pcm_trace.h
@@ -0,0 +1,110 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM snd_pcm
3#define TRACE_INCLUDE_FILE pcm_trace
4
5#if !defined(_PCM_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
6#define _PCM_TRACE_H
7
8#include <linux/tracepoint.h>
9
10TRACE_EVENT(hwptr,
11 TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_uframes_t pos, bool irq),
12 TP_ARGS(substream, pos, irq),
13 TP_STRUCT__entry(
14 __field( bool, in_interrupt )
15 __field( unsigned int, card )
16 __field( unsigned int, device )
17 __field( unsigned int, number )
18 __field( unsigned int, stream )
19 __field( snd_pcm_uframes_t, pos )
20 __field( snd_pcm_uframes_t, period_size )
21 __field( snd_pcm_uframes_t, buffer_size )
22 __field( snd_pcm_uframes_t, old_hw_ptr )
23 __field( snd_pcm_uframes_t, hw_ptr_base )
24 ),
25 TP_fast_assign(
26 __entry->in_interrupt = (irq);
27 __entry->card = (substream)->pcm->card->number;
28 __entry->device = (substream)->pcm->device;
29 __entry->number = (substream)->number;
30 __entry->stream = (substream)->stream;
31 __entry->pos = (pos);
32 __entry->period_size = (substream)->runtime->period_size;
33 __entry->buffer_size = (substream)->runtime->buffer_size;
34 __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr;
35 __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base;
36 ),
37 TP_printk("pcmC%dD%d%c/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu",
38 __entry->card, __entry->device,
39 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c',
40 __entry->number,
41 __entry->in_interrupt ? "IRQ" : "POS",
42 (unsigned long)__entry->pos,
43 (unsigned long)__entry->old_hw_ptr,
44 (unsigned long)__entry->hw_ptr_base,
45 (unsigned long)__entry->period_size,
46 (unsigned long)__entry->buffer_size)
47);
48
49TRACE_EVENT(xrun,
50 TP_PROTO(struct snd_pcm_substream *substream),
51 TP_ARGS(substream),
52 TP_STRUCT__entry(
53 __field( unsigned int, card )
54 __field( unsigned int, device )
55 __field( unsigned int, number )
56 __field( unsigned int, stream )
57 __field( snd_pcm_uframes_t, period_size )
58 __field( snd_pcm_uframes_t, buffer_size )
59 __field( snd_pcm_uframes_t, old_hw_ptr )
60 __field( snd_pcm_uframes_t, hw_ptr_base )
61 ),
62 TP_fast_assign(
63 __entry->card = (substream)->pcm->card->number;
64 __entry->device = (substream)->pcm->device;
65 __entry->number = (substream)->number;
66 __entry->stream = (substream)->stream;
67 __entry->period_size = (substream)->runtime->period_size;
68 __entry->buffer_size = (substream)->runtime->buffer_size;
69 __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr;
70 __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base;
71 ),
72 TP_printk("pcmC%dD%d%c/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu",
73 __entry->card, __entry->device,
74 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c',
75 __entry->number,
76 (unsigned long)__entry->old_hw_ptr,
77 (unsigned long)__entry->hw_ptr_base,
78 (unsigned long)__entry->period_size,
79 (unsigned long)__entry->buffer_size)
80);
81
82TRACE_EVENT(hw_ptr_error,
83 TP_PROTO(struct snd_pcm_substream *substream, const char *why),
84 TP_ARGS(substream, why),
85 TP_STRUCT__entry(
86 __field( unsigned int, card )
87 __field( unsigned int, device )
88 __field( unsigned int, number )
89 __field( unsigned int, stream )
90 __field( const char *, reason )
91 ),
92 TP_fast_assign(
93 __entry->card = (substream)->pcm->card->number;
94 __entry->device = (substream)->pcm->device;
95 __entry->number = (substream)->number;
96 __entry->stream = (substream)->stream;
97 __entry->reason = (why);
98 ),
99 TP_printk("pcmC%dD%d%c/sub%d: ERROR: %s",
100 __entry->card, __entry->device,
101 __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c',
102 __entry->number, __entry->reason)
103);
104
105#endif /* _PCM_TRACE_H */
106
107/* This part must be outside protection */
108#undef TRACE_INCLUDE_PATH
109#define TRACE_INCLUDE_PATH .
110#include <trace/define_trace.h>