[alsa-devel] [PATCH] ASoC: core: Move pcm_mutex up to card level from snd_soc_pcm_runtime
Peter Ujfalusi
peter.ujfalusi at ti.com
Thu Aug 15 09:07:04 CEST 2019
On 14/08/2019 21.14, Pierre-Louis Bossart wrote:
>
>
> On 8/13/19 5:45 AM, Peter Ujfalusi wrote:
>> The pcm_mutex is used to prevent concurrent execution of snd_pcm_ops
>> callbacks. This works fine most of the cases but it can not handle setups
>> when the same DAI is used by different rtd, for example:
>> pcm3168a have two DAIs: one for Playback and one for Capture.
>> If the codec is connected to a single CPU DAI we need to have two
>> dai_link
>> to support both playback and capture.
>>
>> In this case the snd_pcm_ops callbacks can be executed in parallel
>> causing
>> unexpected races in DAI drivers.
>>
>> By moving the pcm_mutex up to card level this can be solved
>> while - hopefully - not breaking other setups.
>>
>> Signed-off-by: Peter Ujfalusi <peter.ujfalusi at ti.com>
>> ---
>> Hi,
>>
>> I have tested the patch on several boards. it fixes the issue with
>> single card
>> with multiple dai_links where the CPU side (mcasp) is the same.
>>
>> However I can not test with anything which use DPCM. It would be great
>> if the
>> patch would gather few tested-by from folks having access to more
>> complicated
>> setups.
>
> Actually you *can* test by submitting a PR for SOF, it'll trigger some
> tests on Intel platforms using DPCM. It's not going to test anything
> related to the compressed API but it's better than nothing.
Good to know and thanks.
I would not thought of abusing the SOF project to run tests, not that I
know how to trigger the right tests ;)
>
> I took this patch and created one PR as an example
> https://github.com/thesofproject/linux/pull/1132
Should I be worried because of your comment there saying 'I have no idea
why the BYT_NOCODEC mode fails, there's no information provided.' ?
>
> Will share results when I have them.
Thank you!
> -Pierre
>
>
>>
>> The backround of this patch:
>> https://mailman.alsa-project.org/pipermail/alsa-devel/2019-August/153864.html
>>
>>
>> Regards,
>> Peter
>>
>> include/sound/soc.h | 6 +++--
>> sound/soc/soc-compress.c | 48 ++++++++++++++++++++--------------------
>> sound/soc/soc-core.c | 2 +-
>> sound/soc/soc-pcm.c | 36 +++++++++++++++---------------
>> 4 files changed, 47 insertions(+), 45 deletions(-)
>>
>> diff --git a/include/sound/soc.h b/include/sound/soc.h
>> index 6ac6481b4882..ec2dbe0ac2aa 100644
>> --- a/include/sound/soc.h
>> +++ b/include/sound/soc.h
>> @@ -990,6 +990,10 @@ struct snd_soc_card {
>> struct mutex mutex;
>> struct mutex dapm_mutex;
>> + /* Mutex for PCM operations */
>> + struct mutex pcm_mutex;
>> + enum snd_soc_pcm_subclass pcm_subclass;
>> +
>> spinlock_t dpcm_lock;
>> bool instantiated;
>> @@ -1107,8 +1111,6 @@ struct snd_soc_pcm_runtime {
>> struct device *dev;
>> struct snd_soc_card *card;
>> struct snd_soc_dai_link *dai_link;
>> - struct mutex pcm_mutex;
>> - enum snd_soc_pcm_subclass pcm_subclass;
>> struct snd_pcm_ops ops;
>> unsigned int params_select; /* currently selected param for
>> dai link */
>> diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
>> index 289211069a1e..9e54d8ae6d2c 100644
>> --- a/sound/soc/soc-compress.c
>> +++ b/sound/soc/soc-compress.c
>> @@ -80,7 +80,7 @@ static int soc_compr_open(struct snd_compr_stream
>> *cstream)
>> struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>> int ret;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
>> ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
>> @@ -108,7 +108,7 @@ static int soc_compr_open(struct snd_compr_stream
>> *cstream)
>> snd_soc_runtime_activate(rtd, cstream->direction);
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return 0;
>> @@ -118,7 +118,7 @@ static int soc_compr_open(struct
>> snd_compr_stream *cstream)
>> if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
>> cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
>> out:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -224,7 +224,7 @@ static void close_delayed_work(struct
>> work_struct *work)
>> container_of(work, struct snd_soc_pcm_runtime,
>> delayed_work.work);
>> struct snd_soc_dai *codec_dai = rtd->codec_dai;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> dev_dbg(rtd->dev,
>> "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
>> @@ -239,7 +239,7 @@ static void close_delayed_work(struct work_struct
>> *work)
>> SND_SOC_DAPM_STREAM_STOP);
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> }
>> static int soc_compr_free(struct snd_compr_stream *cstream)
>> @@ -249,7 +249,7 @@ static int soc_compr_free(struct snd_compr_stream
>> *cstream)
>> struct snd_soc_dai *codec_dai = rtd->codec_dai;
>> int stream;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> if (cstream->direction == SND_COMPRESS_PLAYBACK)
>> stream = SNDRV_PCM_STREAM_PLAYBACK;
>> @@ -292,7 +292,7 @@ static int soc_compr_free(struct snd_compr_stream
>> *cstream)
>> SND_SOC_DAPM_STREAM_STOP);
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return 0;
>> }
>> @@ -375,7 +375,7 @@ static int soc_compr_trigger(struct
>> snd_compr_stream *cstream, int cmd)
>> struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>> int ret;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> ret = soc_compr_components_trigger(cstream, cmd);
>> if (ret < 0)
>> @@ -394,7 +394,7 @@ static int soc_compr_trigger(struct
>> snd_compr_stream *cstream, int cmd)
>> }
>> out:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -480,7 +480,7 @@ static int soc_compr_set_params(struct
>> snd_compr_stream *cstream,
>> struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>> int ret;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> /*
>> * First we call set_params for the CPU DAI, then the component
>> @@ -514,14 +514,14 @@ static int soc_compr_set_params(struct
>> snd_compr_stream *cstream,
>> /* cancel any delayed stream shutdown that is pending */
>> rtd->pop_wait = 0;
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> cancel_delayed_work_sync(&rtd->delayed_work);
>> return 0;
>> err:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -593,7 +593,7 @@ static int soc_compr_get_params(struct
>> snd_compr_stream *cstream,
>> struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>> int ret = 0;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
>> ret = cpu_dai->driver->cops->get_params(cstream, params,
>> cpu_dai);
>> @@ -613,7 +613,7 @@ static int soc_compr_get_params(struct
>> snd_compr_stream *cstream,
>> }
>> err:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -625,7 +625,7 @@ static int soc_compr_get_caps(struct
>> snd_compr_stream *cstream,
>> struct snd_soc_rtdcom_list *rtdcom;
>> int ret = 0;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> for_each_rtdcom(rtd, rtdcom) {
>> component = rtdcom->component;
>> @@ -638,7 +638,7 @@ static int soc_compr_get_caps(struct
>> snd_compr_stream *cstream,
>> break;
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -650,7 +650,7 @@ static int soc_compr_get_codec_caps(struct
>> snd_compr_stream *cstream,
>> struct snd_soc_rtdcom_list *rtdcom;
>> int ret = 0;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> for_each_rtdcom(rtd, rtdcom) {
>> component = rtdcom->component;
>> @@ -664,7 +664,7 @@ static int soc_compr_get_codec_caps(struct
>> snd_compr_stream *cstream,
>> break;
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -676,7 +676,7 @@ static int soc_compr_ack(struct snd_compr_stream
>> *cstream, size_t bytes)
>> struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>> int ret = 0;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
>> ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
>> @@ -697,7 +697,7 @@ static int soc_compr_ack(struct snd_compr_stream
>> *cstream, size_t bytes)
>> }
>> err:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -710,7 +710,7 @@ static int soc_compr_pointer(struct
>> snd_compr_stream *cstream,
>> int ret = 0;
>> struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
>> cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
>> @@ -726,7 +726,7 @@ static int soc_compr_pointer(struct
>> snd_compr_stream *cstream,
>> break;
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -738,7 +738,7 @@ static int soc_compr_copy(struct
>> snd_compr_stream *cstream,
>> struct snd_soc_rtdcom_list *rtdcom;
>> int ret = 0;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> for_each_rtdcom(rtd, rtdcom) {
>> component = rtdcom->component;
>> @@ -751,7 +751,7 @@ static int soc_compr_copy(struct snd_compr_stream
>> *cstream,
>> break;
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
>> index bb1e9e2c4ff4..7f2064889a23 100644
>> --- a/sound/soc/soc-core.c
>> +++ b/sound/soc/soc-core.c
>> @@ -1344,7 +1344,6 @@ static int soc_post_component_init(struct
>> snd_soc_pcm_runtime *rtd,
>> rtd->dev->groups = soc_dev_attr_groups;
>> dev_set_name(rtd->dev, "%s", name);
>> dev_set_drvdata(rtd->dev, rtd);
>> - mutex_init(&rtd->pcm_mutex);
>> INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
>> INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].be_clients);
>> INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].fe_clients);
>> @@ -2395,6 +2394,7 @@ int snd_soc_register_card(struct snd_soc_card
>> *card)
>> card->instantiated = 0;
>> mutex_init(&card->mutex);
>> mutex_init(&card->dapm_mutex);
>> + mutex_init(&card->pcm_mutex);
>> spin_lock_init(&card->dpcm_lock);
>> return snd_soc_bind_card(card);
>> diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
>> index 77c986fe08d0..93bb4a347779 100644
>> --- a/sound/soc/soc-pcm.c
>> +++ b/sound/soc/soc-pcm.c
>> @@ -36,7 +36,7 @@
>> * Increments the active count for all the DAIs and components
>> attached to a PCM
>> * runtime. Should typically be called when a stream is opened.
>> *
>> - * Must be called with the rtd->pcm_mutex being held
>> + * Must be called with the rtd->card->pcm_mutex being held
>> */
>> void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int
>> stream)
>> {
>> @@ -44,7 +44,7 @@ void snd_soc_runtime_activate(struct
>> snd_soc_pcm_runtime *rtd, int stream)
>> struct snd_soc_dai *codec_dai;
>> int i;
>> - lockdep_assert_held(&rtd->pcm_mutex);
>> + lockdep_assert_held(&rtd->card->pcm_mutex);
>> if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
>> cpu_dai->playback_active++;
>> @@ -72,7 +72,7 @@ void snd_soc_runtime_activate(struct
>> snd_soc_pcm_runtime *rtd, int stream)
>> * Decrements the active count for all the DAIs and components
>> attached to a PCM
>> * runtime. Should typically be called when a stream is closed.
>> *
>> - * Must be called with the rtd->pcm_mutex being held
>> + * Must be called with the rtd->card->pcm_mutex being held
>> */
>> void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int
>> stream)
>> {
>> @@ -80,7 +80,7 @@ void snd_soc_runtime_deactivate(struct
>> snd_soc_pcm_runtime *rtd, int stream)
>> struct snd_soc_dai *codec_dai;
>> int i;
>> - lockdep_assert_held(&rtd->pcm_mutex);
>> + lockdep_assert_held(&rtd->card->pcm_mutex);
>> if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
>> cpu_dai->playback_active--;
>> @@ -506,7 +506,7 @@ static int soc_pcm_open(struct snd_pcm_substream
>> *substream)
>> pm_runtime_get_sync(component->dev);
>> }
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> /* startup the audio subsystem */
>> ret = snd_soc_dai_startup(cpu_dai, substream);
>> @@ -604,7 +604,7 @@ static int soc_pcm_open(struct snd_pcm_substream
>> *substream)
>> snd_soc_runtime_activate(rtd, substream->stream);
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return 0;
>> config_err:
>> @@ -623,7 +623,7 @@ static int soc_pcm_open(struct snd_pcm_substream
>> *substream)
>> snd_soc_dai_shutdown(cpu_dai, substream);
>> out:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> for_each_rtdcom(rtd, rtdcom) {
>> component = rtdcom->component;
>> @@ -653,7 +653,7 @@ static void close_delayed_work(struct work_struct
>> *work)
>> container_of(work, struct snd_soc_pcm_runtime,
>> delayed_work.work);
>> struct snd_soc_dai *codec_dai = rtd->codec_dais[0];
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s
>> waiting: %s\n",
>> codec_dai->driver->playback.stream_name,
>> @@ -667,7 +667,7 @@ static void close_delayed_work(struct work_struct
>> *work)
>> SND_SOC_DAPM_STREAM_STOP);
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> }
>> static void codec2codec_close_delayed_work(struct work_struct *work)
>> @@ -694,7 +694,7 @@ static int soc_pcm_close(struct snd_pcm_substream
>> *substream)
>> struct snd_soc_dai *codec_dai;
>> int i;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> snd_soc_runtime_deactivate(rtd, substream->stream);
>> @@ -738,7 +738,7 @@ static int soc_pcm_close(struct
>> snd_pcm_substream *substream)
>> SND_SOC_DAPM_STREAM_STOP);
>> }
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> for_each_rtdcom(rtd, rtdcom) {
>> component = rtdcom->component;
>> @@ -771,7 +771,7 @@ static int soc_pcm_prepare(struct
>> snd_pcm_substream *substream)
>> struct snd_soc_dai *codec_dai;
>> int i, ret = 0;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> if (rtd->dai_link->ops->prepare) {
>> ret = rtd->dai_link->ops->prepare(substream);
>> @@ -826,7 +826,7 @@ static int soc_pcm_prepare(struct
>> snd_pcm_substream *substream)
>> snd_soc_dai_digital_mute(cpu_dai, 0, substream->stream);
>> out:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -876,7 +876,7 @@ static int soc_pcm_hw_params(struct
>> snd_pcm_substream *substream,
>> struct snd_soc_dai *codec_dai;
>> int i, ret = 0;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> if (rtd->dai_link->ops->hw_params) {
>> ret = rtd->dai_link->ops->hw_params(substream, params);
>> if (ret < 0) {
>> @@ -962,7 +962,7 @@ static int soc_pcm_hw_params(struct
>> snd_pcm_substream *substream,
>> if (ret)
>> goto component_err;
>> out:
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> component_err:
>> @@ -986,7 +986,7 @@ static int soc_pcm_hw_params(struct
>> snd_pcm_substream *substream,
>> if (rtd->dai_link->ops->hw_free)
>> rtd->dai_link->ops->hw_free(substream);
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return ret;
>> }
>> @@ -1001,7 +1001,7 @@ static int soc_pcm_hw_free(struct
>> snd_pcm_substream *substream)
>> bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
>> int i;
>> - mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
>> + mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
>> /* clear the corresponding DAIs parameters when going to be
>> inactive */
>> if (cpu_dai->active == 1) {
>> @@ -1043,7 +1043,7 @@ static int soc_pcm_hw_free(struct
>> snd_pcm_substream *substream)
>> snd_soc_dai_hw_free(cpu_dai, substream);
>> - mutex_unlock(&rtd->pcm_mutex);
>> + mutex_unlock(&rtd->card->pcm_mutex);
>> return 0;
>> }
>>
- Péter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
More information about the Alsa-devel
mailing list