ALSA: hda - Protect SPDIF-related stuff via spdif_mutex
authorTakashi Iwai <tiwai@suse.de>
Thu, 10 May 2012 08:21:29 +0000 (10:21 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 10 May 2012 12:56:15 +0000 (14:56 +0200)
Add the missing mutex protection or move into the protected part for
SPDIF access codes for codecs.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_hdmi.c

index 731f8500a23ad4f6b2f2871b53ec25c5da4dd09a..5e7c4bf83abef038594eb5dbc2fce66c4ba41991 100644 (file)
@@ -2864,12 +2864,15 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        int idx = kcontrol->private_value;
-       struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+       struct hda_spdif_out *spdif;
 
+       mutex_lock(&codec->spdif_mutex);
+       spdif = snd_array_elem(&codec->spdif_out, idx);
        ucontrol->value.iec958.status[0] = spdif->status & 0xff;
        ucontrol->value.iec958.status[1] = (spdif->status >> 8) & 0xff;
        ucontrol->value.iec958.status[2] = (spdif->status >> 16) & 0xff;
        ucontrol->value.iec958.status[3] = (spdif->status >> 24) & 0xff;
+       mutex_unlock(&codec->spdif_mutex);
 
        return 0;
 }
@@ -2955,12 +2958,14 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        int idx = kcontrol->private_value;
-       struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
-       hda_nid_t nid = spdif->nid;
+       struct hda_spdif_out *spdif;
+       hda_nid_t nid;
        unsigned short val;
        int change;
 
        mutex_lock(&codec->spdif_mutex);
+       spdif = snd_array_elem(&codec->spdif_out, idx);
+       nid = spdif->nid;
        spdif->status = ucontrol->value.iec958.status[0] |
                ((unsigned int)ucontrol->value.iec958.status[1] << 8) |
                ((unsigned int)ucontrol->value.iec958.status[2] << 16) |
@@ -2982,9 +2987,12 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        int idx = kcontrol->private_value;
-       struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+       struct hda_spdif_out *spdif;
 
+       mutex_lock(&codec->spdif_mutex);
+       spdif = snd_array_elem(&codec->spdif_out, idx);
        ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
+       mutex_unlock(&codec->spdif_mutex);
        return 0;
 }
 
@@ -3004,12 +3012,14 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        int idx = kcontrol->private_value;
-       struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
-       hda_nid_t nid = spdif->nid;
+       struct hda_spdif_out *spdif;
+       hda_nid_t nid;
        unsigned short val;
        int change;
 
        mutex_lock(&codec->spdif_mutex);
+       spdif = snd_array_elem(&codec->spdif_out, idx);
+       nid = spdif->nid;
        val = spdif->ctls & ~AC_DIG1_ENABLE;
        if (ucontrol->value.integer.value[0])
                val |= AC_DIG1_ENABLE;
@@ -3097,6 +3107,9 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
 
+/* get the hda_spdif_out entry from the given NID
+ * call within spdif_mutex lock
+ */
 struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
                                               hda_nid_t nid)
 {
@@ -3113,9 +3126,10 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
 
 void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
 {
-       struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+       struct hda_spdif_out *spdif;
 
        mutex_lock(&codec->spdif_mutex);
+       spdif = snd_array_elem(&codec->spdif_out, idx);
        spdif->nid = (u16)-1;
        mutex_unlock(&codec->spdif_mutex);
 }
@@ -3123,10 +3137,11 @@ EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
 
 void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
 {
-       struct hda_spdif_out *spdif = snd_array_elem(&codec->spdif_out, idx);
+       struct hda_spdif_out *spdif;
        unsigned short val;
 
        mutex_lock(&codec->spdif_mutex);
+       spdif = snd_array_elem(&codec->spdif_out, idx);
        if (spdif->nid != nid) {
                spdif->nid = nid;
                val = spdif->ctls;
@@ -4747,11 +4762,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
 {
        const hda_nid_t *nids = mout->dac_nids;
        int chs = substream->runtime->channels;
-       struct hda_spdif_out *spdif =
-                       snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
+       struct hda_spdif_out *spdif;
        int i;
 
        mutex_lock(&codec->spdif_mutex);
+       spdif = snd_hda_spdif_out_of_nid(codec, mout->dig_out_nid);
        if (mout->dig_out_nid && mout->share_spdif &&
            mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
                if (chs == 2 &&
index 83f345f3c961b05313a17e10d9c46d53ace138c7..ad319d4dc32f7e5d0d5265020a0f700c10bb08ab 100644 (file)
@@ -1592,10 +1592,10 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
        unsigned int dataDCC2, channel_id;
        int i;
        struct hdmi_spec *spec = codec->spec;
-       struct hda_spdif_out *spdif =
-               snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
+       struct hda_spdif_out *spdif;
 
        mutex_lock(&codec->spdif_mutex);
+       spdif = snd_hda_spdif_out_of_nid(codec, spec->cvts[0].cvt_nid);
 
        chs = substream->runtime->channels;