summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjit Pandey <ajitp@codeaurora.org>2019-09-04 14:34:00 +0530
committerShalini Manjunatha <shalma@codeaurora.org>2020-01-23 15:51:00 +0530
commit4365dbfbfec026fcead61838af0fd4b70a258278 (patch)
treeb8e864446a72480d9b58a201cdf9c470d64cbecb
parente6f9fd09cc38cc5ea552ce7287559699d55ba391 (diff)
downloadmsm-extra-4365dbfbfec026fcead61838af0fd4b70a258278.tar.gz
asoc: msm-compress: Add lock in controls _put() and _get() callback
Few mixer controls _put and _get methods uses runtime private data that can be freed by close() callback in parallel threads leading to issue. Added global mutex lock in such methods to avoid runtime concurrency around such data. Change-Id: Ie542c64a4f1e50fd9547ebb9f65df2b7b0c21a0e Signed-off-by: Ajit Pandey <ajitp@codeaurora.org>
-rw-r--r--asoc/msm-compress-q6-v2.c98
1 files changed, 79 insertions, 19 deletions
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index 1735adba..0cf4074f 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
#include <linux/time.h>
#include <linux/math64.h>
#include <linux/wait.h>
+#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -103,6 +104,7 @@ struct msm_compr_pdata {
struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX];
struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX];
bool is_in_use[MSM_FRONTEND_DAI_MAX];
+ struct mutex lock;
};
struct msm_compr_audio {
@@ -1793,6 +1795,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
}
spin_unlock_irqrestore(&prtd->lock, flags);
+ mutex_lock(&pdata->lock);
pdata->cstream[soc_prtd->dai_link->id] = NULL;
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
@@ -1814,6 +1817,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
pdata->is_in_use[soc_prtd->dai_link->id] = false;
kfree(prtd);
runtime->private_data = NULL;
+ mutex_unlock(&pdata->lock);
return 0;
}
@@ -1864,6 +1868,7 @@ static int msm_compr_capture_free(struct snd_compr_stream *cstream)
}
spin_unlock_irqrestore(&prtd->lock, flags);
+ mutex_lock(&pdata->lock);
pdata->cstream[soc_prtd->dai_link->id] = NULL;
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->id,
SNDRV_PCM_STREAM_CAPTURE);
@@ -1874,6 +1879,7 @@ static int msm_compr_capture_free(struct snd_compr_stream *cstream)
kfree(prtd);
runtime->private_data = NULL;
+ mutex_unlock(&pdata->lock);
return 0;
}
@@ -3171,6 +3177,7 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
struct snd_compr_stream *cstream = NULL;
struct msm_compr_audio *prtd = NULL;
long *values = &(ucontrol->value.integer.value[0]);
+ int ret = 0;
int effects_module;
pr_debug("%s\n", __func__);
@@ -3179,21 +3186,25 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
__func__, fe_id);
return -EINVAL;
}
+
+ mutex_lock(&pdata->lock);
cstream = pdata->cstream[fe_id];
audio_effects = pdata->audio_effects[fe_id];
if (!cstream || !audio_effects) {
pr_err("%s: stream or effects inactive\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
prtd = cstream->runtime->private_data;
if (!prtd) {
pr_err("%s: cannot set audio effects\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
if (prtd->compr_passthr != LEGACY_PCM) {
pr_debug("%s: No effects for compr_type[%d]\n",
__func__, prtd->compr_passthr);
- return 0;
+ goto done;
}
pr_debug("%s: Effects supported for compr_type[%d]\n",
__func__, prtd->compr_passthr);
@@ -3254,9 +3265,11 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
break;
default:
pr_err("%s Invalid effects config module\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+done:
+ mutex_unlock(&pdata->lock);
+ return ret;
}
static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
@@ -3268,6 +3281,7 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
snd_soc_component_get_drvdata(comp);
struct msm_compr_audio_effects *audio_effects = NULL;
struct snd_compr_stream *cstream = NULL;
+ int ret = 0;
struct msm_compr_audio *prtd = NULL;
pr_debug("%s\n", __func__);
@@ -3276,19 +3290,23 @@ static int msm_compr_audio_effects_config_get(struct snd_kcontrol *kcontrol,
__func__, fe_id);
return -EINVAL;
}
+
+ mutex_lock(&pdata->lock);
cstream = pdata->cstream[fe_id];
audio_effects = pdata->audio_effects[fe_id];
if (!cstream || !audio_effects) {
pr_debug("%s: stream or effects inactive\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
prtd = cstream->runtime->private_data;
if (!prtd) {
pr_err("%s: cannot set audio effects\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
}
-
- return 0;
+done:
+ mutex_unlock(&pdata->lock);
+ return ret;
}
static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
@@ -3301,6 +3319,7 @@ static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
struct msm_compr_audio_effects *audio_effects = NULL;
struct snd_compr_stream *cstream = NULL;
struct msm_compr_audio *prtd = NULL;
+ int ret = 0;
long *values = &(ucontrol->value.integer.value[0]);
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
@@ -3308,28 +3327,37 @@ static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
__func__, fe_id);
return -EINVAL;
}
+
+ mutex_lock(&pdata->lock);
+
cstream = pdata->cstream[fe_id];
audio_effects = pdata->audio_effects[fe_id];
if (!cstream || !audio_effects) {
pr_err("%s: stream or effects inactive\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
prtd = cstream->runtime->private_data;
if (!prtd) {
pr_err("%s: cannot set audio effects\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
if (prtd->compr_passthr != LEGACY_PCM) {
pr_err("%s: No effects for compr_type[%d]\n",
__func__, prtd->compr_passthr);
- return -EPERM;
+ ret = -EPERM;
+ goto done;
}
audio_effects->query.mod_id = (u32)*values++;
audio_effects->query.parm_id = (u32)*values++;
audio_effects->query.size = (u32)*values++;
audio_effects->query.offset = (u32)*values++;
audio_effects->query.device = (u32)*values++;
- return 0;
+
+done:
+ mutex_unlock(&pdata->lock);
+ return ret;
}
static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
@@ -3342,6 +3370,7 @@ static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
struct msm_compr_audio_effects *audio_effects = NULL;
struct snd_compr_stream *cstream = NULL;
struct msm_compr_audio *prtd = NULL;
+ int ret = 0;
long *values = &(ucontrol->value.integer.value[0]);
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
@@ -3349,23 +3378,29 @@ static int msm_compr_query_audio_effect_get(struct snd_kcontrol *kcontrol,
__func__, fe_id);
return -EINVAL;
}
+
+ mutex_lock(&pdata->lock);
cstream = pdata->cstream[fe_id];
audio_effects = pdata->audio_effects[fe_id];
if (!cstream || !audio_effects) {
pr_debug("%s: stream or effects inactive\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
prtd = cstream->runtime->private_data;
if (!prtd) {
pr_err("%s: cannot set audio effects\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
values[0] = (long)audio_effects->query.mod_id;
values[1] = (long)audio_effects->query.parm_id;
values[2] = (long)audio_effects->query.size;
values[3] = (long)audio_effects->query.offset;
values[4] = (long)audio_effects->query.device;
- return 0;
+done:
+ mutex_unlock(&pdata->lock);
+ return ret;
}
static int msm_compr_send_dec_params(struct snd_compr_stream *cstream,
@@ -3451,6 +3486,7 @@ static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
goto end;
}
+ mutex_lock(&pdata->lock);
switch (prtd->codec) {
case FORMAT_MP3:
case FORMAT_MPEG4_AAC:
@@ -3502,6 +3538,7 @@ static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
}
end:
pr_debug("%s: ret %d\n", __func__, rc);
+ mutex_unlock(&pdata->lock);
return rc;
}
@@ -3710,6 +3747,7 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
goto done;
}
+ mutex_lock(&pdata->lock);
if (prtd->audio_client == NULL) {
pr_err("%s: audio_client is null\n", __func__);
ret = -EINVAL;
@@ -3747,6 +3785,7 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
pr_err("%s: failed to send stream event cmd, err = %d\n",
__func__, ret);
done:
+ mutex_unlock(&pdata->lock);
return ret;
}
@@ -3783,6 +3822,7 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
goto done;
}
+ mutex_lock(&pdata->lock);
if (prtd->audio_client == NULL) {
pr_err("%s: audio_client is null\n", __func__);
ret = -EINVAL;
@@ -3794,6 +3834,7 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
if (ret < 0)
pr_err("%s: failed to register ion fd\n", __func__);
done:
+ mutex_unlock(&pdata->lock);
return ret;
}
@@ -3816,6 +3857,7 @@ static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
goto done;
}
+ mutex_lock(&pdata->lock);
cstream = pdata->cstream[fe_id];
if (cstream == NULL) {
pr_err("%s cstream is null\n", __func__);
@@ -3853,6 +3895,7 @@ static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
pr_err("%s: failed to send rtic event ack, err = %d\n",
__func__, ret);
done:
+ mutex_unlock(&pdata->lock);
return ret;
}
@@ -3937,6 +3980,22 @@ static int msm_compr_probe(struct snd_soc_platform *platform)
return 0;
}
+static int msm_compr_remove(struct snd_soc_platform *platform)
+{
+
+ struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+ snd_soc_platform_get_drvdata(platform);
+ if (!pdata) {
+ pr_err("%s pdata is null\n", __func__);
+ return -ENOMEM;
+ }
+
+ mutex_destroy(&pdata->lock);
+ kfree(pdata);
+
+ return 0;
+}
+
static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -4578,6 +4637,7 @@ static struct snd_soc_platform_driver msm_soc_platform = {
.probe = msm_compr_probe,
.compr_ops = &msm_compr_ops,
.pcm_new = msm_compr_new,
+ .remove = msm_compr_remove,
};
static int msm_compr_dev_probe(struct platform_device *pdev)
@@ -4588,7 +4648,7 @@ static int msm_compr_dev_probe(struct platform_device *pdev)
&msm_soc_platform);
}
-static int msm_compr_remove(struct platform_device *pdev)
+static int msm_compr_dev_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
return 0;
@@ -4608,7 +4668,7 @@ static struct platform_driver msm_compr_driver = {
.suppress_bind_attrs = true,
},
.probe = msm_compr_dev_probe,
- .remove = msm_compr_remove,
+ .remove = msm_compr_dev_remove,
};
static int __init msm_soc_platform_init(void)