At Wed, 12 Mar 2014 11:29:38 +0100,
Jiri Slaby wrote:
>
> From: Takashi Iwai <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Takashi Iwai <[email protected]>
> Signed-off-by: Jiri Slaby <[email protected]>
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html