[alsa-devel] Question about sound device release timing
Kuninori Morimoto
kuninori.morimoto.gx at renesas.com
Fri Aug 25 07:31:04 CEST 2017
Hi Takashi-san, Mark
I noticed snd_soc_dapm_stream_event() is called strange timing
if I unbind sound device during playing
> aplay xxx.wav &
> echo xxxx > /sys/bus/platform/drivers/xxx/unbind
...
> Unable to handle kernel paging request at virtual address dead000000000220
> Mem abort info:
(snip)
> PC is at soc_dapm_dai_stream_event.isra.14+0x20/0xd0
> LR is at snd_soc_dapm_stream_event+0x74/0xa8
(snip)
> [<ffff000008715610>] soc_dapm_dai_stream_event.isra.14+0x20/0xd0
> [<ffff00000871989c>] snd_soc_dapm_stream_event+0x74/0xa8
> [<ffff00000871b23c>] close_delayed_work+0x3c/0x50
> [<ffff0000080bbd6c>] process_one_work+0x1ac/0x318
> [<ffff0000080bbf20>] worker_thread+0x48/0x420
> [<ffff0000080c201c>] kthread+0xfc/0x128
> [<ffff0000080842f0>] ret_from_fork+0x10/0x18
> Code: b40005c9 a9bf7bfd 91048120 910003fd (f9409121)
> ---[ end trace 6739a0ea1013e0b2 ]---
This snd_soc_dapm_stream_event() was called from close_delayed_work()
and it was set on soc_pcm_close()
static int soc_pcm_close(struct snd_pcm_substream *substream)
{
...
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
...
} else {
/* start delayed pop wq here for playback streams */
rtd->pop_wait = 1;
=> queue_delayed_work(system_power_efficient_wq,
&rtd->delayed_work,
msecs_to_jiffies(rtd->pmdown_time));
}
...
}
But, this soc_pcm_close() is called *after* flush_delayed_work() of
soc_cleanup_card_resources().
It seems this close function seems called from snd_card_free()
and this rtd will be freed on soc_remove_pcm_runtimes().
static int soc_cleanup_card_resources(struct snd_soc_card *card)
{
...
/* make sure any delayed work runs */
list_for_each_entry(rtd, &card->rtd_list, list) {
=> flush_delayed_work(&rtd->delayed_work);
}
/* free the ALSA card at first; this syncs with pending operations */
=> snd_card_free(card->snd_card);
...
=> soc_remove_pcm_runtimes(card);
...
}
Because of this, delayed called close_delayed_work() will call
soc_dapm_dai_stream_event() and it access to already freed rtd,
and kernel will die.
I don't know why, but it seems this close is wokring on other thread (?),
but I'm not sure.
Q1. does this close function run on other thread ?
Q2. I can avoid this delayed close by setting rtd->pmdown_time = 0;
before snd_card_free(). but is this correct approach ?
I can avoid this delayed calling close_delayed_work() by local patch,
but then, re-bind doesn't work correctly.
/*
* custom kernel for avoiding close_delayed_work()
*/
> aplay xxx.wav &
> echo xxxx > /sys/bus/platform/drivers/rcar_sound/unbind
/* unbind codec and card drivers here */
>
/*
* try re-bind
*/
/* re-bind codec and card drivers here */
> echo xxxx > /sys/bus/platform/drivers/rcar_sound/bind
rcar_sound ec500000.sound: probed
asoc-simple-card sound: ak4613-hifi <-> ec500000.sound mapping ok
>
> aplay xxx.wav
Playing WAVE '/home/Calm_16bit_48k.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
ALSA lib pcm_params.c:2162:(snd1_pcm_hw_refine_slave) Slave PCM not usable
aplay: set_params:1204: Broken configuration for this PCM: no configurations available
Do you know why or have hint to solve these issue ?
Best regards
---
Kuninori Morimoto
More information about the Alsa-devel
mailing list