Re: [patch added to the 3.12 stable tree] ALSA: hda - Fix possible races in HDMI driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



At Wed, 12 Mar 2014 11:29:38 +0100,
Jiri Slaby wrote:
> 
> From: Takashi Iwai <tiwai@xxxxxxx>
> 
> 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.hannula@xxxxxx>
> Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
> Signed-off-by: Jiri Slaby <jslaby@xxxxxxx>

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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]