Skip to contentSkip to conversation

PCI: Add support for LTR

PATCH Superseded Puranjay Mohan 2 participants 3 messages Sep 25, 2020 – Sep 26, 2020

Subsystems (2)

v4 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

PATCH v4 1/1 PCI: Add support for LTR

Add a new function pci_ltr_init() which will be called from pci_init_capabilities() to initialize every PCIe device's LTR values. Add code in probe.c to evaluate LTR _DSM and save the latencies in pci_dev.

---
v4 - remove pci_upstream_bridge and use acpi_pci_find_companion()
to get the handle for evaluating _DSM.
Add acpi_check_dsm()
Change the logging mechanism.
v3 - change the algorithm to add latencies, add helper funtions for
encoding and decoding the latencies.
v2 - add an #ifdefin pci-acpi.c to fix the bug reported by test bot. v1 - based the patch on v5.9-rc1 so it applies correctly.

---
 drivers/pci/pci-acpi.c   | 37 ++++++++++++++++
 drivers/pci/pci.c        | 96 ++++++++++++++++++++++++++++++++++++++++
 drivers/pci/pci.h        |  3 ++
 drivers/pci/probe.c      |  7 ++-
 include/linux/pci-acpi.h |  1 +
 include/linux/pci.h      |  2 +
 6 files changed, 145 insertions(+), 1 deletion(-)
drivers/pci/pci-acpi.c +37 -0
index d5869a03f748..1bceee861bfc 100644
@@ -1213,6 +1213,43 @@ static void pci_acpi_optimize_delay(struct pci_dev *pdev,
 	ACPI_FREE(obj);
 }
 
+/* pci_acpi_evaluate_ltr_latency
+ *
+ * @dev - the pci_dev to evaluate and save latencies
+ */
+void pci_acpi_evaluate_ltr_latency(struct pci_dev *dev)
+{
+#ifdef CONFIG_PCIEASPM
+	struct acpi_device *adev;
+	union acpi_object *obj, *elements;
+
+	adev = ACPI_COMPANION(&dev->dev);
+	if (!adev && !pci_dev_is_added(dev))
+		adev = acpi_pci_find_companion(&dev->dev);
+	if (!adev)
+		return;
+
+	if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 2,
+				1ULL << DSM_PCI_LTR_MAX_LATENCY))
+		return;
+	obj = acpi_evaluate_dsm(adev->handle, &pci_acpi_dsm_guid, 2,
+					DSM_PCI_LTR_MAX_LATENCY, NULL);
+	if (!obj)
+		return;
+
+	if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 4) {
+		elements = obj->package.elements;
+		dev->max_snoop_latency = (u16)elements[1].integer.value |
+				((u16)elements[0].integer.value <<
+							PCI_LTR_SCALE_SHIFT);
+		dev->max_nosnoop_latency = (u16)elements[3].integer.value |
+				((u16)elements[2].integer.value <<
+							PCI_LTR_SCALE_SHIFT);
+	}
+	ACPI_FREE(obj);
+#endif
+}
+
 static void pci_acpi_set_external_facing(struct pci_dev *dev)
 {
 	u8 val;
drivers/pci/pci.c +96 -0

102 lines not on this page · raw message

drivers/pci/pci.h +3 -0
index fa12f7cbc1a0..18890975d0f1 100644
@@ -110,6 +110,7 @@ void pci_free_cap_save_buffers(struct pci_dev *dev);
 bool pci_bridge_d3_possible(struct pci_dev *dev);
 void pci_bridge_d3_update(struct pci_dev *dev);
 void pci_bridge_wait_for_secondary_bus(struct pci_dev *dev);
+void pci_ltr_init(struct pci_dev *dev);
 
 static inline void pci_wakeup_event(struct pci_dev *dev)
 {
@@ -680,11 +681,13 @@ static inline int pci_aer_raw_clear_status(struct pci_dev *dev) { return -EINVAL
 
 #ifdef CONFIG_ACPI
 int pci_acpi_program_hp_params(struct pci_dev *dev);
+void pci_acpi_evaluate_ltr_latency(struct pci_dev *dev);
 #else
 static inline int pci_acpi_program_hp_params(struct pci_dev *dev)
 {
 	return -ENODEV;
 }
+static inline void pci_acpi_evaluate_ltr_latency(struct pci_dev *dev) {}
 #endif
 
 #ifdef CONFIG_PCIEASPM
drivers/pci/probe.c +6 -1
index 03d37128a24f..74433265ea7e 100644
@@ -2105,6 +2105,11 @@ static void pci_configure_ltr(struct pci_dev *dev)
 
 	if (!pci_is_pcie(dev))
 		return;
+	/*
+	 * Read latency values from _DSM and save in pci_dev
+	 * as a part of latency tolerance reporting mechanism.
+	 */
+	pci_acpi_evaluate_ltr_latency(dev);
 
 	pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
 	if (!(cap & PCI_EXP_DEVCAP2_LTR))
@@ -2123,7 +2128,6 @@ static void pci_configure_ltr(struct pci_dev *dev)
 
 		return;
 	}
-
 	if (!host->native_ltr)
 		return;
 
@@ -2400,6 +2404,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
 	pci_ptm_init(dev);		/* Precision Time Measurement */
 	pci_aer_init(dev);		/* Advanced Error Reporting */
 	pci_dpc_init(dev);		/* Downstream Port Containment */
+	pci_ltr_init(dev);		/* Latency Tolerance Reporting */
 
 	pcie_report_downtraining(dev);
 
include/linux/pci-acpi.h +1 -0
index 5ba475ca9078..e23236a4ff66 100644
@@ -110,6 +110,7 @@ extern const guid_t pci_acpi_dsm_guid;
 
 /* _DSM Definitions for PCI */
 #define DSM_PCI_PRESERVE_BOOT_CONFIG		0x05
+#define DSM_PCI_LTR_MAX_LATENCY			0x06
 #define DSM_PCI_DEVICE_NAME			0x07
 #define DSM_PCI_POWER_ON_RESET_DELAY		0x08
 #define DSM_PCI_DEVICE_READINESS_DURATIONS	0x09
include/linux/pci.h +2 -0
index 835530605c0d..af7558e3c331 100644
@@ -380,6 +380,8 @@ struct pci_dev {
 	struct pcie_link_state	*link_state;	/* ASPM link state */
 	unsigned int	ltr_path:1;	/* Latency Tolerance Reporting
 					   supported from root to here */
+	u16 max_snoop_latency;		/* LTR Max Snoop latency */
+	u16 max_nosnoop_latency;	/* LTR Max No-Snoop latency */
 #endif
 	unsigned int	eetlp_prefix_path:1;	/* End-to-End TLP Prefix */
 
Signature · 1 line
2.27.0
#1 lore raw
Thank you for the patch! Perhaps something to improve:

Hi Puranjay,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on pci/next]
[also build test WARNING on pm/linux-next v5.9-rc6 next-20200925] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Puranjay-Mohan/PCI-Add-support-for-LTR/20200926-020527
base:   https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
config: microblaze-randconfig-r005-20200925 (attached as .config)
compiler: microblaze-linux-gcc (GCC) 9.3.0

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/8d07a88c56c747b6c2217cad501d3b0d5cfe8ca6
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Puranjay-Mohan/PCI-Add-support-for-LTR/20200926-020527 git checkout 8d07a88c56c747b6c2217cad501d3b0d5cfe8ca6
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=microblaze

If you fix the issue, kindly add following tag as appropriate

All warnings (new ones prefixed by >>):

>> drivers/pci/pci.c:3064:5: warning: no previous prototype for 'pci_ltr_decode' [-Wmissing-prototypes]
    3064 | u64 pci_ltr_decode(u16 latency)
         |     ^~~~~~~~~~~~~~
>> drivers/pci/pci.c:3084:5: warning: no previous prototype for 'pci_ltr_encode' [-Wmissing-prototypes]
    3084 | u16 pci_ltr_encode(u64 val)
         |     ^~~~~~~~~~~~~~

vim +/pci_ltr_decode +3064 drivers/pci/pci.c

3059
3060 /**
3061 * pci_ltr_decode - Decode the latency to a value in ns
3062 * @latency: latency according to PCIe base specification 7.8.2.
3063 */

> 3064	u64 pci_ltr_decode(u16 latency)
  3065	{
  3066		u16 scale = (latency & PCI_LTR_SCALE_MASK) >> 10;
  3067		u16 value = latency & PCI_LTR_VALUE_MASK;
  3068	
  3069		switch (scale) {
  3070		case 0: return value;
  3071		case 1: return value * 32;
  3072		case 2: return value * 1024;
  3073		case 3: return value * 32768;
  3074		case 4: return value * 1048576;
  3075		case 5: return value * 33554432;
  3076		}
  3077		return 0;
  3078	}
  3079	
  3080	/**
  3081	 * pci_ltr_encode - Encode the value in ns to a 16 bit register value
  3082	 * @val: latency according to PCIe base specification 7.8.2.
  3083	 */
> 3084	u16 pci_ltr_encode(u64 val)

3085 {
3086 if (val <= 1UL * 0x3ff)
3087 return (0 << 10) | (val & 0x3ff);
3088 if (val <= 32UL * 0x3ff)
3089 return (1 << 10) | ((val >> 5) & 0x3ff);
3090 if (val <= 1024UL * 0x3ff)
3091 return (2 << 10) | ((val >> 10) & 0x3ff);
3092 if (val <= 32768UL * 0x3ff)
3093 return (3 << 10) | ((val >> 15) & 0x3ff);
3094 if (val <= 1048576UL * 0x3ff)
3095 return (4 << 10) | ((val >> 20) & 0x3ff);
3096 if (val <= 33554432UL * 0x3ff)
3097 return (5 << 10) | ((val >> 25) & 0x3ff);
3098 return 0;
3099 }
3100

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

#2 lore raw
In reply to Puranjay Mohan
Thank you for the patch! Perhaps something to improve:

Hi Puranjay,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on pci/next]
[also build test WARNING on pm/linux-next v5.9-rc6 next-20200925] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Puranjay-Mohan/PCI-Add-support-for-LTR/20200926-020527
base:   https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
config: riscv-randconfig-r004-20200925 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project a83eb048cb9a75da7a07a9d5318bbdbf54885c87)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/0day-ci/linux/commit/8d07a88c56c747b6c2217cad501d3b0d5cfe8ca6
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Puranjay-Mohan/PCI-Add-support-for-LTR/20200926-020527 git checkout 8d07a88c56c747b6c2217cad501d3b0d5cfe8ca6
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv

If you fix the issue, kindly add following tag as appropriate

All warnings (new ones prefixed by >>):

>> drivers/pci/pci.c:3064:5: warning: no previous prototype for function 'pci_ltr_decode' [-Wmissing-prototypes]
   u64 pci_ltr_decode(u16 latency)
       ^
   drivers/pci/pci.c:3064:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   u64 pci_ltr_decode(u16 latency)
   ^
   static 
>> drivers/pci/pci.c:3084:5: warning: no previous prototype for function 'pci_ltr_encode' [-Wmissing-prototypes]
   u16 pci_ltr_encode(u64 val)
       ^

drivers/pci/pci.c:3084:1: note: declare 'static' if the function is not intended to be used outside of this translation unit u16 pci_ltr_encode(u64 val)
^
static
2 warnings generated.

vim +/pci_ltr_decode +3064 drivers/pci/pci.c

3059
3060 /**
3061 * pci_ltr_decode - Decode the latency to a value in ns
3062 * @latency: latency according to PCIe base specification 7.8.2.
3063 */

> 3064	u64 pci_ltr_decode(u16 latency)
  3065	{
  3066		u16 scale = (latency & PCI_LTR_SCALE_MASK) >> 10;
  3067		u16 value = latency & PCI_LTR_VALUE_MASK;
  3068	
  3069		switch (scale) {
  3070		case 0: return value;
  3071		case 1: return value * 32;
  3072		case 2: return value * 1024;
  3073		case 3: return value * 32768;
  3074		case 4: return value * 1048576;
  3075		case 5: return value * 33554432;
  3076		}
  3077		return 0;
  3078	}
  3079	
  3080	/**
  3081	 * pci_ltr_encode - Encode the value in ns to a 16 bit register value
  3082	 * @val: latency according to PCIe base specification 7.8.2.
  3083	 */
> 3084	u16 pci_ltr_encode(u64 val)

3085 {
3086 if (val <= 1UL * 0x3ff)
3087 return (0 << 10) | (val & 0x3ff);
3088 if (val <= 32UL * 0x3ff)
3089 return (1 << 10) | ((val >> 5) & 0x3ff);
3090 if (val <= 1024UL * 0x3ff)
3091 return (2 << 10) | ((val >> 10) & 0x3ff);
3092 if (val <= 32768UL * 0x3ff)
3093 return (3 << 10) | ((val >> 15) & 0x3ff);
3094 if (val <= 1048576UL * 0x3ff)
3095 return (4 << 10) | ((val >> 20) & 0x3ff);
3096 if (val <= 33554432UL * 0x3ff)
3097 return (5 << 10) | ((val >> 25) & 0x3ff);
3098 return 0;
3099 }
3100

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org