[alsa-devel] [PATCH] ASoC: ti: davinci-mcasp: Protect hw_params callback against race
If the playback and capture of the same McASP is connected to different dai link (non duplex PCM links, like with pcm3168a codec) then there is a high probability of race between the two direction leaving McASP in a confused state.
Protect the hw_params() with a mutex to make sure that this is not happening.
The concurrent execution of hw_params for capture and playback can be easily triggered with custom .asoundrc file (for pcm3168a codec):
pcm.dmixed8 { type dmix ipc_key 2048 ipc_perm 0666 slave { pcm "hw:0,0" format S24_LE channels 8 rate 96000 } bindings { 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 } }
pcm.cpb-headset-1 { type plug slave.pcm dmixed8
hint { show on description "Headset 1 jack" } ttable.0.0 1 ttable.1.4 1 }
pcm.dsnooped6 { type dsnoop ipc_key 2049 ipc_perm 0666 slave { pcm "hw:0,1" format S24_LE channels 6 rate 96000 } bindings { 0 0 1 1 2 2 3 3 4 4 5 5 } }
pcm.cpb-mic-1 { type plug slave.pcm "dsnooped6"
hint { show on description "Microphone 1 jack" } ttable.0.0 1 ttable.1.3 1 }
Then running: arecord -D cpb-mic-1 -f S24_LE -c2 -r48000 | aplay -D cpb-headset-1 -f S24_LE -c2 -r48000
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com --- sound/soc/ti/davinci-mcasp.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c index 7aa3c32e4a49..fe7a0b3572e2 100644 --- a/sound/soc/ti/davinci-mcasp.c +++ b/sound/soc/ti/davinci-mcasp.c @@ -111,6 +111,7 @@ struct davinci_mcasp { u32 channels; int max_format_width; u8 active_serializers[2]; + struct mutex mutex;
#ifdef CONFIG_GPIOLIB struct gpio_chip gpio_chip; @@ -1169,6 +1170,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, int period_size = params_period_size(params); int ret;
+ mutex_lock(&mcasp->mutex); + switch (params_format(params)) { case SNDRV_PCM_FORMAT_U8: case SNDRV_PCM_FORMAT_S8: @@ -1197,12 +1200,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
default: printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); - return -EINVAL; + ret = -EINVAL; + goto out; }
ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt); if (ret) - return ret; + goto out;
/* * If mcasp is BCLK master, and a BCLK divider was not provided by @@ -1223,7 +1227,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, ret = mcasp_common_hw_param(mcasp, substream->stream, period_size * channels, channels); if (ret) - return ret; + goto out;
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE) ret = mcasp_dit_hw_param(mcasp, params_rate(params)); @@ -1232,7 +1236,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, channels);
if (ret) - return ret; + goto out;
davinci_config_channel_size(mcasp, word_length);
@@ -1242,7 +1246,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, mcasp->max_format_width = word_length; }
- return 0; +out: + mutex_unlock(&mcasp->mutex); + + return ret; }
static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, @@ -2335,6 +2342,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev) if (ret) return -EINVAL;
+ mutex_init(&mcasp->mutex); + ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component, &davinci_mcasp_dai[pdata->op_mode], 1);
On Mon, Aug 12, 2019 at 12:53:04PM +0300, Peter Ujfalusi wrote:
If the playback and capture of the same McASP is connected to different dai link (non duplex PCM links, like with pcm3168a codec) then there is a high probability of race between the two direction leaving McASP in a confused state.
Protect the hw_params() with a mutex to make sure that this is not happening.
This feels like something we might want to consider moving up to the core, though not every device is going to need it I guess it should be safe to do there.
On 12/08/2019 14.13, Mark Brown wrote:
On Mon, Aug 12, 2019 at 12:53:04PM +0300, Peter Ujfalusi wrote:
If the playback and capture of the same McASP is connected to different dai link (non duplex PCM links, like with pcm3168a codec) then there is a high probability of race between the two direction leaving McASP in a confused state.
Protect the hw_params() with a mutex to make sure that this is not happening.
This feels like something we might want to consider moving up to the core, though not every device is going to need it I guess it should be safe to do there.
soc_pcm_hw_params() is already protected by mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
which (I think) gives protection for dai_links when they support both playback and capture.
I faced with the concurrency when interfacing with pcm3168a codec, which require two dai_links. One for playback and one for capture so they don't share the same snd_soc_pcm_runtime.
I believe moving the mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
to card level could substitute (new mutex on the card for pcm operations probably) the need to handle this in drivers.
We would need to change soc-core/pcm/compress for this.
- Péter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On Mon, Aug 12, 2019 at 02:46:33PM +0300, Peter Ujfalusi wrote:
to card level could substitute (new mutex on the card for pcm operations probably) the need to handle this in drivers.
We would need to change soc-core/pcm/compress for this.
Yeah, it'd be a reasonably substantial change.
On 12/08/2019 14.57, Mark Brown wrote:
On Mon, Aug 12, 2019 at 02:46:33PM +0300, Peter Ujfalusi wrote:
to card level could substitute (new mutex on the card for pcm operations probably) the need to handle this in drivers.
We would need to change soc-core/pcm/compress for this.
Yeah, it'd be a reasonably substantial change.
OK, works fine on several boards, I'll send a patch tomorrow after a bit more testing.
- Péter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
On Mon, Aug 12, 2019 at 03:56:11PM +0300, Peter Ujfalusi wrote:
On 12/08/2019 14.57, Mark Brown wrote:
On Mon, Aug 12, 2019 at 02:46:33PM +0300, Peter Ujfalusi wrote:
to card level could substitute (new mutex on the card for pcm operations probably) the need to handle this in drivers.
We would need to change soc-core/pcm/compress for this.
Yeah, it'd be a reasonably substantial change.
OK, works fine on several boards, I'll send a patch tomorrow after a bit more testing.
Ah, excellent, thanks for that! That was more of a "we should do this" thing than a "do this instead" thing but obviously fixing more systems is even better so please don't let me stop you. Only sending applied mails when I push things out solves one set of problems but does make for other races :/
participants (2)
-
Mark Brown
-
Peter Ujfalusi