ALSA: hda/tas2781: add locks to kcontrols
authorGergo Koteles <soyer@irl.hu>
Tue, 26 Mar 2024 16:18:46 +0000 (17:18 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 27 Mar 2024 10:19:28 +0000 (11:19 +0100)
The rcabin.profile_cfg_id, cur_prog, cur_conf, force_fwload_status
variables are acccessible from multiple threads and therefore require
locking.

Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver")
CC: stable@vger.kernel.org
Signed-off-by: Gergo Koteles <soyer@irl.hu>
Message-ID: <e35b867f6fe5fa1f869dd658a0a1f2118b737f57.1711469583.git.soyer@irl.hu>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/tas2781_hda_i2c.c

index 5acb475c10a72360a650ebcfaa0b1dd7cb613226..9a43f563bb9ef0fa244af30148901bb44198a200 100644 (file)
@@ -185,8 +185,12 @@ static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
 {
        struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
 
+       mutex_lock(&tas_priv->codec_lock);
+
        ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return 0;
 }
 
@@ -200,11 +204,15 @@ static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
 
        val = clamp(nr_profile, 0, max);
 
+       mutex_lock(&tas_priv->codec_lock);
+
        if (tas_priv->rcabin.profile_cfg_id != val) {
                tas_priv->rcabin.profile_cfg_id = val;
                ret = 1;
        }
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return ret;
 }
 
@@ -241,8 +249,12 @@ static int tasdevice_program_get(struct snd_kcontrol *kcontrol,
 {
        struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
 
+       mutex_lock(&tas_priv->codec_lock);
+
        ucontrol->value.integer.value[0] = tas_priv->cur_prog;
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return 0;
 }
 
@@ -257,11 +269,15 @@ static int tasdevice_program_put(struct snd_kcontrol *kcontrol,
 
        val = clamp(nr_program, 0, max);
 
+       mutex_lock(&tas_priv->codec_lock);
+
        if (tas_priv->cur_prog != val) {
                tas_priv->cur_prog = val;
                ret = 1;
        }
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return ret;
 }
 
@@ -270,8 +286,12 @@ static int tasdevice_config_get(struct snd_kcontrol *kcontrol,
 {
        struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
 
+       mutex_lock(&tas_priv->codec_lock);
+
        ucontrol->value.integer.value[0] = tas_priv->cur_conf;
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return 0;
 }
 
@@ -286,11 +306,15 @@ static int tasdevice_config_put(struct snd_kcontrol *kcontrol,
 
        val = clamp(nr_config, 0, max);
 
+       mutex_lock(&tas_priv->codec_lock);
+
        if (tas_priv->cur_conf != val) {
                tas_priv->cur_conf = val;
                ret = 1;
        }
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return ret;
 }
 
@@ -300,8 +324,15 @@ static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
        struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
+       int ret;
+
+       mutex_lock(&tas_priv->codec_lock);
+
+       ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc);
+
+       mutex_unlock(&tas_priv->codec_lock);
 
-       return tasdevice_amp_getvol(tas_priv, ucontrol, mc);
+       return ret;
 }
 
 static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
@@ -310,9 +341,16 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
        struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
+       int ret;
+
+       mutex_lock(&tas_priv->codec_lock);
 
        /* The check of the given value is in tasdevice_amp_putvol. */
-       return tasdevice_amp_putvol(tas_priv, ucontrol, mc);
+       ret = tasdevice_amp_putvol(tas_priv, ucontrol, mc);
+
+       mutex_unlock(&tas_priv->codec_lock);
+
+       return ret;
 }
 
 static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
@@ -320,10 +358,14 @@ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
 {
        struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
 
+       mutex_lock(&tas_priv->codec_lock);
+
        ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status;
        dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
                        tas_priv->force_fwload_status ? "ON" : "OFF");
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return 0;
 }
 
@@ -333,6 +375,8 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
        struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
        bool change, val = (bool)ucontrol->value.integer.value[0];
 
+       mutex_lock(&tas_priv->codec_lock);
+
        if (tas_priv->force_fwload_status == val)
                change = false;
        else {
@@ -342,6 +386,8 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
        dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
                tas_priv->force_fwload_status ? "ON" : "OFF");
 
+       mutex_unlock(&tas_priv->codec_lock);
+
        return change;
 }