Skip to content

Commit 034f93f

Browse files
committed
Merge branch 'pci/pm'
- Cache the PTM capability offset instead of searching for it every time (Bjorn Helgaas) - Separate PTM configuration from PTM enable (Bjorn Helgaas) - Add pci_suspend_ptm() and pci_resume_ptm() to disable and re-enable PTM on suspend/resume so some Root Ports can safely enter a lower-power PM state (Bjorn Helgaas) - Disable PTM for all devices during suspend; previously we only did this for Root Ports and even then only in certain cases (Bjorn Helgaas) - Simplify pci_pm_suspend_noirq() (Rajvi Jingar) - Reduce the delay after transitions to/from D3hot by using usleep_range() instead of msleep(), which reduces the typical delay from 19ms to 10ms (Sajid Dalvi, Will McVicker) * pci/pm: PCI/PM: Reduce D3hot delay with usleep_range() PCI/PM: Simplify pci_pm_suspend_noirq() PCI/PM: Always disable PTM for all devices during suspend PCI/PTM: Consolidate PTM interface declarations PCI/PTM: Reorder functions in logical order PCI/PTM: Preserve RsvdP bits in PTM Control register PCI/PTM: Move pci_ptm_info() body into its only caller PCI/PTM: Add pci_suspend_ptm() and pci_resume_ptm() PCI/PTM: Separate configuration and enable PCI/PTM: Add pci_upstream_ptm() helper PCI/PTM: Cache PTM Capability offset
2 parents 519e512 + 3e34796 commit 034f93f

File tree

5 files changed

+208
-183
lines changed

5 files changed

+208
-183
lines changed

drivers/pci/pci-driver.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,12 @@ static int pci_pm_suspend(struct device *dev)
774774

775775
pci_dev->skip_bus_pm = false;
776776

777+
/*
778+
* Disabling PTM allows some systems, e.g., Intel mobile chips
779+
* since Coffee Lake, to enter a lower-power PM state.
780+
*/
781+
pci_suspend_ptm(pci_dev);
782+
777783
if (pci_has_legacy_pm_support(pci_dev))
778784
return pci_legacy_suspend(dev, PMSG_SUSPEND);
779785

@@ -867,20 +873,15 @@ static int pci_pm_suspend_noirq(struct device *dev)
867873
}
868874
}
869875

870-
if (pci_dev->skip_bus_pm) {
876+
if (!pci_dev->state_saved) {
877+
pci_save_state(pci_dev);
878+
871879
/*
872-
* Either the device is a bridge with a child in D0 below it, or
873-
* the function is running for the second time in a row without
874-
* going through full resume, which is possible only during
875-
* suspend-to-idle in a spurious wakeup case. The device should
876-
* be in D0 at this point, but if it is a bridge, it may be
877-
* necessary to save its state.
880+
* If the device is a bridge with a child in D0 below it,
881+
* it needs to stay in D0, so check skip_bus_pm to avoid
882+
* putting it into a low-power state in that case.
878883
*/
879-
if (!pci_dev->state_saved)
880-
pci_save_state(pci_dev);
881-
} else if (!pci_dev->state_saved) {
882-
pci_save_state(pci_dev);
883-
if (pci_power_manageable(pci_dev))
884+
if (!pci_dev->skip_bus_pm && pci_power_manageable(pci_dev))
884885
pci_prepare_to_sleep(pci_dev);
885886
}
886887

@@ -987,6 +988,8 @@ static int pci_pm_resume(struct device *dev)
987988
if (pci_dev->state_saved)
988989
pci_restore_standard_config(pci_dev);
989990

991+
pci_resume_ptm(pci_dev);
992+
990993
if (pci_has_legacy_pm_support(pci_dev))
991994
return pci_legacy_resume(dev);
992995

@@ -1274,6 +1277,8 @@ static int pci_pm_runtime_suspend(struct device *dev)
12741277
pci_power_t prev = pci_dev->current_state;
12751278
int error;
12761279

1280+
pci_suspend_ptm(pci_dev);
1281+
12771282
/*
12781283
* If pci_dev->driver is not set (unbound), we leave the device in D0,
12791284
* but it may go to D3cold when the bridge above it runtime suspends.
@@ -1335,6 +1340,7 @@ static int pci_pm_runtime_resume(struct device *dev)
13351340
* D3cold when the bridge above it runtime suspended.
13361341
*/
13371342
pci_pm_default_resume_early(pci_dev);
1343+
pci_resume_ptm(pci_dev);
13381344

13391345
if (!pci_dev->driver)
13401346
return 0;

drivers/pci/pci.c

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,15 @@ struct pci_pme_device {
6666

6767
static void pci_dev_d3_sleep(struct pci_dev *dev)
6868
{
69-
unsigned int delay = dev->d3hot_delay;
70-
71-
if (delay < pci_pm_d3hot_delay)
72-
delay = pci_pm_d3hot_delay;
73-
74-
if (delay)
75-
msleep(delay);
69+
unsigned int delay_ms = max(dev->d3hot_delay, pci_pm_d3hot_delay);
70+
unsigned int upper;
71+
72+
if (delay_ms) {
73+
/* Use a 20% upper bound, 1ms minimum */
74+
upper = max(DIV_ROUND_CLOSEST(delay_ms, 5), 1U);
75+
usleep_range(delay_ms * USEC_PER_MSEC,
76+
(delay_ms + upper) * USEC_PER_MSEC);
77+
}
7678
}
7779

7880
bool pci_reset_supported(struct pci_dev *dev)
@@ -2708,24 +2710,12 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
27082710
if (target_state == PCI_POWER_ERROR)
27092711
return -EIO;
27102712

2711-
/*
2712-
* There are systems (for example, Intel mobile chips since Coffee
2713-
* Lake) where the power drawn while suspended can be significantly
2714-
* reduced by disabling PTM on PCIe root ports as this allows the
2715-
* port to enter a lower-power PM state and the SoC to reach a
2716-
* lower-power idle state as a whole.
2717-
*/
2718-
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
2719-
pci_disable_ptm(dev);
2720-
27212713
pci_enable_wake(dev, target_state, wakeup);
27222714

27232715
error = pci_set_power_state(dev, target_state);
27242716

2725-
if (error) {
2717+
if (error)
27262718
pci_enable_wake(dev, target_state, false);
2727-
pci_restore_ptm_state(dev);
2728-
}
27292719

27302720
return error;
27312721
}
@@ -2766,24 +2756,12 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
27662756
if (target_state == PCI_POWER_ERROR)
27672757
return -EIO;
27682758

2769-
/*
2770-
* There are systems (for example, Intel mobile chips since Coffee
2771-
* Lake) where the power drawn while suspended can be significantly
2772-
* reduced by disabling PTM on PCIe root ports as this allows the
2773-
* port to enter a lower-power PM state and the SoC to reach a
2774-
* lower-power idle state as a whole.
2775-
*/
2776-
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
2777-
pci_disable_ptm(dev);
2778-
27792759
__pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
27802760

27812761
error = pci_set_power_state(dev, target_state);
27822762

2783-
if (error) {
2763+
if (error)
27842764
pci_enable_wake(dev, target_state, false);
2785-
pci_restore_ptm_state(dev);
2786-
}
27872765

27882766
return error;
27892767
}

drivers/pci/pci.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -505,13 +505,17 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
505505
#endif /* CONFIG_PCI_IOV */
506506

507507
#ifdef CONFIG_PCIE_PTM
508+
void pci_ptm_init(struct pci_dev *dev);
508509
void pci_save_ptm_state(struct pci_dev *dev);
509510
void pci_restore_ptm_state(struct pci_dev *dev);
510-
void pci_disable_ptm(struct pci_dev *dev);
511+
void pci_suspend_ptm(struct pci_dev *dev);
512+
void pci_resume_ptm(struct pci_dev *dev);
511513
#else
514+
static inline void pci_ptm_init(struct pci_dev *dev) { }
512515
static inline void pci_save_ptm_state(struct pci_dev *dev) { }
513516
static inline void pci_restore_ptm_state(struct pci_dev *dev) { }
514-
static inline void pci_disable_ptm(struct pci_dev *dev) { }
517+
static inline void pci_suspend_ptm(struct pci_dev *dev) { }
518+
static inline void pci_resume_ptm(struct pci_dev *dev) { }
515519
#endif
516520

517521
unsigned long pci_cardbus_resource_alignment(struct resource *);
@@ -579,12 +583,6 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
579583
static inline void pcie_ecrc_get_policy(char *str) { }
580584
#endif
581585

582-
#ifdef CONFIG_PCIE_PTM
583-
void pci_ptm_init(struct pci_dev *dev);
584-
#else
585-
static inline void pci_ptm_init(struct pci_dev *dev) { }
586-
#endif
587-
588586
struct pci_dev_reset_methods {
589587
u16 vendor;
590588
u16 device;

0 commit comments

Comments
 (0)