Message ID | 875zgfcey5.wl-kuninori.morimoto.gx@renesas.com (mailing list archive) |
---|---|
State | Accepted |
Commit | b56be800f1292c9b79c4f66571c701551bdf9e12 |
Headers | show |
Series | ASoC: soc-pcm cleanup step2 | expand |
On 2/10/2020 4:14 AM, Kuninori Morimoto wrote: > > From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> > > Current soc_pcm_open() calls snd_soc_dai_startup() under loop. > Thus, it needs to care about started/not-yet-started codec DAI. > > But, if soc-dai.c is handling it, soc-pcm.c don't need to care > about it. > This patch adds started flag to soc-dai.h, and simplify soc-pcm.c. > This is one of prepare for cleanup soc-pcm-open() > > Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> > --- (...) > static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, > diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c > index 51031e33..73a8293 100644 > --- a/sound/soc/soc-dai.c > +++ b/sound/soc/soc-dai.c > @@ -295,17 +295,24 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, > { > int ret = 0; > > - if (dai->driver->ops->startup) > + if (!dai->started && > + dai->driver->ops->startup) > ret = dai->driver->ops->startup(substream, dai); > > + if (ret == 0) > + dai->started = 1; > + > return ret; > } Hi, the above change breaks simultaneous playback and capture on single DAI in more complicated use cases. With above change when one runs playback first, startup callback is skipped when running capture while playback is still running. With snd_soc_skl it leads to null pointer dereference, because we didn't initialize streams properly: [ 78.901574] dpcm_be_dai_hw_params:2219: Analog Playback and Capture: ASoC: hw_params BE Analog Playback and Capture [ 78.901582] dapm_update_dai_unlocked:2638: snd_hda_codec_realtek ehdaudio0D0: Update DAI routes for Analog Codec DAI capture [ 78.901585] dapm_update_dai_chan:2612: snd_hda_codec_realtek ehdaudio0D0: Connecting DAI route AIF3TX -> Analog Codec Capture [ 78.901590] dapm_update_dai_chan:2612: snd_hda_codec_realtek ehdaudio0D0: Connecting DAI route AIF1TX -> Analog Codec Capture [ 78.901608] dapm_update_dai_unlocked:2638: snd_soc_skl 0000:00:1f.3: Update DAI routes for Analog CPU DAI capture [ 78.901612] dapm_update_dai_chan:2612: snd_soc_skl 0000:00:1f.3: Connecting DAI route Analog CPU Capture -> codec0_in [ 78.901615] dpcm_fe_dai_hw_params:2277: Analog HDA DSP: ASoC: hw_params FE Analog HDA DSP rate 48000 chan 2 fmt 2 [ 78.901622] skl_pcm_hw_params:307: snd_soc_skl 0000:00:1f.3: skl_pcm_hw_params: hda-dsp-analog-dai [ 78.901624] ================================================================== [ 78.907515] BUG: KASAN: null-ptr-deref in skl_pcm_hw_params+0x102/0x3d0 [snd_soc_skl] [ 78.914003] Write of size 4 at addr 0000000000000044 by task arecord/2119 Amadeusz
>> static inline void *snd_soc_dai_get_dma_data(const struct >> snd_soc_dai *dai, >> diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c >> index 51031e33..73a8293 100644 >> --- a/sound/soc/soc-dai.c >> +++ b/sound/soc/soc-dai.c >> @@ -295,17 +295,24 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, >> { >> int ret = 0; >> - if (dai->driver->ops->startup) >> + if (!dai->started && >> + dai->driver->ops->startup) >> ret = dai->driver->ops->startup(substream, dai); >> + if (ret == 0) >> + dai->started = 1; >> + >> return ret; >> } > > Hi, > > the above change breaks simultaneous playback and capture on single DAI > in more complicated use cases. With above change when one runs playback > first, startup callback is skipped when running capture while playback > is still running. Should the 'started' bitfield should be an array for capture and playback cases respectively? e.g. diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 78bac995db15..d4825b82c7a3 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -351,7 +351,7 @@ struct snd_soc_dai { /* bit field */ unsigned int probed:1; - unsigned int started:1; + unsigned int started[SNDRV_PCM_STREAM_LAST + 1]; }; static inline struct snd_soc_pcm_stream * diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 19142f6e533c..8f3cad8db89a 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -295,12 +295,12 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, { int ret = 0; - if (!dai->started && + if (!dai->started[substream->stream] && dai->driver->ops->startup) ret = dai->driver->ops->startup(substream, dai); if (ret == 0) - dai->started = 1; + dai->started[substream->stream] = 1; return ret; } @@ -308,11 +308,11 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { - if (dai->started && + if (dai->started[substream->stream] && dai->driver->ops->shutdown) dai->driver->ops->shutdown(substream, dai); - dai->started = 0; + dai->started[substream->stream] = 0; } int snd_soc_dai_prepare(struct snd_soc_dai *dai,
Hi Amadeusz, Pierre-Louis Thank you for your feedback, and sorry to bother you. > > the above change breaks simultaneous playback and capture on single > > DAI in more complicated use cases. With above change when one runs > > playback first, startup callback is skipped when running capture > > while playback is still running. Similar issue had been happened on component open before. https://lore.kernel.org/alsa-devel/20200219182650.1416-1-kai.vehmanen@linux.intel.com/ I'm so sorry but this is bug. In my quick check, this patch is not related to other patches. So, just reverting it is nice idea, I think. > Should the 'started' bitfield should be an array for capture and > playback cases respectively? e.g. Yeah. But, I will re-try this issue (for DAI, for Component) again. Let's just revert it so far. Is it OK for you ? Thank you for your help !! Best regards --- Kuninori Morimoto Thank you for your help !! Best regards --- Kuninori Morimoto
On 3/30/2020 3:10 AM, Kuninori Morimoto wrote: > > Hi Amadeusz, Pierre-Louis > > Thank you for your feedback, and sorry to bother you. > >>> the above change breaks simultaneous playback and capture on single >>> DAI in more complicated use cases. With above change when one runs >>> playback first, startup callback is skipped when running capture >>> while playback is still running. > > Similar issue had been happened on component open before. > https://lore.kernel.org/alsa-devel/20200219182650.1416-1-kai.vehmanen@linux.intel.com/ > > I'm so sorry but this is bug. > In my quick check, this patch is not related to other patches. > So, just reverting it is nice idea, I think. > >> Should the 'started' bitfield should be an array for capture and >> playback cases respectively? e.g. > > Yeah. > But, I will re-try this issue (for DAI, for Component) again. > Let's just revert it so far. > Is it OK for you ? > > Thank you for your help !! > Hi, I tested patch from Pierre and it works for me, I'm also ok with revert. Thanks, Amadeusz
On Mon, Mar 30, 2020 at 09:25:31AM +0200, Amadeusz Sławiński wrote: > On 3/30/2020 3:10 AM, Kuninori Morimoto wrote: > > But, I will re-try this issue (for DAI, for Component) again. > > Let's just revert it so far. > > Is it OK for you ? > I tested patch from Pierre and it works for me, I'm also ok with revert. Pierre's patch makes sense to me and this is the only reported issue so I'd be happy with that. Whichever way can one (or both!) of you please send a patch?
Hi Mark > > I tested patch from Pierre and it works for me, I'm also ok with revert. > > Pierre's patch makes sense to me and this is the only reported issue so > I'd be happy with that. Whichever way can one (or both!) of you please > send a patch? I have no objection about Pierre's patch. But I want to re-make it in future. Thank you for your help !! Best regards --- Kuninori Morimoto
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index eaaeb00..04c23ac 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -324,7 +324,6 @@ struct snd_soc_dai { /* DAI runtime info */ unsigned int capture_active; /* stream usage count */ unsigned int playback_active; /* stream usage count */ - unsigned int probed:1; unsigned int active; @@ -348,6 +347,10 @@ struct snd_soc_dai { unsigned int rx_mask; struct list_head list; + + /* bit field */ + unsigned int probed:1; + unsigned int started:1; }; static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 51031e33..73a8293 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -295,17 +295,24 @@ int snd_soc_dai_startup(struct snd_soc_dai *dai, { int ret = 0; - if (dai->driver->ops->startup) + if (!dai->started && + dai->driver->ops->startup) ret = dai->driver->ops->startup(substream, dai); + if (ret == 0) + dai->started = 1; + return ret; } void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream) { - if (dai->driver->ops->shutdown) + if (dai->started && + dai->driver->ops->shutdown) dai->driver->ops->shutdown(substream, dai); + + dai->started = 0; } int snd_soc_dai_prepare(struct snd_soc_dai *dai, diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8d8ed47..d53afb9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -568,7 +568,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) { pr_err("ASoC: %s startup failed: %d\n", rtd->dai_link->name, ret); - goto machine_err; + goto codec_dai_err; } /* Dynamic PCM DAI links compat checks use dynamic capabilities */ @@ -637,11 +637,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) config_err: soc_rtd_shutdown(rtd, substream); -machine_err: - i = rtd->num_codecs; - codec_dai_err: - for_each_rtd_codec_dai_rollback(rtd, i, codec_dai) + for_each_rtd_codec_dai(rtd, i, codec_dai) snd_soc_dai_shutdown(codec_dai, substream); component_err: