summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoumya Managoli <smanag@codeaurora.org>2019-10-03 18:21:07 +0530
committerSoumya Managoli <smanag@codeaurora.org>2019-10-24 14:52:10 +0530
commit1c9afab264e3cafa461d746e9dcfd3c0487754cb (patch)
tree55be2976fe9d54f333458f43c01ca2c40c5c2dc1
parentdd4645c977feb6cef4d7f598abd8864cc7b7e878 (diff)
asoc: msm-pcm: Added lock in controls _put() and _get()
callback There is race condition around private data used in put() and get() of few mixer ctls with close() callback. Added global mutex lock and code changes to protect such critical section by accessing such lock. Change-Id: I276c2a234cfcbef88b4272b945e5c3f121e8eb32 Signed-off-by: Soumya Managoli <smanag@codeaurora.org>
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c81
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h1
2 files changed, 77 insertions, 5 deletions
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index a7aab83..fef0792 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -880,6 +881,14 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
+ pdata = (struct msm_plat_data *)
+ dev_get_drvdata(soc_prtd->platform->dev);
+ if (!pdata) {
+ pr_err("%s: platform data is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&pdata->lock);
if (prtd->audio_client) {
dir = IN;
@@ -922,6 +931,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
kfree(prtd);
runtime->private_data = NULL;
+ mutex_unlock(&pdata->lock);
return 0;
}
@@ -1016,8 +1026,18 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct msm_audio *prtd = runtime->private_data;
int dir = OUT;
+ struct msm_plat_data *pdata;
pr_debug("%s\n", __func__);
+
+ pdata = (struct msm_plat_data *)
+ dev_get_drvdata(soc_prtd->platform->dev);
+ if (!pdata) {
+ pr_err("%s: platform data is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&pdata->lock);
if (prtd->audio_client) {
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
q6asm_audio_client_buf_free_contiguous(dir,
@@ -1029,6 +1049,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
SNDRV_PCM_STREAM_CAPTURE);
kfree(prtd);
runtime->private_data = NULL;
+ mutex_unlock(&pdata->lock);
return 0;
}
@@ -1197,6 +1218,7 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
goto done;
}
+ mutex_lock(&pdata->lock);
event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
(event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
@@ -1228,6 +1250,7 @@ static int msm_pcm_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;
}
@@ -1393,21 +1416,35 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol,
vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
struct msm_audio *prtd;
int volume = ucontrol->value.integer.value[0];
+ struct snd_soc_pcm_runtime *soc_prtd = NULL;
+ struct msm_plat_data *pdata = NULL;
pr_debug("%s: volume : 0x%x\n", __func__, volume);
if (!substream) {
- pr_err("%s substream not found\n", __func__);
+ pr_err("%s: substream not found\n", __func__);
return -ENODEV;
}
- if (!substream->runtime) {
- pr_err("%s substream runtime not found\n", __func__);
+ soc_prtd = substream->private_data;
+ if (!substream->runtime || !soc_prtd) {
+ pr_err("%s: substream runtime or private_data not found\n",
+ __func__);
return 0;
}
+
+ pdata = (struct msm_plat_data *)
+ dev_get_drvdata(soc_prtd->platform->dev);
+ if (!pdata) {
+ pr_err("%s: pdata not found\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&pdata->lock);
prtd = substream->runtime->private_data;
if (prtd) {
rc = msm_pcm_set_volume(prtd, volume);
prtd->volume = volume;
}
+ mutex_unlock(&pdata->lock);
return rc;
}
@@ -1572,14 +1609,28 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
struct snd_pcm_substream *substream;
struct msm_audio *prtd;
+ struct snd_soc_pcm_runtime *rtd = NULL;
+ struct msm_plat_data *pdata = NULL;
pr_debug("%s", __func__);
substream = snd_pcm_chmap_substream(info, idx);
if (!substream)
return -ENODEV;
- if (!substream->runtime)
+
+ rtd = substream->private_data;
+ if (rtd) {
+ pdata = (struct msm_plat_data *)
+ dev_get_drvdata(rtd->platform->dev);
+ if (!pdata) {
+ pr_err("%s: pdata not found\n", __func__);
+ return -ENODEV;
+ }
+ }
+
+ if (!substream->runtime || !rtd)
return 0;
+ mutex_lock(&pdata->lock);
prtd = substream->runtime->private_data;
if (prtd) {
prtd->set_channel_map = true;
@@ -1587,6 +1638,7 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
prtd->channel_map[i] =
(char)(ucontrol->value.integer.value[i]);
}
+ mutex_unlock(&pdata->lock);
return 0;
}
@@ -1598,16 +1650,30 @@ static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
struct snd_pcm_substream *substream;
struct msm_audio *prtd;
+ struct snd_soc_pcm_runtime *rtd = NULL;
+ struct msm_plat_data *pdata = NULL;
pr_debug("%s", __func__);
substream = snd_pcm_chmap_substream(info, idx);
if (!substream)
return -ENODEV;
+
+ rtd = substream->private_data;
+ if (rtd) {
+ pdata = (struct msm_plat_data *)
+ dev_get_drvdata(rtd->platform->dev);
+ if (!pdata) {
+ pr_err("%s: pdata not found\n", __func__);
+ return -ENODEV;
+ }
+ }
+
memset(ucontrol->value.integer.value, 0,
sizeof(ucontrol->value.integer.value));
- if (!substream->runtime)
+ if (!substream->runtime || !rtd)
return 0; /* no channels set */
+ mutex_lock(&pdata->lock);
prtd = substream->runtime->private_data;
if (prtd && prtd->set_channel_map == true) {
@@ -1619,6 +1685,7 @@ static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[i] = 0;
}
+ mutex_unlock(&pdata->lock);
return 0;
}
@@ -2244,6 +2311,7 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
chmixer_pspd->output_channel = ucontrol->value.integer.value[3];
chmixer_pspd->port_idx = ucontrol->value.integer.value[4];
+ mutex_lock(&pdata->lock);
/* cache value and take effect during adm_open stage */
msm_pcm_routing_set_channel_mixer_cfg(fe_id,
session_type,
@@ -2266,6 +2334,7 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
}
}
done:
+ mutex_unlock(&pdata->lock);
return ret;
}
@@ -3089,6 +3158,7 @@ static int msm_pcm_probe(struct platform_device *pdev)
pr_debug("%s: avs_ver = %d\n", __func__, pdata->avs_ver);
+ mutex_init(&pdata->lock);
dev_set_drvdata(&pdev->dev, pdata);
dev_dbg(&pdev->dev, "%s: dev name %s\n",
@@ -3102,6 +3172,7 @@ static int msm_pcm_remove(struct platform_device *pdev)
struct msm_plat_data *pdata;
pdata = dev_get_drvdata(&pdev->dev);
+ mutex_destroy(&pdata->lock);
kfree(pdata);
snd_soc_unregister_platform(&pdev->dev);
return 0;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index a90e9f7..f0a9648 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -127,6 +127,7 @@ struct msm_plat_data {
struct snd_pcm *pcm;
struct snd_pcm *pcm_device[MSM_FRONTEND_DAI_MM_SIZE];
struct msm_pcm_channel_mixer chmixer_pspd[MSM_FRONTEND_DAI_MM_SIZE][2];
+ struct mutex lock;
};
#endif /*_MSM_PCM_H*/