At Tue, 9 Oct 2012 19:23:56 +0800, Daniel J Blueman wrote:
On 9 October 2012 18:07, Takashi Iwai tiwai@suse.de wrote:
At Tue, 09 Oct 2012 12:04:08 +0200, Takashi Iwai wrote:
At Tue, 9 Oct 2012 00:34:09 +0800, Daniel J Blueman wrote:
On 8 October 2012 20:58, Takashi Iwai tiwai@suse.de wrote:
At Tue, 25 Sep 2012 13:20:05 +0800, Daniel J Blueman wrote:
On my Macbook with a discrete Nvidia GPU, there is a race between selecting the integrated GPU and putting the discrete GPU into D3 [1], reliably causing a kernel oops [2].
Introducing a delay of ~1s between the calls prevents this. When the second 'OFF' write path executes, it looks like struct azx at card->private_data hasn't yet been allocated yet [3], so there is likely some locking missing.
It's rather pci_get_drvdata() returning NULL (i.e. card is NULL, thus card->private_data causes Oops). Could you check the patch like below and see whether you get a kernel warning (but no Oops) or the problem gets fixed by shifting the assignment of pci drvdata?
[...]
Good patching. Calling pci_set_drvdata later prevents the oops in HDA, though we see unexpected 0x0 responses in the response ring buffer [1], which we don't see when there's a >~1.5s delay between IGD and OFF.
If the previous patch fixed, it means that the switching occurred during the device was being probed. Maybe a better approach to register the VGA switcheroo after the proper initialization.
The patch below is a revised one. Please give it a try.
Also, it's not clear which card spews the spurious response. Apply the patch below in addition.
[...]
hda-intel: 0000:01:00.1: spurious response 0x0:0x0, last cmd=0x1f0004 $ lspci -s :1:0.1 01:00.1 Audio device: NVIDIA Corporation Device 0e1b (rev ff)
It's the NVIDIA device which presumably hasn't completed it's transition to D3 at the time the OFF is executed.
OK, then could you try the patch below on the top of previous two patches?
Takashi
--- diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index f09ff6c..676c64d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2639,13 +2640,13 @@ static void azx_vs_set_state(struct pci_dev *pci, disabled ? "Disabling" : "Enabling", pci_name(chip->pci)); if (disabled) { + snd_hda_lock_devices(chip->bus); azx_suspend(&pci->dev); chip->disabled = true; - snd_hda_lock_devices(chip->bus); } else { - snd_hda_unlock_devices(chip->bus); chip->disabled = false; azx_resume(&pci->dev); + snd_hda_unlock_devices(chip->bus); } } }