Skip to content

Commit e8bdc5e

Browse files
committed
PCI/PTM: Add pci_suspend_ptm() and pci_resume_ptm()
We disable PTM during suspend because that allows some Root Ports to enter lower-power PM states, which means we also need to disable PTM for all downstream devices. Add pci_suspend_ptm() and pci_resume_ptm() for this purpose. pci_enable_ptm() and pci_disable_ptm() are for drivers to use to enable or disable PTM. They use dev->ptm_enabled to keep track of whether PTM should be enabled. pci_suspend_ptm() and pci_resume_ptm() are PCI core-internal functions to temporarily disable PTM during suspend and (depending on dev->ptm_enabled) re-enable PTM during resume. Enable/disable/suspend/resume all use internal __pci_enable_ptm() and __pci_disable_ptm() functions that only update the PTM Control register. Outline: pci_enable_ptm(struct pci_dev *dev) { __pci_enable_ptm(dev); dev->ptm_enabled = 1; pci_ptm_info(dev); } pci_disable_ptm(struct pci_dev *dev) { if (dev->ptm_enabled) { __pci_disable_ptm(dev); dev->ptm_enabled = 0; } } pci_suspend_ptm(struct pci_dev *dev) { if (dev->ptm_enabled) __pci_disable_ptm(dev); } pci_resume_ptm(struct pci_dev *dev) { if (dev->ptm_enabled) __pci_enable_ptm(dev); } Nothing currently calls pci_resume_ptm(); the suspend path saves the PTM state before disabling PTM, so the PTM state restore in the resume path implicitly re-enables it. A future change will use pci_resume_ptm() to fix some problems with this approach. Link: https://lore.kernel.org/r/[email protected] Tested-by: Rajvi Jingar <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Reviewed-by: Mika Westerberg <[email protected]>
1 parent 118b9df commit e8bdc5e

File tree

4 files changed

+65
-18
lines changed

4 files changed

+65
-18
lines changed

drivers/pci/pci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2714,7 +2714,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
27142714
* lower-power idle state as a whole.
27152715
*/
27162716
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
2717-
pci_disable_ptm(dev);
2717+
pci_suspend_ptm(dev);
27182718

27192719
pci_enable_wake(dev, target_state, wakeup);
27202720

@@ -2772,7 +2772,7 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
27722772
* lower-power idle state as a whole.
27732773
*/
27742774
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
2775-
pci_disable_ptm(dev);
2775+
pci_suspend_ptm(dev);
27762776

27772777
__pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
27782778

drivers/pci/pci.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,11 +507,13 @@ static inline int pci_iov_bus_range(struct pci_bus *bus)
507507
#ifdef CONFIG_PCIE_PTM
508508
void pci_save_ptm_state(struct pci_dev *dev);
509509
void pci_restore_ptm_state(struct pci_dev *dev);
510-
void pci_disable_ptm(struct pci_dev *dev);
510+
void pci_suspend_ptm(struct pci_dev *dev);
511+
void pci_resume_ptm(struct pci_dev *dev);
511512
#else
512513
static inline void pci_save_ptm_state(struct pci_dev *dev) { }
513514
static inline void pci_restore_ptm_state(struct pci_dev *dev) { }
514-
static inline void pci_disable_ptm(struct pci_dev *dev) { }
515+
static inline void pci_suspend_ptm(struct pci_dev *dev) { }
516+
static inline void pci_resume_ptm(struct pci_dev *dev) { }
515517
#endif
516518

517519
unsigned long pci_cardbus_resource_alignment(struct resource *);

drivers/pci/pcie/ptm.c

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static void pci_ptm_info(struct pci_dev *dev)
2929
dev->ptm_root ? " (root)" : "", clock_desc);
3030
}
3131

32-
void pci_disable_ptm(struct pci_dev *dev)
32+
static void __pci_disable_ptm(struct pci_dev *dev)
3333
{
3434
u16 ptm = dev->ptm_cap;
3535
u16 ctrl;
@@ -42,6 +42,21 @@ void pci_disable_ptm(struct pci_dev *dev)
4242
pci_write_config_word(dev, ptm + PCI_PTM_CTRL, ctrl);
4343
}
4444

45+
/**
46+
* pci_disable_ptm() - Disable Precision Time Measurement
47+
* @dev: PCI device
48+
*
49+
* Disable Precision Time Measurement for @dev.
50+
*/
51+
void pci_disable_ptm(struct pci_dev *dev)
52+
{
53+
if (dev->ptm_enabled) {
54+
__pci_disable_ptm(dev);
55+
dev->ptm_enabled = 0;
56+
}
57+
}
58+
EXPORT_SYMBOL(pci_disable_ptm);
59+
4560
void pci_save_ptm_state(struct pci_dev *dev)
4661
{
4762
u16 ptm = dev->ptm_cap;
@@ -151,18 +166,8 @@ void pci_ptm_init(struct pci_dev *dev)
151166
pci_enable_ptm(dev, NULL);
152167
}
153168

154-
/**
155-
* pci_enable_ptm() - Enable Precision Time Measurement
156-
* @dev: PCI device
157-
* @granularity: pointer to return granularity
158-
*
159-
* Enable Precision Time Measurement for @dev. If successful and
160-
* @granularity is non-NULL, return the Effective Granularity.
161-
*
162-
* Return: zero if successful, or -EINVAL if @dev lacks a PTM Capability or
163-
* is not a PTM Root and lacks an upstream path of PTM-enabled devices.
164-
*/
165-
int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
169+
/* Enable PTM in the Control register if possible */
170+
static int __pci_enable_ptm(struct pci_dev *dev)
166171
{
167172
u16 ptm = dev->ptm_cap;
168173
struct pci_dev *ups;
@@ -191,8 +196,29 @@ int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
191196
ctrl |= PCI_PTM_CTRL_ROOT;
192197

193198
pci_write_config_dword(dev, ptm + PCI_PTM_CTRL, ctrl);
194-
dev->ptm_enabled = 1;
199+
return 0;
200+
}
195201

202+
/**
203+
* pci_enable_ptm() - Enable Precision Time Measurement
204+
* @dev: PCI device
205+
* @granularity: pointer to return granularity
206+
*
207+
* Enable Precision Time Measurement for @dev. If successful and
208+
* @granularity is non-NULL, return the Effective Granularity.
209+
*
210+
* Return: zero if successful, or -EINVAL if @dev lacks a PTM Capability or
211+
* is not a PTM Root and lacks an upstream path of PTM-enabled devices.
212+
*/
213+
int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
214+
{
215+
int rc;
216+
217+
rc = __pci_enable_ptm(dev);
218+
if (rc)
219+
return rc;
220+
221+
dev->ptm_enabled = 1;
196222
pci_ptm_info(dev);
197223

198224
if (granularity)
@@ -201,6 +227,23 @@ int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
201227
}
202228
EXPORT_SYMBOL(pci_enable_ptm);
203229

230+
/*
231+
* Disable PTM, but preserve dev->ptm_enabled so we silently re-enable it on
232+
* resume if necessary.
233+
*/
234+
void pci_suspend_ptm(struct pci_dev *dev)
235+
{
236+
if (dev->ptm_enabled)
237+
__pci_disable_ptm(dev);
238+
}
239+
240+
/* If PTM was enabled before suspend, re-enable it when resuming */
241+
void pci_resume_ptm(struct pci_dev *dev)
242+
{
243+
if (dev->ptm_enabled)
244+
__pci_enable_ptm(dev);
245+
}
246+
204247
bool pcie_ptm_enabled(struct pci_dev *dev)
205248
{
206249
if (!dev)

include/linux/pci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,10 +1678,12 @@ bool pci_ats_disabled(void);
16781678

16791679
#ifdef CONFIG_PCIE_PTM
16801680
int pci_enable_ptm(struct pci_dev *dev, u8 *granularity);
1681+
void pci_disable_ptm(struct pci_dev *dev);
16811682
bool pcie_ptm_enabled(struct pci_dev *dev);
16821683
#else
16831684
static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
16841685
{ return -EINVAL; }
1686+
static inline void pci_disable_ptm(struct pci_dev *dev) { }
16851687
static inline bool pcie_ptm_enabled(struct pci_dev *dev)
16861688
{ return false; }
16871689
#endif

0 commit comments

Comments
 (0)