Commit 3e347969 authored by Sajid Dalvi's avatar Sajid Dalvi Committed by Bjorn Helgaas

PCI/PM: Reduce D3hot delay with usleep_range()

PCIe r6.0, sec 5.9, requires a 10ms delay between programming a device to
change to or from D3hot and the time the device is next accessed (unless
Readiness Notifications are used).

The 10ms value (PCI_PM_D3HOT_WAIT) doesn't appear directly here because
some chipsets require 120ms for devices *below* them (pci_pm_d3hot_delay)
and some devices require more or less than 10ms (dev->d3hot_delay).

But msleep(10) typically waits about *20*ms, which is more than we need.
Switch to usleep_range() to improve the delay accuracy.

Based on a commit from Sajid in the Pixel 6 kernel tree [1].  On a Pixel 6,
the 10ms delay for the Exynos PCIe device delayed for an average of 19ms.
Switching to usleep_range() decreased the resume time by about 9ms.

[1] https://android.googlesource.com/kernel/gs/+/18a8cad68d8e6d50f339a716a18295e6d987cee3

[bhelgaas commit log, add timers-howto.rst link]
Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/timers/timers-howto.rst?id=v5.19#n73
Link: https://lore.kernel.org/r/20220921212735.2131588-1-willmcvicker@google.comSigned-off-by: default avatarSajid Dalvi <sdalvi@google.com>
Signed-off-by: default avatarWill McVicker <willmcvicker@google.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarMatthias Kaehlcke <mka@chromium.org>
parent 4c00cba1
...@@ -66,13 +66,15 @@ struct pci_pme_device { ...@@ -66,13 +66,15 @@ struct pci_pme_device {
static void pci_dev_d3_sleep(struct pci_dev *dev) static void pci_dev_d3_sleep(struct pci_dev *dev)
{ {
unsigned int delay = dev->d3hot_delay; unsigned int delay_ms = max(dev->d3hot_delay, pci_pm_d3hot_delay);
unsigned int upper;
if (delay < pci_pm_d3hot_delay) if (delay_ms) {
delay = pci_pm_d3hot_delay; /* Use a 20% upper bound, 1ms minimum */
upper = max(DIV_ROUND_CLOSEST(delay_ms, 5), 1U);
if (delay) usleep_range(delay_ms * USEC_PER_MSEC,
msleep(delay); (delay_ms + upper) * USEC_PER_MSEC);
}
} }
bool pci_reset_supported(struct pci_dev *dev) bool pci_reset_supported(struct pci_dev *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment