[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