[alsa-devel] [Resend] Add the stream report feature. Could you review my idea?
Takashi Sakamoto
o-takashi at sakamocchi.jp
Thu May 15 05:37:21 CEST 2014
Hi JongHo,
I can understand your needs but I have a question for your idea.
Most of snd_printd() output in your patch are fixed value in each
substream and it's retrieved from user-land via nodes in procfs or via
library APIs. I think it OK to retrieve them immediately when the error
message is generated.
So I think it enough to retrieve these items for every time:
+ snd_printd("avail: %ld\n", snd_pcm_playback_avail(runtime));
+ else
+ snd_printd("avail: %ld\n", snd_pcm_capture_avail(runtime));
+ snd_printd("avail_max: %ld\n", runtime->avail_max);
+ snd_printd("hw_ptr: %ld\n", runtime->status->hw_ptr);
+ snd_printd("appl_ptr: %ld\n", runtime->control->appl_ptr);
The similar information can be got via hw_ptr_error() in
sound/core/pcm_lib.c. You can enable the output when enabling
CONFIG_SND_PCM_XRUN_DEBUG and writing appropriate value to
/proc/asound/card%d/pcm%d{c,p}/xrun_debug. See:
http://git.kernel.org/cgit/linux/kernel/git/tiwai/sound.git/tree/sound/core/pcm_lib.c#n145
I think there is already an alternative so I disagree with your idea.
Regards
Takashi (not a maintainer) Sakamoto
o-takashi at sakamocchi.jp
(2014年05月15日 01:59), JongHo Kim wrote:
> (Add the alsa-devel at alsa-project.org)
>
> Hi
>
> I am work on ASoC part and developing the smartphone(Android).
> we have been doing the stress and long runtime test.
> audio output is no problem but I sometimes face
> the "playback write error(DMA or IRQ trouble?)" error message.
> I know the meaning of the message and I can solve the error.
> the problem may be caused by AP(clk) or I2S or DMA or Codec.
>
> I would like to trace the hardware error at the printed message.
>
> Could you review my idea?
>
> Thanks
> ---
> include/sound/pcm.h | 2 ++
> include/sound/soc-dai.h | 2 ++
> include/sound/soc.h | 1 +
> sound/core/pcm_lib.c | 3 +++
> sound/core/pcm_native.c | 51
> +++++++++++++++++++++++++++++++++++++++++++++++++
> sound/soc/soc-pcm.c | 26 +++++++++++++++++++++++++
> 6 files changed, 85 insertions(+)
>
> diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> index b4d6697..cd3093a 100644
> --- a/include/sound/pcm.h
> +++ b/include/sound/pcm.h
> @@ -82,6 +82,7 @@ struct snd_pcm_ops {
> unsigned long offset);
> int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct
> *vma);
> int (*ack)(struct snd_pcm_substream *substream);
> + void (*report)(struct snd_pcm_substream *substream);
> };
>
> /*
> @@ -502,6 +503,7 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
> int snd_pcm_start(struct snd_pcm_substream *substream);
> int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t
> status);
> int snd_pcm_drain_done(struct snd_pcm_substream *substream);
> +void snd_pcm_report(struct snd_pcm_substream *substream);
> #ifdef CONFIG_PM
> int snd_pcm_suspend(struct snd_pcm_substream *substream);
> int snd_pcm_suspend_all(struct snd_pcm *pcm);
> diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
> index fad7676..c032393 100644
> --- a/include/sound/soc-dai.h
> +++ b/include/sound/soc-dai.h
> @@ -184,6 +184,8 @@ struct snd_soc_dai_ops {
> struct snd_soc_dai *);
> int (*bespoke_trigger)(struct snd_pcm_substream *, int,
> struct snd_soc_dai *);
> + void (*report)(struct snd_pcm_substream *,
> + struct snd_soc_dai *);
> /*
> * For hardware based FIFO caused delay reporting.
> * Optional.
> diff --git a/include/sound/soc.h b/include/sound/soc.h
> index 0b83168..7685839 100644
> --- a/include/sound/soc.h
> +++ b/include/sound/soc.h
> @@ -641,6 +641,7 @@ struct snd_soc_ops {
> int (*hw_free)(struct snd_pcm_substream *);
> int (*prepare)(struct snd_pcm_substream *);
> int (*trigger)(struct snd_pcm_substream *, int);
> + void (*report)(struct snd_pcm_substream *);
> };
>
> struct snd_soc_compr_ops {
> diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
> index ce83def..0d6c9a3 100644
> --- a/sound/core/pcm_lib.c
> +++ b/sound/core/pcm_lib.c
> @@ -1944,6 +1944,9 @@ static int wait_for_avail(struct snd_pcm_substream
> *substream,
> "%s write error (DMA or IRQ trouble?)\n",
> is_playback ? "playback" : "capture");
> err = -EIO;
> + snd_pcm_stream_unlock_irq(substream);
> + snd_pcm_report(substream);
> + snd_pcm_stream_lock_irq(substream);
> break;
> }
> }
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index b653ab0..0ccdc10 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -978,6 +978,57 @@ int snd_pcm_drain_done(struct snd_pcm_substream
> *substream)
> SNDRV_PCM_STATE_SETUP);
> }
>
> +void snd_pcm_report(struct snd_pcm_substream *substream)
> +{
> + struct snd_pcm_runtime *runtime = substream->runtime;
> +
> + if (!runtime) {
> + snd_printd("runtime disappear\n");
> + return;
> + }
> +
> + mutex_lock(&substream->pcm->open_mutex);
> + snd_printd("access: %i\n", runtime->access);
> + snd_printd("format: %i\n", runtime->format);
> + snd_printd("subformat: %d\n", runtime->subformat);
> + snd_printd("channels: %u\n", runtime->channels);
> + snd_printd("rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num,
> + runtime->rate_den);
> + snd_printd("period_size: %lu\n", runtime->period_size);
> + snd_printd("buffer_size: %lu\n", runtime->buffer_size);
> + snd_printd("tstamp_mode: %i\n", runtime->tstamp_mode);
> + snd_printd("period_step: %u\n", runtime->period_step);
> + snd_printd("avail_min: %lu\n", runtime->control->avail_min);
> + snd_printd("start_threshold: %lu\n", runtime->start_threshold);
> + snd_printd("stop_threshold: %lu\n", runtime->stop_threshold);
> + snd_printd("silence_threshold: %lu\n", runtime->silence_threshold);
> + snd_printd("silence_size: %lu\n", runtime->silence_size);
> + snd_printd("boundary: %lu\n", runtime->boundary);
> + snd_printd("state: %i\n", runtime->status->state);
> + snd_printd("owner_pid: %d\n", pid_vnr(substream->pid));
> + snd_printd("trigger_time: %ld.%09ld\n",
> + runtime->trigger_tstamp.tv_sec,
> + runtime->trigger_tstamp.tv_nsec);
> + snd_printd("tstamp: %ld.%09ld\n",
> + runtime->status->tstamp.tv_sec,
> + runtime->status->tstamp.tv_nsec);
> + snd_printd("delay: %ld\n", runtime->delay);
> + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
> + snd_printd("avail: %ld\n", snd_pcm_playback_avail(runtime));
> + else
> + snd_printd("avail: %ld\n", snd_pcm_capture_avail(runtime));
> + snd_printd("avail_max: %ld\n", runtime->avail_max);
> + snd_printd("hw_ptr: %ld\n", runtime->status->hw_ptr);
> + snd_printd("appl_ptr: %ld\n", runtime->control->appl_ptr);
> +
> + mutex_unlock(&substream->pcm->open_mutex);
> +
> + if (substream->ops->report)
> + substream->ops->report(substream);
> +
> + return;
> +}
> +
> /*
> * pause callbacks
> */
> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
> index 2cedf09..98a47b3 100644
> --- a/sound/soc/soc-pcm.c
> +++ b/sound/soc/soc-pcm.c
> @@ -883,6 +883,30 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct
> snd_pcm_substream *substream)
> return offset;
> }
>
> +static void soc_pcm_report(struct snd_pcm_substream *substream)
> +{
> + struct snd_soc_pcm_runtime *rtd = substream->private_data;
> + struct snd_soc_platform *platform = rtd->platform;
> + struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
> + struct snd_soc_dai *codec_dai = rtd->codec_dai;
> +
> + mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
> + /* report the audio subsystem */
> + if (rtd->dai_link->ops && rtd->dai_link->ops->report)
> + rtd->dai_link->ops->report(substream);
> +
> + if (cpu_dai->driver->ops->report)
> + cpu_dai->driver->ops->report(substream, cpu_dai);
> +
> + if (platform->driver->ops && platform->driver->ops->report)
> + platform->driver->ops->report(substream);
> +
> + if (codec_dai->driver->ops->report)
> + codec_dai->driver->ops->report(substream, codec_dai);
> +
> + mutex_unlock(&rtd->pcm_mutex);
> +}
> +
> /* connect a FE and BE */
> static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
> struct snd_soc_pcm_runtime *be, int stream)
> @@ -2267,6 +2291,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int
> num)
> rtd->ops.close = dpcm_fe_dai_close;
> rtd->ops.pointer = soc_pcm_pointer;
> rtd->ops.ioctl = soc_pcm_ioctl;
> + rtd->ops.report = soc_pcm_report;
> } else {
> rtd->ops.open = soc_pcm_open;
> rtd->ops.hw_params = soc_pcm_hw_params;
> @@ -2276,6 +2301,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int
> num)
> rtd->ops.close = soc_pcm_close;
> rtd->ops.pointer = soc_pcm_pointer;
> rtd->ops.ioctl = soc_pcm_ioctl;
> + rtd->ops.report = soc_pcm_report;
> }
>
> if (platform->driver->ops) {
More information about the Alsa-devel
mailing list