diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2016-06-13 12:01:51 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-08-18 17:04:57 -0400 |
commit | eec097d43100a8195fd4f678671ecd5d986dd675 (patch) | |
tree | ec874686b415958f9123b68f4ba0f85bae6b8c86 | |
parent | 9bb04a0c4e261187be904d05c2bcd1da0eebc20c (diff) |
PCI: Add pci_enable_ptm() for drivers to enable PTM on endpoints
Add an pci_enable_ptm() interface so drivers can enable PTM.
The PCI core enables PTM on PTM Roots and switches automatically, but we
don't enable PTM on endpoints unless a driver requests it.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/pcie/ptm.c | 45 | ||||
-rw-r--r-- | include/linux/pci.h | 7 | ||||
-rw-r--r-- | include/uapi/linux/pci_regs.h | 1 |
3 files changed, 53 insertions, 0 deletions
diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c index 48eea4e65247..a14ac94b96dc 100644 --- a/drivers/pci/pcie/ptm.c +++ b/drivers/pci/pcie/ptm.c | |||
@@ -68,3 +68,48 @@ void pci_ptm_init(struct pci_dev *dev) | |||
68 | 68 | ||
69 | pci_ptm_info(dev); | 69 | pci_ptm_info(dev); |
70 | } | 70 | } |
71 | |||
72 | int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) | ||
73 | { | ||
74 | int pos; | ||
75 | u32 cap, ctrl; | ||
76 | struct pci_dev *ups; | ||
77 | |||
78 | if (!pci_is_pcie(dev)) | ||
79 | return -EINVAL; | ||
80 | |||
81 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM); | ||
82 | if (!pos) | ||
83 | return -EINVAL; | ||
84 | |||
85 | pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap); | ||
86 | if (!(cap & PCI_PTM_CAP_REQ)) | ||
87 | return -EINVAL; | ||
88 | |||
89 | /* | ||
90 | * For a PCIe Endpoint, PTM is only useful if the endpoint can | ||
91 | * issue PTM requests to upstream devices that have PTM enabled. | ||
92 | * | ||
93 | * For Root Complex Integrated Endpoints, there is no upstream | ||
94 | * device, so there must be some implementation-specific way to | ||
95 | * associate the endpoint with a time source. | ||
96 | */ | ||
97 | if (pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT) { | ||
98 | ups = pci_upstream_bridge(dev); | ||
99 | if (!ups || !ups->ptm_enabled) | ||
100 | return -EINVAL; | ||
101 | } else if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) { | ||
102 | } else | ||
103 | return -EINVAL; | ||
104 | |||
105 | ctrl = PCI_PTM_CTRL_ENABLE; | ||
106 | pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl); | ||
107 | dev->ptm_enabled = 1; | ||
108 | |||
109 | pci_ptm_info(dev); | ||
110 | |||
111 | if (granularity) | ||
112 | *granularity = 0; | ||
113 | return 0; | ||
114 | } | ||
115 | EXPORT_SYMBOL(pci_enable_ptm); | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 96c509fa9d46..9e4b6d6f3c8d 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -1407,6 +1407,13 @@ static inline void pci_disable_ats(struct pci_dev *d) { } | |||
1407 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } | 1407 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } |
1408 | #endif | 1408 | #endif |
1409 | 1409 | ||
1410 | #ifdef CONFIG_PCIE_PTM | ||
1411 | int pci_enable_ptm(struct pci_dev *dev, u8 *granularity); | ||
1412 | #else | ||
1413 | static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) | ||
1414 | { return -EINVAL; } | ||
1415 | #endif | ||
1416 | |||
1410 | void pci_cfg_access_lock(struct pci_dev *dev); | 1417 | void pci_cfg_access_lock(struct pci_dev *dev); |
1411 | bool pci_cfg_access_trylock(struct pci_dev *dev); | 1418 | bool pci_cfg_access_trylock(struct pci_dev *dev); |
1412 | void pci_cfg_access_unlock(struct pci_dev *dev); | 1419 | void pci_cfg_access_unlock(struct pci_dev *dev); |
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 926fff41b417..72bbe1491cbf 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h | |||
@@ -967,6 +967,7 @@ | |||
967 | 967 | ||
968 | /* Precision Time Measurement */ | 968 | /* Precision Time Measurement */ |
969 | #define PCI_PTM_CAP 0x04 /* PTM Capability */ | 969 | #define PCI_PTM_CAP 0x04 /* PTM Capability */ |
970 | #define PCI_PTM_CAP_REQ 0x00000001 /* Requester capable */ | ||
970 | #define PCI_PTM_CAP_ROOT 0x00000004 /* Root capable */ | 971 | #define PCI_PTM_CAP_ROOT 0x00000004 /* Root capable */ |
971 | #define PCI_PTM_CTRL 0x08 /* PTM Control */ | 972 | #define PCI_PTM_CTRL 0x08 /* PTM Control */ |
972 | #define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */ | 973 | #define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */ |