summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-10-29 16:41:20 -0400
committerTakashi Iwai <tiwai@suse.de>2019-10-30 10:32:37 -0400
commit302d5a80d232134246032bc4263fd7facdddb8f1 (patch)
treeb36a354c7572ab6773c0f19c968044af9955eed6
parent1a7f60b9df614bb36d14dc0c0bc898a31b2b506f (diff)
ALSA: hda - Fix mutex deadlock in HDMI codec driver
The commit ade49db337a9 ("ALSA: hda/hdmi - Allow audio component for AMD/ATI and Nvidia HDMI") introduced the spec->pcm_lock mutex lock to the whole generic_hdmi_init() function for avoiding the race with the audio component registration. However, this caused a dead lock when the unsolicited event is handled without the audio component, as the codec gets runtime-resumed in hdmi_present_sense() which is already inside the spec->pcm_lock in its caller. For avoiding this deadlock, add a new mutex only for the audio component binding that is used in both generic_hdmi_init() and the audio notifier registration where the jack callbacks are handled / re-registered. Fixes: ade49db337a9 ("ALSA: hda/hdmi - Allow audio component for AMD/ATI and Nvidia HDMI") Reported-and-tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://lore.kernel.org/r/s5himo7i89i.wl-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/patch_hdmi.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 795cbda32cbb..b72553710ffb 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -145,6 +145,7 @@ struct hdmi_spec {
145 struct snd_array pins; /* struct hdmi_spec_per_pin */ 145 struct snd_array pins; /* struct hdmi_spec_per_pin */
146 struct hdmi_pcm pcm_rec[16]; 146 struct hdmi_pcm pcm_rec[16];
147 struct mutex pcm_lock; 147 struct mutex pcm_lock;
148 struct mutex bind_lock; /* for audio component binding */
148 /* pcm_bitmap means which pcms have been assigned to pins*/ 149 /* pcm_bitmap means which pcms have been assigned to pins*/
149 unsigned long pcm_bitmap; 150 unsigned long pcm_bitmap;
150 int pcm_used; /* counter of pcm_rec[] */ 151 int pcm_used; /* counter of pcm_rec[] */
@@ -2258,7 +2259,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
2258 struct hdmi_spec *spec = codec->spec; 2259 struct hdmi_spec *spec = codec->spec;
2259 int pin_idx; 2260 int pin_idx;
2260 2261
2261 mutex_lock(&spec->pcm_lock); 2262 mutex_lock(&spec->bind_lock);
2262 spec->use_jack_detect = !codec->jackpoll_interval; 2263 spec->use_jack_detect = !codec->jackpoll_interval;
2263 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { 2264 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
2264 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); 2265 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -2275,7 +2276,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
2275 snd_hda_jack_detect_enable_callback(codec, pin_nid, 2276 snd_hda_jack_detect_enable_callback(codec, pin_nid,
2276 jack_callback); 2277 jack_callback);
2277 } 2278 }
2278 mutex_unlock(&spec->pcm_lock); 2279 mutex_unlock(&spec->bind_lock);
2279 return 0; 2280 return 0;
2280} 2281}
2281 2282
@@ -2382,6 +2383,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec)
2382 spec->ops = generic_standard_hdmi_ops; 2383 spec->ops = generic_standard_hdmi_ops;
2383 spec->dev_num = 1; /* initialize to 1 */ 2384 spec->dev_num = 1; /* initialize to 1 */
2384 mutex_init(&spec->pcm_lock); 2385 mutex_init(&spec->pcm_lock);
2386 mutex_init(&spec->bind_lock);
2385 snd_hdac_register_chmap_ops(&codec->core, &spec->chmap); 2387 snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);
2386 2388
2387 spec->chmap.ops.get_chmap = hdmi_get_chmap; 2389 spec->chmap.ops.get_chmap = hdmi_get_chmap;
@@ -2451,7 +2453,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
2451 int i; 2453 int i;
2452 2454
2453 spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops); 2455 spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops);
2454 mutex_lock(&spec->pcm_lock); 2456 mutex_lock(&spec->bind_lock);
2455 spec->use_acomp_notifier = use_acomp; 2457 spec->use_acomp_notifier = use_acomp;
2456 spec->codec->relaxed_resume = use_acomp; 2458 spec->codec->relaxed_resume = use_acomp;
2457 /* reprogram each jack detection logic depending on the notifier */ 2459 /* reprogram each jack detection logic depending on the notifier */
@@ -2461,7 +2463,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
2461 get_pin(spec, i)->pin_nid, 2463 get_pin(spec, i)->pin_nid,
2462 use_acomp); 2464 use_acomp);
2463 } 2465 }
2464 mutex_unlock(&spec->pcm_lock); 2466 mutex_unlock(&spec->bind_lock);
2465} 2467}
2466 2468
2467/* enable / disable the notifier via master bind / unbind */ 2469/* enable / disable the notifier via master bind / unbind */