aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-12-04 09:09:23 -0500
committerTakashi Iwai <tiwai@suse.de>2012-12-04 10:00:40 -0500
commitf4c482a4d0b3407cffaa79ef1c516bd5fe1dba13 (patch)
tree12a5690a8778b18f381536be1773ad71fb101cba /sound
parent0d9741c0e058e2857fe3fed37975515dc8dcd21d (diff)
ALSA: hda - Fix yet another race of vga_switcheroo registration
The recent fix for vga switcheroo race in commit 128960a9 opened yet another race. At the time the audio driver starts probing, user may turn off D-GPU off. But at this moment, the audio driver still doesn't register the vga switcheroo client, thus the switching isn't notified. Then the hardware gets off out of sudden, resulting in invalid reads and lots of "spurious response" error messages. For solving this situation, the following changes have been done in this patch: - Move again vga switcheroo registration to the very early stage of the probing; this also requires to set pci drvdata properly before registration - Introduce the completion to synchronize the driver probe at vga switcheroo callbacks; this assures that the whole probing finished before executing the callbacks Reported-by: Daniel J Blueman <daniel@quora.org> Tested-by: Daniel J Blueman <daniel@quora.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_intel.c61
1 files changed, 32 insertions, 29 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 4bb52da3ace9..22ecadcf22dd 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -49,6 +49,7 @@
49#include <linux/pm_runtime.h> 49#include <linux/pm_runtime.h>
50#include <linux/clocksource.h> 50#include <linux/clocksource.h>
51#include <linux/time.h> 51#include <linux/time.h>
52#include <linux/completion.h>
52 53
53#ifdef CONFIG_X86 54#ifdef CONFIG_X86
54/* for snoop control */ 55/* for snoop control */
@@ -469,6 +470,7 @@ struct azx {
469 /* locks */ 470 /* locks */
470 spinlock_t reg_lock; 471 spinlock_t reg_lock;
471 struct mutex open_mutex; 472 struct mutex open_mutex;
473 struct completion probe_wait;
472 474
473 /* streams (x num_streams) */ 475 /* streams (x num_streams) */
474 struct azx_dev *azx_dev; 476 struct azx_dev *azx_dev;
@@ -2745,6 +2747,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
2745 struct azx *chip = card->private_data; 2747 struct azx *chip = card->private_data;
2746 bool disabled; 2748 bool disabled;
2747 2749
2750 wait_for_completion(&chip->probe_wait);
2748 if (chip->init_failed) 2751 if (chip->init_failed)
2749 return; 2752 return;
2750 2753
@@ -2790,6 +2793,7 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
2790 struct snd_card *card = pci_get_drvdata(pci); 2793 struct snd_card *card = pci_get_drvdata(pci);
2791 struct azx *chip = card->private_data; 2794 struct azx *chip = card->private_data;
2792 2795
2796 wait_for_completion(&chip->probe_wait);
2793 if (chip->init_failed) 2797 if (chip->init_failed)
2794 return false; 2798 return false;
2795 if (chip->disabled || !chip->bus) 2799 if (chip->disabled || !chip->bus)
@@ -2851,6 +2855,9 @@ static int azx_free(struct azx *chip)
2851 2855
2852 azx_notifier_unregister(chip); 2856 azx_notifier_unregister(chip);
2853 2857
2858 chip->init_failed = 1; /* to be sure */
2859 complete(&chip->probe_wait);
2860
2854 if (use_vga_switcheroo(chip)) { 2861 if (use_vga_switcheroo(chip)) {
2855 if (chip->disabled && chip->bus) 2862 if (chip->disabled && chip->bus)
2856 snd_hda_unlock_devices(chip->bus); 2863 snd_hda_unlock_devices(chip->bus);
@@ -3156,6 +3163,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
3156 INIT_LIST_HEAD(&chip->pcm_list); 3163 INIT_LIST_HEAD(&chip->pcm_list);
3157 INIT_LIST_HEAD(&chip->list); 3164 INIT_LIST_HEAD(&chip->list);
3158 init_vga_switcheroo(chip); 3165 init_vga_switcheroo(chip);
3166 init_completion(&chip->probe_wait);
3159 3167
3160 chip->position_fix[0] = chip->position_fix[1] = 3168 chip->position_fix[0] = chip->position_fix[1] =
3161 check_position_fix(chip, position_fix[dev]); 3169 check_position_fix(chip, position_fix[dev]);
@@ -3183,26 +3191,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
3183 } 3191 }
3184 } 3192 }
3185 3193
3186 if (check_hdmi_disabled(pci)) {
3187 snd_printk(KERN_INFO SFX "VGA controller for %s is disabled\n",
3188 pci_name(pci));
3189 if (use_vga_switcheroo(chip)) {
3190 snd_printk(KERN_INFO SFX "Delaying initialization\n");
3191 chip->disabled = true;
3192 goto ok;
3193 }
3194 kfree(chip);
3195 pci_disable_device(pci);
3196 return -ENXIO;
3197 }
3198
3199 err = azx_first_init(chip);
3200 if (err < 0) {
3201 azx_free(chip);
3202 return err;
3203 }
3204
3205 ok:
3206 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); 3194 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
3207 if (err < 0) { 3195 if (err < 0) {
3208 snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); 3196 snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
@@ -3447,7 +3435,29 @@ static int __devinit azx_probe(struct pci_dev *pci,
3447 if (err < 0) 3435 if (err < 0)
3448 goto out_free; 3436 goto out_free;
3449 card->private_data = chip; 3437 card->private_data = chip;
3438
3439 pci_set_drvdata(pci, card);
3440
3441 err = register_vga_switcheroo(chip);
3442 if (err < 0) {
3443 snd_printk(KERN_ERR SFX
3444 "Error registering VGA-switcheroo client\n");
3445 goto out_free;
3446 }
3447
3448 if (check_hdmi_disabled(pci)) {
3449 snd_printk(KERN_INFO SFX "VGA controller for %s is disabled\n",
3450 pci_name(pci));
3451 snd_printk(KERN_INFO SFX "Delaying initialization\n");
3452 chip->disabled = true;
3453 }
3454
3450 probe_now = !chip->disabled; 3455 probe_now = !chip->disabled;
3456 if (probe_now) {
3457 err = azx_first_init(chip);
3458 if (err < 0)
3459 goto out_free;
3460 }
3451 3461
3452#ifdef CONFIG_SND_HDA_PATCH_LOADER 3462#ifdef CONFIG_SND_HDA_PATCH_LOADER
3453 if (patch[dev] && *patch[dev]) { 3463 if (patch[dev] && *patch[dev]) {
@@ -3468,23 +3478,16 @@ static int __devinit azx_probe(struct pci_dev *pci,
3468 goto out_free; 3478 goto out_free;
3469 } 3479 }
3470 3480
3471 pci_set_drvdata(pci, card);
3472
3473 if (pci_dev_run_wake(pci)) 3481 if (pci_dev_run_wake(pci))
3474 pm_runtime_put_noidle(&pci->dev); 3482 pm_runtime_put_noidle(&pci->dev);
3475 3483
3476 err = register_vga_switcheroo(chip);
3477 if (err < 0) {
3478 snd_printk(KERN_ERR SFX
3479 "Error registering VGA-switcheroo client\n");
3480 goto out_free;
3481 }
3482
3483 dev++; 3484 dev++;
3485 complete(&chip->probe_wait);
3484 return 0; 3486 return 0;
3485 3487
3486out_free: 3488out_free:
3487 snd_card_free(card); 3489 snd_card_free(card);
3490 pci_set_drvdata(pci, NULL);
3488 return err; 3491 return err;
3489} 3492}
3490 3493