[alsa-devel] [PATCH] ASoC: ti: davinci-mcasp: Protect hw_params callback against race

Peter Ujfalusi peter.ujfalusi at ti.com
Mon Aug 12 11:53:04 CEST 2019


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 at 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);
-- 
Peter

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