PCI: Add support for LTR
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -380,6 +380,8 @@ struct pci_dev {struct pcie_link_state *link_state;/* ASPM link state */ unsigned int ltr_path:1; /* Latency Tolerance Reportingsupported 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
kernel test robot
build botThank 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
kernel test robot
build botThank 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