aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Yong <jonathan.yong@intel.com>2016-06-11 15:13:38 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-08-15 14:44:08 -0400
commit9bb04a0c4e261187be904d05c2bcd1da0eebc20c (patch)
tree725a72656a45640205c5d05885dc9c3fd41f01e0
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
PCI: Add Precision Time Measurement (PTM) support
Add Precision Time Measurement (PTM) support (see PCIe r3.1, sec 6.22). Enable PTM on PTM Root devices and switch ports. This does not enable PTM on endpoints. There currently are no PTM-capable devices on the market, but it is expected to be supported by the Intel Apollo Lake platform. [bhelgaas: complete rework] Signed-off-by: Jonathan Yong <jonathan.yong@intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/pci.h6
-rw-r--r--drivers/pci/pcie/Kconfig11
-rw-r--r--drivers/pci/pcie/Makefile1
-rw-r--r--drivers/pci/pcie/ptm.c70
-rw-r--r--drivers/pci/probe.c3
-rw-r--r--include/linux/pci.h5
-rw-r--r--include/uapi/linux/pci_regs.h10
7 files changed, 105 insertions, 1 deletions
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 9730c474b016..194521bfb1a3 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -332,6 +332,12 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
332 332
333void pci_enable_acs(struct pci_dev *dev); 333void pci_enable_acs(struct pci_dev *dev);
334 334
335#ifdef CONFIG_PCIE_PTM
336void pci_ptm_init(struct pci_dev *dev);
337#else
338static inline void pci_ptm_init(struct pci_dev *dev) { }
339#endif
340
335struct pci_dev_reset_methods { 341struct pci_dev_reset_methods {
336 u16 vendor; 342 u16 vendor;
337 u16 device; 343 u16 device;
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 7fcea75afa4c..7ce77635e5ad 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -92,3 +92,14 @@ config PCIE_DPC
92 will be handled by the DPC driver. If your system doesn't 92 will be handled by the DPC driver. If your system doesn't
93 have this capability or you do not want to use this feature, 93 have this capability or you do not want to use this feature,
94 it is safe to answer N. 94 it is safe to answer N.
95
96config PCIE_PTM
97 bool "PCIe Precision Time Measurement support"
98 default n
99 depends on PCIEPORTBUS
100 help
101 This enables PCI Express Precision Time Measurement (PTM)
102 support.
103
104 This is only useful if you have devices that support PTM, but it
105 is safe to enable even if you don't.
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index b24525b3dec1..36e35ea8fde7 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_PCIEAER) += aer/
16obj-$(CONFIG_PCIE_PME) += pme.o 16obj-$(CONFIG_PCIE_PME) += pme.o
17 17
18obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o 18obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o
19obj-$(CONFIG_PCIE_PTM) += ptm.o
diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c
new file mode 100644
index 000000000000..48eea4e65247
--- /dev/null
+++ b/drivers/pci/pcie/ptm.c
@@ -0,0 +1,70 @@
1/*
2 * PCI Express Precision Time Measurement
3 * Copyright (c) 2016, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/pci.h>
18#include "../pci.h"
19
20static void pci_ptm_info(struct pci_dev *dev)
21{
22 dev_info(&dev->dev, "PTM enabled%s\n", dev->ptm_root ? " (root)" : "");
23}
24
25void pci_ptm_init(struct pci_dev *dev)
26{
27 int pos;
28 u32 cap, ctrl;
29 struct pci_dev *ups;
30
31 if (!pci_is_pcie(dev))
32 return;
33
34 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM);
35 if (!pos)
36 return;
37
38 /*
39 * Enable PTM only on interior devices (root ports, switch ports,
40 * etc.) on the assumption that it causes no link traffic until an
41 * endpoint enables it.
42 */
43 if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT ||
44 pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END))
45 return;
46
47 pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap);
48
49 /*
50 * There's no point in enabling PTM unless it's enabled in the
51 * upstream device or this device can be a PTM Root itself. Per
52 * the spec recommendation (PCIe r3.1, sec 7.32.3), select the
53 * furthest upstream Time Source as the PTM Root.
54 */
55 ups = pci_upstream_bridge(dev);
56 if (ups && ups->ptm_enabled) {
57 ctrl = PCI_PTM_CTRL_ENABLE;
58 } else {
59 if (cap & PCI_PTM_CAP_ROOT) {
60 ctrl = PCI_PTM_CTRL_ENABLE | PCI_PTM_CTRL_ROOT;
61 dev->ptm_root = 1;
62 } else
63 return;
64 }
65
66 pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl);
67 dev->ptm_enabled = 1;
68
69 pci_ptm_info(dev);
70}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 93f280df3428..e2e424472058 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1667,6 +1667,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
1667 pci_enable_acs(dev); 1667 pci_enable_acs(dev);
1668 1668
1669 pci_cleanup_aer_error_status_regs(dev); 1669 pci_cleanup_aer_error_status_regs(dev);
1670
1671 /* Precision Time Measurement */
1672 pci_ptm_init(dev);
1670} 1673}
1671 1674
1672/* 1675/*
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2599a980340f..96c509fa9d46 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -367,6 +367,11 @@ struct pci_dev {
367 int rom_attr_enabled; /* has display of the rom attribute been enabled? */ 367 int rom_attr_enabled; /* has display of the rom attribute been enabled? */
368 struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ 368 struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
369 struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ 369 struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
370
371#ifdef CONFIG_PCIE_PTM
372 unsigned int ptm_root:1;
373 unsigned int ptm_enabled:1;
374#endif
370#ifdef CONFIG_PCI_MSI 375#ifdef CONFIG_PCI_MSI
371 const struct attribute_group **msi_irq_groups; 376 const struct attribute_group **msi_irq_groups;
372#endif 377#endif
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 404095124ae2..926fff41b417 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -671,7 +671,8 @@
671#define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ 671#define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */
672#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ 672#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */
673#define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ 673#define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */
674#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DPC 674#define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */
675#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM
675 676
676#define PCI_EXT_CAP_DSN_SIZEOF 12 677#define PCI_EXT_CAP_DSN_SIZEOF 12
677#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 678#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
@@ -964,4 +965,11 @@
964 965
965#define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ 966#define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */
966 967
968/* Precision Time Measurement */
969#define PCI_PTM_CAP 0x04 /* PTM Capability */
970#define PCI_PTM_CAP_ROOT 0x00000004 /* Root capable */
971#define PCI_PTM_CTRL 0x08 /* PTM Control */
972#define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */
973#define PCI_PTM_CTRL_ROOT 0x00000002 /* Root select */
974
967#endif /* LINUX_PCI_REGS_H */ 975#endif /* LINUX_PCI_REGS_H */