On Sat, Mar 21, 2020 at 2:02 AM Karol Herbst <kherbst@xxxxxxxxxx> wrote: > > On Fri, Mar 20, 2020 at 11:19 PM Bjorn Helgaas <helgaas@xxxxxxxxxx> wrote: > > > > On Tue, Mar 10, 2020 at 08:26:27PM +0100, Karol Herbst wrote: > > > Fixes the infamous 'runtime PM' bug many users are facing on Laptops with > > > Nvidia Pascal GPUs by skipping said PCI power state changes on the GPU. > > > > > > Depending on the used kernel there might be messages like those in demsg: > > > > > > "nouveau 0000:01:00.0: Refused to change power state, currently in D3" > > > "nouveau 0000:01:00.0: can't change power state from D3cold to D0 (config > > > space inaccessible)" > > > followed by backtraces of kernel crashes or timeouts within nouveau. > > > > > > It's still unkown why this issue exists, but this is a reliable workaround > > > and solves a very annoying issue for user having to choose between a > > > crashing kernel or higher power consumption of their Laptops. > > > > Thanks for the bugzilla link. The bugzilla mentions lots of mailing > > list discussion. Can you include links to some of that? > > > > IIUC this basically just turns off PCI power management for the GPU. > > Can you do that with something like the following? I don't know > > anything about DRM, so I don't know where you could save the pm_cap, > > but I'm sure the driver could keep it somewhere. > > > > Sure this would work? From a quick look over the pci code, it looks > like a of code would be skipped we really need, like the platform code > to turn off the GPU via ACPI. But I could also remember incorrectly on > how all of that worked again. I can of course try and see what the > effect of this patch would be. And would the parent bus even go into > D3hot if it knows one of its children is still at D0? Because that's > what the result of that would be as well, no? And I know that if the > bus stays in D0, that it has a negative impact on power consumption. > > Anyway, I will try that out, I am just not seeing how that would help. > so it seems like that has worked unless I screwed up locally. Will do some proper testing and then I think we won't need to go through the pci tree anymore as no changes are required there with that. > > > > diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c > > index b65ae817eabf..2ad825e8891c 100644 > > --- a/drivers/gpu/drm/nouveau/nouveau_drm.c > > +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c > > @@ -618,6 +618,23 @@ nouveau_drm_device_fini(struct drm_device *dev) > > kfree(drm); > > } > > > > +static void quirk_broken_nv_runpm(struct drm_device *drm_dev) > > +{ > > + struct pci_dev *pdev = drm_dev->pdev; > > + struct pci_dev *bridge = pci_upstream_bridge(pdev); > > + > > + if (!bridge || bridge->vendor != PCI_VENDOR_ID_INTEL) > > + return; > > + > > + switch (bridge->device) { > > + case 0x1901: > > + STASH->pm_cap = pdev->pm_cap; > > + pdev->pm_cap = 0; > > + NV_INFO(drm_dev, "Disabling PCI power management to avoid bug\n"); > > + break; > > + } > > +} > > + > > static int nouveau_drm_probe(struct pci_dev *pdev, > > const struct pci_device_id *pent) > > { > > @@ -699,6 +716,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev, > > if (ret) > > goto fail_drm_dev_init; > > > > + quirk_broken_nv_runpm(drm_dev); > > return 0; > > > > fail_drm_dev_init: > > @@ -735,6 +753,9 @@ nouveau_drm_remove(struct pci_dev *pdev) > > { > > struct drm_device *dev = pci_get_drvdata(pdev); > > > > + /* If we disabled PCI power management, restore it */ > > + if (STASH->pm_cap) > > + pdev->pm_cap = STASH->pm_cap; > > nouveau_drm_device_remove(dev); > > pci_disable_device(pdev); > > } > >