aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2017-11-17 15:26:42 -0500
committerBjorn Helgaas <bhelgaas@google.com>2017-12-19 00:02:55 -0500
commit80d7d7a904fac3f8114448dbb8cc9fa253b10120 (patch)
treec8201ad777dfa736eabf928c4883fbb8a25c8124
parent1291a0d5049dbc06baaaf66a9ff3f53db493b19b (diff)
PCI/ASPM: Calculate LTR_L1.2_THRESHOLD from device characteristics
Per PCIe r3.1, sec 5.5.1, LTR_L1.2_THRESHOLD determines whether we enter the L1.2 Link state: if L1.2 is enabled and downstream devices have reported that they can tolerate latency of at least LTR_L1.2_THRESHOLD, we must enter L1.2 when CLKREQ# is de-asserted. The implication is that LTR_L1.2_THRESHOLD is the time required to transition the Link from L0 to L1.2 and back to L0, and per sec 5.5.3.3.1, Figures 5-16 and 5-17, it appears that the absolute minimum time for those transitions would be T(POWER_OFF) + T(L1.2) + T(POWER_ON) + T(COMMONMODE). Therefore, compute LTR_L1.2_THRESHOLD as: 2us T(POWER_OFF) + 4us T(L1.2) + T(POWER_ON) + T(COMMONMODE) = LTR_L1.2_THRESHOLD Previously we set LTR_L1.2_THRESHOLD to a fixed value of 163840ns (163.84us): #define LTR_L1_2_THRESHOLD_BITS ((1 << 21) | (1 << 23) | (1 << 30)) ((1 << 21) | (1 << 23) | (1 << 30)) = 0x40a00000 LTR_L1.2_THRESHOLD_Value = (0x40a00000 & 0x03ff0000) >> 16 = 0xa0 = 160 LTR_L1.2_THRESHOLD_Scale = (0x40a00000 & 0xe0000000) >> 29 = 0x2 (* 1024ns) LTR_L1.2_THRESHOLD = 160 * 1024ns = 163840ns Obviously this doesn't account for the circuit characteristics of different implementations. Note that while firmware may enable LTR, Linux itself currently does not enable LTR. When L1.2 is enabled but LTR is not, LTR_L1.2_THRESHOLD is ignored and we always enter L1.2 when it is enabled and CLKREQ# is de-asserted. So this patch should not have any effect unless firmware enables LTR. Fixes: f1f0366dd6be ("PCI/ASPM: Calculate and save the L1.2 timing parameters") Link: https://www.coreboot.org/pipermail/coreboot-gerrit/2015-March/021134.html Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Vidya Sagar <vidyas@nvidia.com> Cc: Kenji Chen <kenji.chen@intel.com> Cc: Patrick Georgi <pgeorgi@google.com> Cc: Rajat Jain <rajatja@google.com>
-rw-r--r--drivers/pci/pcie/aspm.c71
1 files changed, 47 insertions, 24 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 9783e10da3a9..3b9b4d50cd98 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -43,18 +43,6 @@
43#define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1 | \ 43#define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1 | \
44 ASPM_STATE_L1SS) 44 ASPM_STATE_L1SS)
45 45
46/*
47 * When L1 substates are enabled, the LTR L1.2 threshold is a timing parameter
48 * that decides whether L1.1 or L1.2 is entered (Refer PCIe spec for details).
49 * Not sure is there is a way to "calculate" this on the fly, but maybe we
50 * could turn it into a parameter in future. This value has been taken from
51 * the following files from Intel's coreboot (which is the only code I found
52 * to have used this):
53 * https://www.coreboot.org/pipermail/coreboot-gerrit/2015-March/021134.html
54 * https://review.coreboot.org/#/c/8832/
55 */
56#define LTR_L1_2_THRESHOLD_BITS ((1 << 21) | (1 << 23) | (1 << 30))
57
58struct aspm_latency { 46struct aspm_latency {
59 u32 l0s; /* L0s latency (nsec) */ 47 u32 l0s; /* L0s latency (nsec) */
60 u32 l1; /* L1 latency (nsec) */ 48 u32 l1; /* L1 latency (nsec) */
@@ -333,6 +321,32 @@ static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val)
333 return 0; 321 return 0;
334} 322}
335 323
324static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value)
325{
326 u64 threshold_ns = threshold_us * 1000;
327
328 /* See PCIe r3.1, sec 7.33.3 and sec 6.18 */
329 if (threshold_ns < 32) {
330 *scale = 0;
331 *value = threshold_ns;
332 } else if (threshold_ns < 1024) {
333 *scale = 1;
334 *value = threshold_ns >> 5;
335 } else if (threshold_ns < 32768) {
336 *scale = 2;
337 *value = threshold_ns >> 10;
338 } else if (threshold_ns < 1048576) {
339 *scale = 3;
340 *value = threshold_ns >> 15;
341 } else if (threshold_ns < 33554432) {
342 *scale = 4;
343 *value = threshold_ns >> 20;
344 } else {
345 *scale = 5;
346 *value = threshold_ns >> 25;
347 }
348}
349
336struct aspm_register_info { 350struct aspm_register_info {
337 u32 support:2; 351 u32 support:2;
338 u32 enabled:2; 352 u32 enabled:2;
@@ -443,6 +457,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link,
443 struct aspm_register_info *dwreg) 457 struct aspm_register_info *dwreg)
444{ 458{
445 u32 val1, val2, scale1, scale2; 459 u32 val1, val2, scale1, scale2;
460 u32 t_common_mode, t_power_on, l1_2_threshold, scale, value;
446 461
447 link->l1ss.up_cap_ptr = upreg->l1ss_cap_ptr; 462 link->l1ss.up_cap_ptr = upreg->l1ss_cap_ptr;
448 link->l1ss.dw_cap_ptr = dwreg->l1ss_cap_ptr; 463 link->l1ss.dw_cap_ptr = dwreg->l1ss_cap_ptr;
@@ -454,16 +469,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link,
454 /* Choose the greater of the two Port Common_Mode_Restore_Times */ 469 /* Choose the greater of the two Port Common_Mode_Restore_Times */
455 val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; 470 val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
456 val2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; 471 val2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8;
457 if (val1 > val2) 472 t_common_mode = max(val1, val2);
458 link->l1ss.ctl1 |= val1 << 8;
459 else
460 link->l1ss.ctl1 |= val2 << 8;
461
462 /*
463 * We currently use LTR L1.2 threshold to be fixed constant picked from
464 * Intel's coreboot.
465 */
466 link->l1ss.ctl1 |= LTR_L1_2_THRESHOLD_BITS;
467 473
468 /* Choose the greater of the two Port T_POWER_ON times */ 474 /* Choose the greater of the two Port T_POWER_ON times */
469 val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19; 475 val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19;
@@ -472,10 +478,27 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link,
472 scale2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16; 478 scale2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16;
473 479
474 if (calc_l1ss_pwron(link->pdev, scale1, val1) > 480 if (calc_l1ss_pwron(link->pdev, scale1, val1) >
475 calc_l1ss_pwron(link->downstream, scale2, val2)) 481 calc_l1ss_pwron(link->downstream, scale2, val2)) {
476 link->l1ss.ctl2 |= scale1 | (val1 << 3); 482 link->l1ss.ctl2 |= scale1 | (val1 << 3);
477 else 483 t_power_on = calc_l1ss_pwron(link->pdev, scale1, val1);
484 } else {
478 link->l1ss.ctl2 |= scale2 | (val2 << 3); 485 link->l1ss.ctl2 |= scale2 | (val2 << 3);
486 t_power_on = calc_l1ss_pwron(link->downstream, scale2, val2);
487 }
488
489 /*
490 * Set LTR_L1.2_THRESHOLD to the time required to transition the
491 * Link from L0 to L1.2 and back to L0 so we enter L1.2 only if
492 * downstream devices report (via LTR) that they can tolerate at
493 * least that much latency.
494 *
495 * Based on PCIe r3.1, sec 5.5.3.3.1, Figures 5-16 and 5-17, and
496 * Table 5-11. T(POWER_OFF) is at most 2us and T(L1.2) is at
497 * least 4us.
498 */
499 l1_2_threshold = 2 + 4 + t_common_mode + t_power_on;
500 encode_l12_threshold(l1_2_threshold, &scale, &value);
501 link->l1ss.ctl1 |= t_common_mode << 8 | scale << 29 | value << 16;
479} 502}
480 503
481static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) 504static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)