Message ID | 20240710205838.2413465-3-superm1@kernel.org (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Bjorn Helgaas |
Headers | show |
Series | Verify devices transition from D3cold to D0 | expand |
On Wed, 10 Jul 2024, superm1@kernel.org wrote: > From: Mario Limonciello <mario.limonciello@amd.com> > > It is reported that USB4 routers and downstream devices may behave > incorrectly if a dock cable is plugged in at approximately the time that > the autosuspend_delay is configured. In this situation the device has > attempted to enter D3cold, but didn't finish D3cold entry when the PCI > core tried to transition it back to D0. > > Empirically measuring this situation an "aborted" D3cold exit takes > ~60ms and a "normal" D3cold exit takes ~10ms. > > The PCI-PM 1.2 spec specifies that the restore time for functions > in D3cold is either 'Full context restore or boot latency'. > > As PCIe r6.0 sec 5.8 specifies that the device will have gone > through a conventional reset it may take some time for the I'd add comma after reset. The code change looks okay though, Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> > device to be ready. > > Wait up to 1 sec as specified in PCIe r6.0 sec 6.6.1 for a device > in D3cold to return to D0. > > Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> > --- > drivers/pci/pci.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 4ad02ad640518..9af324ab6bb02 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -1388,6 +1388,17 @@ int pci_power_up(struct pci_dev *dev) > else if (state == PCI_D2) > udelay(PCI_PM_D2_DELAY); > > + /* > + * D3cold -> D0 will have gone through a conventional reset and may need > + * time to be ready. > + */ > + if (dev->current_state == PCI_D3cold) { > + int ret; > + > + ret = pci_dev_wait(dev, "D3cold->D0", PCI_RESET_WAIT); > + if (ret) > + return ret; > + } > end: > dev->current_state = PCI_D0; > if (need_restore) >
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4ad02ad640518..9af324ab6bb02 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1388,6 +1388,17 @@ int pci_power_up(struct pci_dev *dev) else if (state == PCI_D2) udelay(PCI_PM_D2_DELAY); + /* + * D3cold -> D0 will have gone through a conventional reset and may need + * time to be ready. + */ + if (dev->current_state == PCI_D3cold) { + int ret; + + ret = pci_dev_wait(dev, "D3cold->D0", PCI_RESET_WAIT); + if (ret) + return ret; + } end: dev->current_state = PCI_D0; if (need_restore)