linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Karol Herbst <kherbst@redhat.com>
To: Bjorn Helgaas <helgaas@kernel.org>
Cc: nouveau <nouveau@lists.freedesktop.org>,
	Lyude Paul <lyude@redhat.com>,
	linux-pci@vger.kernel.org
Subject: Re: [PATCH v2 4/4] pci: save the boot pcie link speed and restore it on fini
Date: Tue, 21 May 2019 00:30:38 +0200	[thread overview]
Message-ID: <CACO55tsHi+4gRMC=XqOypJttztKNe5oKxxk0eqEVxGZoMzS+4Q@mail.gmail.com> (raw)
In-Reply-To: <20190520211933.GA57618@google.com>

On Mon, May 20, 2019 at 11:20 PM Bjorn Helgaas <helgaas@kernel.org> wrote:
>
> On Tue, May 07, 2019 at 10:12:45PM +0200, Karol Herbst wrote:
> > Apperantly things go south if we suspend the device with a different PCIE
> > link speed set than it got booted with. Fixes runtime suspend on my gp107.
> >
> > This all looks like some bug inside the pci subsystem and I would prefer a
> > fix there instead of nouveau, but maybe there is no real nice way of doing
> > that outside of drivers?
>
> I agree it would be nice to fix this in the PCI core if that's
> feasible.
>
> It looks like this driver changes the PCIe link speed using some
> device-specific mechanism.  When we suspend, we put the device in
> D3cold, so it loses all its state.  When we resume, the link probably
> comes up at the boot speed because nothing did that device-specific
> magic to change it, so you probably end up with the link being slow
> but the driver thinking it's configured to be fast, and maybe that
> combination doesn't work.
>
> If it requires something device-specific to change that link speed, I
> don't know how to put that in the PCI core.  But maybe I'm missing
> something?
>
> Per the PCIe spec (r4.0, sec 1.2):
>
>   Initialization – During hardware initialization, each PCI Express
>   Link is set up following a negotiation of Lane widths and frequency
>   of operation by the two agents at each end of the Link. No firmware
>   or operating system software is involved.
>
> I have been assuming that this means device-specific link speed
> management is out of spec, but it seems pretty common that devices
> don't come up by themselves at the fastest possible link speed.  So
> maybe the spec just intends that devices can operate at *some* valid
> speed.
>

I would expect that devices kind of have to figure out what they can
operate on and the operating system kind of just checks what the
current state is and doesn't try to "restore" the old state or
something?

We don't do anything in the driver after the device was suspended. And
the 0x88000 is a mirror of the PCI config space, but we also got some
PCIe stuff at 0x8c000 which is used by newer GPUs for gen3 stuff
essentially. I have no idea how much of this is part of the actual pci
standard and how much is driver specific. But the driver also wants to
have some control over the link speed as it's tight to performance
states on GPU.

The big issue here is just, that the GPU boots with 8.0, some on-gpu
init mechanism decreases it to 2.5. If we suspend, the GPU or at least
the communication with the controller is broken. But if we set it to
the boot speed, resuming the GPU just works. So my assumption was,
that _something_ (might it be the controller or the pci subsystem)
tries to force to operate on an invalid link speed and because the
bridge controller is actually powered down as well (as all children
are in D3cold) I could imagine that something in the pci subsystem
actually restores the state which lets the controller fail to
establish communication again?

Just something which kind of would make sense to me.

> > v2: squashed together patch 4 and 5
> >
> > Signed-off-by: Karol Herbst <kherbst@redhat.com>
> > Reviewed-by: Lyude Paul <lyude@redhat.com>
> > ---
> >  drm/nouveau/include/nvkm/subdev/pci.h |  5 +++--
> >  drm/nouveau/nvkm/subdev/pci/base.c    |  9 +++++++--
> >  drm/nouveau/nvkm/subdev/pci/pcie.c    | 24 ++++++++++++++++++++----
> >  drm/nouveau/nvkm/subdev/pci/priv.h    |  2 ++
> >  4 files changed, 32 insertions(+), 8 deletions(-)
> >
> > diff --git a/drm/nouveau/include/nvkm/subdev/pci.h b/drm/nouveau/include/nvkm/subdev/pci.h
> > index 1fdf3098..b23793a2 100644
> > --- a/drm/nouveau/include/nvkm/subdev/pci.h
> > +++ b/drm/nouveau/include/nvkm/subdev/pci.h
> > @@ -26,8 +26,9 @@ struct nvkm_pci {
> >       } agp;
> >
> >       struct {
> > -             enum nvkm_pcie_speed speed;
> > -             u8 width;
> > +             enum nvkm_pcie_speed cur_speed;
> > +             enum nvkm_pcie_speed def_speed;
> > +             u8 cur_width;
> >       } pcie;
> >
> >       bool msi;
> > diff --git a/drm/nouveau/nvkm/subdev/pci/base.c b/drm/nouveau/nvkm/subdev/pci/base.c
> > index ee2431a7..d9fb5a83 100644
> > --- a/drm/nouveau/nvkm/subdev/pci/base.c
> > +++ b/drm/nouveau/nvkm/subdev/pci/base.c
> > @@ -90,6 +90,8 @@ nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend)
> >
> >       if (pci->agp.bridge)
> >               nvkm_agp_fini(pci);
> > +     else if (pci_is_pcie(pci->pdev))
> > +             nvkm_pcie_fini(pci);
> >
> >       return 0;
> >  }
> > @@ -100,6 +102,8 @@ nvkm_pci_preinit(struct nvkm_subdev *subdev)
> >       struct nvkm_pci *pci = nvkm_pci(subdev);
> >       if (pci->agp.bridge)
> >               nvkm_agp_preinit(pci);
> > +     else if (pci_is_pcie(pci->pdev))
> > +             nvkm_pcie_preinit(pci);
> >       return 0;
> >  }
> >
> > @@ -193,8 +197,9 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device,
> >       pci->func = func;
> >       pci->pdev = device->func->pci(device)->pdev;
> >       pci->irq = -1;
> > -     pci->pcie.speed = -1;
> > -     pci->pcie.width = -1;
> > +     pci->pcie.cur_speed = -1;
> > +     pci->pcie.def_speed = -1;
> > +     pci->pcie.cur_width = -1;
> >
> >       if (device->type == NVKM_DEVICE_AGP)
> >               nvkm_agp_ctor(pci);
> > diff --git a/drm/nouveau/nvkm/subdev/pci/pcie.c b/drm/nouveau/nvkm/subdev/pci/pcie.c
> > index 70ccbe0d..731dd30e 100644
> > --- a/drm/nouveau/nvkm/subdev/pci/pcie.c
> > +++ b/drm/nouveau/nvkm/subdev/pci/pcie.c
> > @@ -85,6 +85,13 @@ nvkm_pcie_oneinit(struct nvkm_pci *pci)
> >       return 0;
> >  }
> >
> > +int
> > +nvkm_pcie_preinit(struct nvkm_pci *pci)
> > +{
> > +     pci->pcie.def_speed = nvkm_pcie_get_speed(pci);
> > +     return 0;
> > +}
> > +
> >  int
> >  nvkm_pcie_init(struct nvkm_pci *pci)
> >  {
> > @@ -105,12 +112,21 @@ nvkm_pcie_init(struct nvkm_pci *pci)
> >       if (pci->func->pcie.init)
> >               pci->func->pcie.init(pci);
> >
> > -     if (pci->pcie.speed != -1)
> > -             nvkm_pcie_set_link(pci, pci->pcie.speed, pci->pcie.width);
> > +     if (pci->pcie.cur_speed != -1)
> > +             nvkm_pcie_set_link(pci, pci->pcie.cur_speed,
> > +                                pci->pcie.cur_width);
> >
> >       return 0;
> >  }
> >
> > +int
> > +nvkm_pcie_fini(struct nvkm_pci *pci)
> > +{
> > +     if (!IS_ERR_VALUE(pci->pcie.def_speed))
> > +             return nvkm_pcie_set_link(pci, pci->pcie.def_speed, 16);
> > +     return 0;
> > +}
> > +
> >  int
> >  nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
> >  {
> > @@ -146,8 +162,8 @@ nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
> >               speed = max_speed;
> >       }
> >
> > -     pci->pcie.speed = speed;
> > -     pci->pcie.width = width;
> > +     pci->pcie.cur_speed = speed;
> > +     pci->pcie.cur_width = width;
> >
> >       if (speed == cur_speed) {
> >               nvkm_debug(subdev, "requested matches current speed\n");
> > diff --git a/drm/nouveau/nvkm/subdev/pci/priv.h b/drm/nouveau/nvkm/subdev/pci/priv.h
> > index a0d4c007..e7744671 100644
> > --- a/drm/nouveau/nvkm/subdev/pci/priv.h
> > +++ b/drm/nouveau/nvkm/subdev/pci/priv.h
> > @@ -60,5 +60,7 @@ enum nvkm_pcie_speed gk104_pcie_max_speed(struct nvkm_pci *);
> >  int gk104_pcie_version_supported(struct nvkm_pci *);
> >
> >  int nvkm_pcie_oneinit(struct nvkm_pci *);
> > +int nvkm_pcie_preinit(struct nvkm_pci *);
> >  int nvkm_pcie_init(struct nvkm_pci *);
> > +int nvkm_pcie_fini(struct nvkm_pci *);
> >  #endif
> > --
> > 2.21.0
> >

  reply	other threads:[~2019-05-20 22:30 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-07 20:12 [PATCH v2 0/4] Potential fix for runpm issues on various laptops Karol Herbst
2019-05-07 20:12 ` [PATCH v2 1/4] drm: don't set the pci power state if the pci subsystem handles the ACPI bits Karol Herbst
2019-05-08 19:10   ` Lyude Paul
2019-05-07 20:12 ` [PATCH v2 2/4] pci: enable pcie link changes for pascal Karol Herbst
2019-05-20 21:25   ` Bjorn Helgaas
2019-05-07 20:12 ` [PATCH v2 3/4] pci: add nvkm_pcie_get_speed Karol Herbst
2019-05-07 20:12 ` [PATCH v2 4/4] pci: save the boot pcie link speed and restore it on fini Karol Herbst
2019-05-20 21:19   ` Bjorn Helgaas
2019-05-20 22:30     ` Karol Herbst [this message]
2019-05-21 13:10       ` Bjorn Helgaas
2019-05-21 13:28         ` Karol Herbst
2019-05-21 13:50           ` [Nouveau] " Ilia Mirkin
2019-05-21 13:56             ` Karol Herbst
2019-05-21 14:13           ` Bjorn Helgaas
2019-05-21 14:30             ` Karol Herbst
2019-05-21 17:35               ` Karol Herbst
2019-05-21 17:48                 ` Karol Herbst
2019-06-03 13:18                   ` Karol Herbst
2019-06-03 18:10                     ` Bjorn Helgaas
2019-06-19 12:07                       ` Karol Herbst
2019-06-19 12:12                         ` Karol Herbst
2019-06-24 15:04                           ` Karol Herbst
2019-05-20 13:23 ` [PATCH v2 0/4] Potential fix for runpm issues on various laptops Karol Herbst

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CACO55tsHi+4gRMC=XqOypJttztKNe5oKxxk0eqEVxGZoMzS+4Q@mail.gmail.com' \
    --to=kherbst@redhat.com \
    --cc=helgaas@kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=nouveau@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).