At Wed, 12 Mar 2014 11:29:38 +0100,
Jiri Slaby wrote:
> 
> From: Takashi Iwai <ti...@suse.de>
> 
> This patch has been added to the 3.12 stable tree. If you have any
> objections, please let us know.
> 
> ===============
> 
> commit cbbaa603a03cc46681e24d6b2804b62fde95a2af upstream.
> 
> Some per_pin fields and ELD contents might be changed dynamically in
> multiple ways where the concurrent accesses are still opened in the
> current code.  This patch fixes such possible races by using eld->lock
> in appropriate places.
> 
> Reported-by: Anssi Hannula <anssi.hann...@iki.fi>
> Signed-off-by: Takashi Iwai <ti...@suse.de>
> Signed-off-by: Jiri Slaby <jsl...@suse.cz>

This alone leads to a mutex deadlock, and it needs a few more series
of enhancements and fixes.  So, either take the whole patches or drop
this.

a4e9a38b40a0e2f7dad1a0b355896d23fbdd16e0
  ALSA: hda - Move mutex from hda_eld to per_pin in HDMI codec driver
b55447a7301b12d509df4b2909ed38d125ad83d4
  ALSA: hda - Fix typos in patch_hdmi.c
da4a7a3926d09c13ae052ede67feb7285e01e3f5
  ALSA: hda - Explicitly keep codec powered up in hdmi_present_sense


Takashi

> ---
>  sound/pci/hda/patch_hdmi.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
> index 9d1b4589c21b..f576bd6f541d 100644
> --- a/sound/pci/hda/patch_hdmi.c
> +++ b/sound/pci/hda/patch_hdmi.c
> @@ -1365,6 +1365,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin 
> *per_pin, int repoll)
>       bool update_eld = false;
>       bool eld_changed = false;
>  
> +     mutex_lock(&pin_eld->lock);
>       pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
>       if (pin_eld->monitor_present)
>               eld->eld_valid  = !!(present & AC_PINSENSE_ELDV);
> @@ -1394,11 +1395,10 @@ static void hdmi_present_sense(struct 
> hdmi_spec_per_pin *per_pin, int repoll)
>                       queue_delayed_work(codec->bus->workq,
>                                          &per_pin->work,
>                                          msecs_to_jiffies(300));
> -                     return;
> +                     goto unlock;
>               }
>       }
>  
> -     mutex_lock(&pin_eld->lock);
>       if (pin_eld->eld_valid && !eld->eld_valid) {
>               update_eld = true;
>               eld_changed = true;
> @@ -1423,12 +1423,13 @@ static void hdmi_present_sense(struct 
> hdmi_spec_per_pin *per_pin, int repoll)
>                       hdmi_setup_audio_infoframe(codec, per_pin,
>                                                  per_pin->non_pcm);
>       }
> -     mutex_unlock(&pin_eld->lock);
>  
>       if (eld_changed)
>               snd_ctl_notify(codec->bus->card,
>                              SNDRV_CTL_EVENT_MASK_VALUE | 
> SNDRV_CTL_EVENT_MASK_INFO,
>                              &per_pin->eld_ctl->id);
> + unlock:
> +     mutex_unlock(&pin_eld->lock);
>  }
>  
>  static void hdmi_repoll_eld(struct work_struct *work)
> @@ -1600,10 +1601,12 @@ static int generic_hdmi_playback_pcm_prepare(struct 
> hda_pcm_stream *hinfo,
>       int pinctl;
>  
>       non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
> +     mutex_lock(&per_pin->sink_eld.lock);
>       per_pin->channels = substream->runtime->channels;
>       per_pin->setup = true;
>  
>       hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
> +     mutex_unlock(&per_pin->sink_eld.lock);
>  
>       if (spec->dyn_pin_out) {
>               pinctl = snd_hda_codec_read(codec, pin_nid, 0,
> @@ -1658,11 +1661,14 @@ static int hdmi_pcm_close(struct hda_pcm_stream 
> *hinfo,
>               }
>  
>               snd_hda_spdif_ctls_unassign(codec, pin_idx);
> +
> +             mutex_lock(&per_pin->sink_eld.lock);
>               per_pin->chmap_set = false;
>               memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
>  
>               per_pin->setup = false;
>               per_pin->channels = 0;
> +             mutex_unlock(&per_pin->sink_eld.lock);
>       }
>  
>       return 0;
> @@ -1791,10 +1797,12 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol 
> *kcontrol,
>       ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
>       if (ca < 0)
>               return -EINVAL;
> +     mutex_lock(&per_pin->sink_eld.lock);
>       per_pin->chmap_set = true;
>       memcpy(per_pin->chmap, chmap, sizeof(chmap));
>       if (prepared)
>               hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
> +     mutex_unlock(&per_pin->sink_eld.lock);
>  
>       return 0;
>  }
> -- 
> 1.9.0
> 
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to