diff options
| -rw-r--r-- | drivers/pci/pci.h | 6 | ||||
| -rw-r--r-- | drivers/pci/pcie/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/pci/pcie/Makefile | 1 | ||||
| -rw-r--r-- | drivers/pci/pcie/ptm.c | 70 | ||||
| -rw-r--r-- | drivers/pci/probe.c | 3 | ||||
| -rw-r--r-- | include/linux/pci.h | 5 | ||||
| -rw-r--r-- | include/uapi/linux/pci_regs.h | 10 |
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 | ||
| 333 | void pci_enable_acs(struct pci_dev *dev); | 333 | void pci_enable_acs(struct pci_dev *dev); |
| 334 | 334 | ||
| 335 | #ifdef CONFIG_PCIE_PTM | ||
| 336 | void pci_ptm_init(struct pci_dev *dev); | ||
| 337 | #else | ||
| 338 | static inline void pci_ptm_init(struct pci_dev *dev) { } | ||
| 339 | #endif | ||
| 340 | |||
| 335 | struct pci_dev_reset_methods { | 341 | struct 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 | |||
| 96 | config 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/ | |||
| 16 | obj-$(CONFIG_PCIE_PME) += pme.o | 16 | obj-$(CONFIG_PCIE_PME) += pme.o |
| 17 | 17 | ||
| 18 | obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o | 18 | obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o |
| 19 | obj-$(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 | |||
| 20 | static void pci_ptm_info(struct pci_dev *dev) | ||
| 21 | { | ||
| 22 | dev_info(&dev->dev, "PTM enabled%s\n", dev->ptm_root ? " (root)" : ""); | ||
| 23 | } | ||
| 24 | |||
| 25 | void 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 */ |
