summaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorLibin Yang <libin.yang@linux.intel.com>2016-02-19 08:42:06 +0100
committerTakashi Iwai <tiwai@suse.de>2016-02-19 09:06:39 +0100
commit3184270ec188a70df555ab08bca70c0e61704205 (patch)
tree3699aff4a9620c4e1ee5a771bbb0986edb71882e /sound/pci
parentALSA: oxfw: use workqueue instead of tasklet for scs1x (diff)
downloadlinux-3184270ec188a70df555ab08bca70c0e61704205.tar.xz
linux-3184270ec188a70df555ab08bca70c0e61704205.zip
ALSA: hda - hdmi get jack from hda_jack_tbl when not dyn_pcm_assign
On Intel platform, if !dyn_pcm_assign, spec->pcm_rec[].jack is not NULL even after snd_hda_jack_tbl_clear() is called to free snd_jack. This may cause access invalid memory when calling snd_jack_report. Fixes: 25e4abb33df3 ('ALSA: hda - hdmi jack created based on pcm') Signed-off-by: Libin Yang <libin.yang@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_hdmi.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index f4443b5fbf6e..541986f414cb 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1956,6 +1956,29 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
return ret;
}
+static struct snd_jack *pin_idx_to_jack(struct hda_codec *codec,
+ struct hdmi_spec_per_pin *per_pin)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct snd_jack *jack = NULL;
+ struct hda_jack_tbl *jack_tbl;
+
+ /* if !dyn_pcm_assign, get jack from hda_jack_tbl
+ * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
+ * NULL even after snd_hda_jack_tbl_clear() is called to
+ * free snd_jack. This may cause access invalid memory
+ * when calling snd_jack_report
+ */
+ if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign)
+ jack = spec->pcm_rec[per_pin->pcm_idx].jack;
+ else if (!spec->dyn_pcm_assign) {
+ jack_tbl = snd_hda_jack_tbl_get(codec, per_pin->pin_nid);
+ if (jack_tbl)
+ jack = jack_tbl->jack;
+ }
+ return jack;
+}
+
/* update ELD and jack state via audio component */
static void sync_eld_via_acomp(struct hda_codec *codec,
struct hdmi_spec_per_pin *per_pin)
@@ -1989,11 +2012,10 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
/* pcm_idx >=0 before update_eld() means it is in monitor
* disconnected event. Jack must be fetched before update_eld()
*/
- if (per_pin->pcm_idx >= 0)
- jack = spec->pcm_rec[per_pin->pcm_idx].jack;
+ jack = pin_idx_to_jack(codec, per_pin);
update_eld(codec, per_pin, eld);
- if (jack == NULL && per_pin->pcm_idx >= 0)
- jack = spec->pcm_rec[per_pin->pcm_idx].jack;
+ if (jack == NULL)
+ jack = pin_idx_to_jack(codec, per_pin);
if (jack == NULL)
goto unlock;
snd_jack_report(jack,