Skip to content

Commit

Permalink
ALSA: hda - Fix registration race of VGA switcheroo
Browse files Browse the repository at this point in the history
Delay the registration of VGA switcheroo client to the end of the
probing.  Otherwise a too quick switching may result in Oops during
probing.

Also add the check of the return value from snd_hda_lock_devices().

Reported-and-tested-by: Daniel J Blueman <[email protected]>
Cc: <[email protected]> [v3.5+]
Signed-off-by: Takashi Iwai <[email protected]>
  • Loading branch information
tiwai committed Oct 15, 2012
1 parent e73fa21 commit 128960a
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ struct azx {

/* VGA-switcheroo setup */
unsigned int use_vga_switcheroo:1;
unsigned int vga_switcheroo_registered:1;
unsigned int init_failed:1; /* delayed init failed */
unsigned int disabled:1; /* disabled by VGA-switcher */

Expand Down Expand Up @@ -2640,7 +2641,9 @@ static void azx_vs_set_state(struct pci_dev *pci,
if (disabled) {
azx_suspend(&pci->dev);
chip->disabled = true;
snd_hda_lock_devices(chip->bus);
if (snd_hda_lock_devices(chip->bus))
snd_printk(KERN_WARNING SFX
"Cannot lock devices!\n");
} else {
snd_hda_unlock_devices(chip->bus);
chip->disabled = false;
Expand Down Expand Up @@ -2683,14 +2686,20 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {

static int __devinit register_vga_switcheroo(struct azx *chip)
{
int err;

if (!chip->use_vga_switcheroo)
return 0;
/* FIXME: currently only handling DIS controller
* is there any machine with two switchable HDMI audio controllers?
*/
return vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
VGA_SWITCHEROO_DIS,
chip->bus != NULL);
if (err < 0)
return err;
chip->vga_switcheroo_registered = 1;
return 0;
}
#else
#define init_vga_switcheroo(chip) /* NOP */
Expand All @@ -2712,7 +2721,8 @@ static int azx_free(struct azx *chip)
if (use_vga_switcheroo(chip)) {
if (chip->disabled && chip->bus)
snd_hda_unlock_devices(chip->bus);
vga_switcheroo_unregister_client(chip->pci);
if (chip->vga_switcheroo_registered)
vga_switcheroo_unregister_client(chip->pci);
}

if (chip->initialized) {
Expand Down Expand Up @@ -3060,14 +3070,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
}

ok:
err = register_vga_switcheroo(chip);
if (err < 0) {
snd_printk(KERN_ERR SFX
"Error registering VGA-switcheroo client\n");
azx_free(chip);
return err;
}

err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
Expand Down Expand Up @@ -3338,6 +3340,13 @@ static int __devinit azx_probe(struct pci_dev *pci,
if (pci_dev_run_wake(pci))
pm_runtime_put_noidle(&pci->dev);

err = register_vga_switcheroo(chip);
if (err < 0) {
snd_printk(KERN_ERR SFX
"Error registering VGA-switcheroo client\n");
goto out_free;
}

dev++;
return 0;

Expand Down

0 comments on commit 128960a

Please sign in to comment.