Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: hda - Fix inconsistent monitor_present state until repoll

While the previous commit fixed the missing monitor_present flag
update, it may be still in an inconsistent state while the driver
repolls: the flag itself is updated, but the eld_valid flag and the
contents don't follow until the repoll finishes (and may be repeated
for a few times).

The basic problem is that pin_eld->monitor_present is updated in the
caller side. This should have been updated only in update_eld(). So,
the proper fix is to avoid accessing pin_eld but only spec->temp_eld.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

+4 -7
+4 -7
sound/pci/hda/patch_hdmi.c
··· 1396 1396 struct hda_codec *codec = per_pin->codec; 1397 1397 struct hdmi_spec *spec = codec->spec; 1398 1398 struct hdmi_eld *eld = &spec->temp_eld; 1399 - struct hdmi_eld *pin_eld = &per_pin->sink_eld; 1400 1399 hda_nid_t pin_nid = per_pin->pin_nid; 1401 1400 /* 1402 1401 * Always execute a GetPinSense verb here, even when called from ··· 1412 1413 present = snd_hda_pin_sense(codec, pin_nid); 1413 1414 1414 1415 mutex_lock(&per_pin->lock); 1415 - pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); 1416 - eld->monitor_present = pin_eld->monitor_present; 1417 - 1418 - if (pin_eld->monitor_present) 1416 + eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); 1417 + if (eld->monitor_present) 1419 1418 eld->eld_valid = !!(present & AC_PINSENSE_ELDV); 1420 1419 else 1421 1420 eld->eld_valid = false; 1422 1421 1423 1422 codec_dbg(codec, 1424 1423 "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", 1425 - codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid); 1424 + codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); 1426 1425 1427 1426 if (eld->eld_valid) { 1428 1427 if (spec->ops.pin_get_eld(codec, pin_nid, eld->eld_buffer, ··· 1440 1443 else 1441 1444 update_eld(codec, per_pin, eld); 1442 1445 1443 - ret = !repoll || !pin_eld->monitor_present || pin_eld->eld_valid; 1446 + ret = !repoll || !eld->monitor_present || eld->eld_valid; 1444 1447 1445 1448 jack = snd_hda_jack_tbl_get(codec, pin_nid); 1446 1449 if (jack)