* [Linux-kernel-mentees] [PATCH v4] PCI: Add support for LTR
@ 2020-09-25 18:03 Puranjay Mohan
2020-09-26 3:52 ` kernel test robot
2020-09-26 3:53 ` kernel test robot
0 siblings, 2 replies; 3+ messages in thread
From: Puranjay Mohan @ 2020-09-25 18:03 UTC (permalink / raw)
To: bjorn; +Cc: linux-pci, linux-kernel-mentees, Puranjay Mohan
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.
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
---
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(-)
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index d5869a03f748..1bceee861bfc 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -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;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a458c46d7e39..a44f07550fac 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3056,6 +3056,102 @@ void pci_pm_init(struct pci_dev *dev)
dev->imm_ready = 1;
}
+/**
+ * pci_ltr_decode - Decode the latency to a value in ns
+ * @latency: latency according to PCIe base specification 7.8.2.
+ */
+u64 pci_ltr_decode(u16 latency)
+{
+ u16 scale = (latency & PCI_LTR_SCALE_MASK) >> 10;
+ u16 value = latency & PCI_LTR_VALUE_MASK;
+
+ switch (scale) {
+ case 0: return value;
+ case 1: return value * 32;
+ case 2: return value * 1024;
+ case 3: return value * 32768;
+ case 4: return value * 1048576;
+ case 5: return value * 33554432;
+ }
+ return 0;
+}
+
+/**
+ * pci_ltr_encode - Encode the value in ns to a 16 bit register value
+ * @val: latency according to PCIe base specification 7.8.2.
+ */
+u16 pci_ltr_encode(u64 val)
+{
+ if (val <= 1UL * 0x3ff)
+ return (0 << 10) | (val & 0x3ff);
+ if (val <= 32UL * 0x3ff)
+ return (1 << 10) | ((val >> 5) & 0x3ff);
+ if (val <= 1024UL * 0x3ff)
+ return (2 << 10) | ((val >> 10) & 0x3ff);
+ if (val <= 32768UL * 0x3ff)
+ return (3 << 10) | ((val >> 15) & 0x3ff);
+ if (val <= 1048576UL * 0x3ff)
+ return (4 << 10) | ((val >> 20) & 0x3ff);
+ if (val <= 33554432UL * 0x3ff)
+ return (5 << 10) | ((val >> 25) & 0x3ff);
+ return 0;
+}
+
+/**
+ * pci_ltr_init - Initialize Latency Tolerance Information of given PCI device
+ * @dev: PCI device to handle.
+ */
+void pci_ltr_init(struct pci_dev *dev)
+{
+#ifdef CONFIG_PCIEASPM
+ struct pci_dev *bridge = dev;
+ int ltr;
+ u64 max_snoop = 0, max_nosnoop = 0;
+ u16 max_snoop_encoded, max_nosnoop_encoded;
+ u16 max_snoop_current, max_nosnoop_current;
+ u64 max_snoop_current_decoded, max_nosnoop_current_decoded;
+
+ ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+ if (!ltr)
+ return;
+
+ bridge = pci_upstream_bridge(bridge);
+ while (bridge) {
+ max_snoop += pci_ltr_decode(bridge->max_snoop_latency);
+ max_nosnoop += pci_ltr_decode(bridge->max_nosnoop_latency);
+ bridge = pci_upstream_bridge(bridge);
+ }
+ max_snoop_encoded = pci_ltr_encode(max_snoop);
+ max_nosnoop_encoded = pci_ltr_encode(max_nosnoop);
+
+ pci_read_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT,
+ &max_snoop_current);
+ max_snoop_current_decoded = pci_ltr_decode(max_snoop_current);
+ pci_read_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT,
+ &max_nosnoop_current);
+ max_nosnoop_current_decoded = pci_ltr_decode(max_nosnoop_current);
+
+ pci_dbg(dev,
+ "Calculated Max Snoop Latency %lluns Max No-Snoop Latency %lluns\n",
+ max_snoop, max_nosnoop);
+
+ if (max_snoop != max_snoop_current_decoded) {
+ pci_info(dev, "Max Snoop Latency %lluns (was %lluns)\n",
+ max_snoop, max_snoop_current_decoded);
+ pci_write_config_word(dev,
+ ltr + PCI_LTR_MAX_SNOOP_LAT,
+ max_snoop_encoded);
+ }
+ if (max_nosnoop != max_nosnoop_current_decoded) {
+ pci_info(dev, "Max No-Snoop Latency %lluns (was %lluns)\n",
+ max_nosnoop, max_nosnoop_current_decoded);
+ pci_write_config_word(dev,
+ ltr + PCI_LTR_MAX_NOSNOOP_LAT,
+ max_nosnoop_encoded);
+ }
+#endif
+}
+
static unsigned long pci_ea_flags(struct pci_dev *dev, u8 prop)
{
unsigned long flags = IORESOURCE_PCI_FIXED | IORESOURCE_PCI_EA_BEI;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fa12f7cbc1a0..18890975d0f1 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -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
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 03d37128a24f..74433265ea7e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -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);
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 5ba475ca9078..e23236a4ff66 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -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
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 835530605c0d..af7558e3c331 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -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 */
--
2.27.0
_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [Linux-kernel-mentees] [PATCH v4] PCI: Add support for LTR
2020-09-25 18:03 [Linux-kernel-mentees] [PATCH v4] PCI: Add support for LTR Puranjay Mohan
@ 2020-09-26 3:52 ` kernel test robot
2020-09-26 3:53 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2020-09-26 3:52 UTC (permalink / raw)
To: Puranjay Mohan, bjorn
Cc: linux-pci, linux-kernel-mentees, kbuild-all, Puranjay Mohan
[-- Attachment #1: Type: text/plain, Size: 3325 bytes --]
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
Reported-by: kernel test robot <lkp@intel.com>
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@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27739 bytes --]
[-- Attachment #3: Type: text/plain, Size: 201 bytes --]
_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Linux-kernel-mentees] [PATCH v4] PCI: Add support for LTR
2020-09-25 18:03 [Linux-kernel-mentees] [PATCH v4] PCI: Add support for LTR Puranjay Mohan
2020-09-26 3:52 ` kernel test robot
@ 2020-09-26 3:53 ` kernel test robot
1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2020-09-26 3:53 UTC (permalink / raw)
To: Puranjay Mohan, bjorn
Cc: kbuild-all, Puranjay Mohan, linux-pci, clang-built-linux,
linux-kernel-mentees
[-- Attachment #1: Type: text/plain, Size: 3832 bytes --]
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
Reported-by: kernel test robot <lkp@intel.com>
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@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 33291 bytes --]
[-- Attachment #3: Type: text/plain, Size: 201 bytes --]
_______________________________________________
Linux-kernel-mentees mailing list
Linux-kernel-mentees@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/linux-kernel-mentees
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-09-26 3:54 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-25 18:03 [Linux-kernel-mentees] [PATCH v4] PCI: Add support for LTR Puranjay Mohan
2020-09-26 3:52 ` kernel test robot
2020-09-26 3:53 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).