OSDN Git Service

asoc: msm-compress: Add lock in controls _put() and _get() callback
authorJhansi Konathala <cjkonat@codeaurora.org>
Fri, 29 Nov 2019 12:02:07 +0000 (17:32 +0530)
committerGerrit - the friendly Code Review server <code-review@localhost>
Sat, 25 Jan 2020 11:11:04 +0000 (03:11 -0800)
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>
Signed-off-by: Jhansi Konathala <cjkonat@codeaurora.org>
sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c

index 3746a20..10976bf 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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>
@@ -107,6 +108,7 @@ struct msm_compr_pdata {
        int32_t ion_fd[MSM_FRONTEND_DAI_MAX];
        bool is_in_use[MSM_FRONTEND_DAI_MAX];
        bool avs_ver;
+       struct mutex lock;
 };
 
 struct msm_compr_audio {
@@ -1851,6 +1853,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->be_id] = NULL;
        if (cstream->direction == SND_COMPRESS_PLAYBACK) {
                msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
@@ -1880,6 +1883,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
        pdata->is_in_use[soc_prtd->dai_link->be_id] = false;
        kfree(prtd);
        runtime->private_data = NULL;
+       mutex_unlock(&pdata->lock);
 
        return 0;
 }
@@ -1930,6 +1934,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->be_id] = NULL;
        msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
                                        SNDRV_PCM_STREAM_CAPTURE);
@@ -1940,6 +1945,7 @@ static int msm_compr_capture_free(struct snd_compr_stream *cstream)
 
        kfree(prtd);
        runtime->private_data = NULL;
+       mutex_unlock(&pdata->lock);
 
        return 0;
 }
@@ -3228,6 +3234,7 @@ static int msm_compr_audio_effects_config_put(struct snd_kcontrol *kcontrol,
        struct msm_compr_audio *prtd = NULL;
        long *values = &(ucontrol->value.integer.value[0]);
        int effects_module;
+       int ret = 0;
 
        pr_debug("%s\n", __func__);
        if (fe_id >= MSM_FRONTEND_DAI_MAX) {
@@ -3235,16 +3242,19 @@ 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",
@@ -3310,9 +3320,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,
@@ -3325,6 +3337,7 @@ static int msm_compr_audio_effects_config_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;
 
        pr_debug("%s\n", __func__);
        if (fe_id >= MSM_FRONTEND_DAI_MAX) {
@@ -3332,19 +3345,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_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;
        }
-
-       return 0;
+done:
+       mutex_unlock(&pdata->lock);
+       return ret;
 }
 
 static int msm_compr_query_audio_effect_put(struct snd_kcontrol *kcontrol,
@@ -3357,6 +3374,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) {
@@ -3364,28 +3382,34 @@ 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,
@@ -3398,6 +3422,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) {
@@ -3405,23 +3430,28 @@ 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,
@@ -3508,6 +3538,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:
@@ -3556,6 +3587,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;
 }
 
@@ -4093,6 +4125,7 @@ static int msm_compr_probe(struct snd_soc_platform *platform)
        if (!pdata)
                return -ENOMEM;
 
+       mutex_init(&pdata->lock);
        snd_soc_platform_set_drvdata(platform, pdata);
 
        for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
@@ -4138,6 +4171,20 @@ 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)
 {
@@ -4900,6 +4947,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)
@@ -4910,7 +4958,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;
@@ -4929,7 +4977,7 @@ static struct platform_driver msm_compr_driver = {
                .of_match_table = msm_compr_dt_match,
        },
        .probe = msm_compr_dev_probe,
-       .remove = msm_compr_remove,
+       .remove = msm_compr_dev_remove,
 };
 
 static int __init msm_soc_platform_init(void)