diff options
author | Libin Yang <libin.yang@linux.intel.com> | 2016-02-19 15:42:06 +0800 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-02-19 09:06:39 +0100 |
commit | 3184270ec188a70df555ab08bca70c0e61704205 (patch) | |
tree | 3699aff4a9620c4e1ee5a771bbb0986edb71882e /sound/pci/hda/patch_hdmi.c | |
parent | ea7900536775d4bfa0ea83ed677b6a96e29859b5 (diff) | |
download | op-kernel-dev-3184270ec188a70df555ab08bca70c0e61704205.zip op-kernel-dev-3184270ec188a70df555ab08bca70c0e61704205.tar.gz |
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/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index f4443b5..541986f 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, |