ALSA: hda - Fix registration race of VGA switcheroo
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 <daniel@quora.org> Cc: <stable@vger.kernel.org> [v3.5+] Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
e73fa21b4e
commit
128960a9ad
|
@ -501,6 +501,7 @@ struct azx {
|
||||||
|
|
||||||
/* VGA-switcheroo setup */
|
/* VGA-switcheroo setup */
|
||||||
unsigned int use_vga_switcheroo:1;
|
unsigned int use_vga_switcheroo:1;
|
||||||
|
unsigned int vga_switcheroo_registered:1;
|
||||||
unsigned int init_failed:1; /* delayed init failed */
|
unsigned int init_failed:1; /* delayed init failed */
|
||||||
unsigned int disabled:1; /* disabled by VGA-switcher */
|
unsigned int disabled:1; /* disabled by VGA-switcher */
|
||||||
|
|
||||||
|
@ -2640,7 +2641,9 @@ static void azx_vs_set_state(struct pci_dev *pci,
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
azx_suspend(&pci->dev);
|
azx_suspend(&pci->dev);
|
||||||
chip->disabled = true;
|
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 {
|
} else {
|
||||||
snd_hda_unlock_devices(chip->bus);
|
snd_hda_unlock_devices(chip->bus);
|
||||||
chip->disabled = false;
|
chip->disabled = false;
|
||||||
|
@ -2683,14 +2686,20 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
|
||||||
|
|
||||||
static int __devinit register_vga_switcheroo(struct azx *chip)
|
static int __devinit register_vga_switcheroo(struct azx *chip)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
if (!chip->use_vga_switcheroo)
|
if (!chip->use_vga_switcheroo)
|
||||||
return 0;
|
return 0;
|
||||||
/* FIXME: currently only handling DIS controller
|
/* FIXME: currently only handling DIS controller
|
||||||
* is there any machine with two switchable HDMI audio controllers?
|
* 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,
|
VGA_SWITCHEROO_DIS,
|
||||||
chip->bus != NULL);
|
chip->bus != NULL);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
chip->vga_switcheroo_registered = 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define init_vga_switcheroo(chip) /* NOP */
|
#define init_vga_switcheroo(chip) /* NOP */
|
||||||
|
@ -2712,7 +2721,8 @@ static int azx_free(struct azx *chip)
|
||||||
if (use_vga_switcheroo(chip)) {
|
if (use_vga_switcheroo(chip)) {
|
||||||
if (chip->disabled && chip->bus)
|
if (chip->disabled && chip->bus)
|
||||||
snd_hda_unlock_devices(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) {
|
if (chip->initialized) {
|
||||||
|
@ -3060,14 +3070,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
|
||||||
}
|
}
|
||||||
|
|
||||||
ok:
|
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);
|
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
|
snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
|
||||||
|
@ -3338,6 +3340,13 @@ static int __devinit azx_probe(struct pci_dev *pci,
|
||||||
if (pci_dev_run_wake(pci))
|
if (pci_dev_run_wake(pci))
|
||||||
pm_runtime_put_noidle(&pci->dev);
|
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++;
|
dev++;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue