diff options
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 9783e10da3a9..57feef2ecfe7 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 | |||
58 | struct aspm_latency { | 46 | struct 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) */ |
@@ -278,7 +266,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) | |||
278 | return; | 266 | return; |
279 | 267 | ||
280 | /* Training failed. Restore common clock configurations */ | 268 | /* Training failed. Restore common clock configurations */ |
281 | dev_err(&parent->dev, "ASPM: Could not configure common clock\n"); | 269 | pci_err(parent, "ASPM: Could not configure common clock\n"); |
282 | list_for_each_entry(child, &linkbus->devices, bus_list) | 270 | list_for_each_entry(child, &linkbus->devices, bus_list) |
283 | pcie_capability_write_word(child, PCI_EXP_LNKCTL, | 271 | pcie_capability_write_word(child, PCI_EXP_LNKCTL, |
284 | child_reg[PCI_FUNC(child->devfn)]); | 272 | child_reg[PCI_FUNC(child->devfn)]); |
@@ -328,11 +316,36 @@ static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val) | |||
328 | case 2: | 316 | case 2: |
329 | return val * 100; | 317 | return val * 100; |
330 | } | 318 | } |
331 | dev_err(&pdev->dev, "%s: Invalid T_PwrOn scale: %u\n", | 319 | pci_err(pdev, "%s: Invalid T_PwrOn scale: %u\n", __func__, scale); |
332 | __func__, scale); | ||
333 | return 0; | 320 | return 0; |
334 | } | 321 | } |
335 | 322 | ||
323 | static void encode_l12_threshold(u32 threshold_us, u32 *scale, u32 *value) | ||
324 | { | ||
325 | u64 threshold_ns = threshold_us * 1000; | ||
326 | |||
327 | /* See PCIe r3.1, sec 7.33.3 and sec 6.18 */ | ||
328 | if (threshold_ns < 32) { | ||
329 | *scale = 0; | ||
330 | *value = threshold_ns; | ||
331 | } else if (threshold_ns < 1024) { | ||
332 | *scale = 1; | ||
333 | *value = threshold_ns >> 5; | ||
334 | } else if (threshold_ns < 32768) { | ||
335 | *scale = 2; | ||
336 | *value = threshold_ns >> 10; | ||
337 | } else if (threshold_ns < 1048576) { | ||
338 | *scale = 3; | ||
339 | *value = threshold_ns >> 15; | ||
340 | } else if (threshold_ns < 33554432) { | ||
341 | *scale = 4; | ||
342 | *value = threshold_ns >> 20; | ||
343 | } else { | ||
344 | *scale = 5; | ||
345 | *value = threshold_ns >> 25; | ||
346 | } | ||
347 | } | ||
348 | |||
336 | struct aspm_register_info { | 349 | struct aspm_register_info { |
337 | u32 support:2; | 350 | u32 support:2; |
338 | u32 enabled:2; | 351 | u32 enabled:2; |
@@ -443,6 +456,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, | |||
443 | struct aspm_register_info *dwreg) | 456 | struct aspm_register_info *dwreg) |
444 | { | 457 | { |
445 | u32 val1, val2, scale1, scale2; | 458 | u32 val1, val2, scale1, scale2; |
459 | u32 t_common_mode, t_power_on, l1_2_threshold, scale, value; | ||
446 | 460 | ||
447 | link->l1ss.up_cap_ptr = upreg->l1ss_cap_ptr; | 461 | link->l1ss.up_cap_ptr = upreg->l1ss_cap_ptr; |
448 | link->l1ss.dw_cap_ptr = dwreg->l1ss_cap_ptr; | 462 | link->l1ss.dw_cap_ptr = dwreg->l1ss_cap_ptr; |
@@ -454,16 +468,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link, | |||
454 | /* Choose the greater of the two Port Common_Mode_Restore_Times */ | 468 | /* Choose the greater of the two Port Common_Mode_Restore_Times */ |
455 | val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; | 469 | val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; |
456 | val2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; | 470 | val2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_CM_RESTORE_TIME) >> 8; |
457 | if (val1 > val2) | 471 | 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 | 472 | ||
468 | /* Choose the greater of the two Port T_POWER_ON times */ | 473 | /* Choose the greater of the two Port T_POWER_ON times */ |
469 | val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19; | 474 | val1 = (upreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_VALUE) >> 19; |
@@ -472,10 +477,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; | 477 | scale2 = (dwreg->l1ss_cap & PCI_L1SS_CAP_P_PWR_ON_SCALE) >> 16; |
473 | 478 | ||
474 | if (calc_l1ss_pwron(link->pdev, scale1, val1) > | 479 | if (calc_l1ss_pwron(link->pdev, scale1, val1) > |
475 | calc_l1ss_pwron(link->downstream, scale2, val2)) | 480 | calc_l1ss_pwron(link->downstream, scale2, val2)) { |
476 | link->l1ss.ctl2 |= scale1 | (val1 << 3); | 481 | link->l1ss.ctl2 |= scale1 | (val1 << 3); |
477 | else | 482 | t_power_on = calc_l1ss_pwron(link->pdev, scale1, val1); |
483 | } else { | ||
478 | link->l1ss.ctl2 |= scale2 | (val2 << 3); | 484 | link->l1ss.ctl2 |= scale2 | (val2 << 3); |
485 | t_power_on = calc_l1ss_pwron(link->downstream, scale2, val2); | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | * Set LTR_L1.2_THRESHOLD to the time required to transition the | ||
490 | * Link from L0 to L1.2 and back to L0 so we enter L1.2 only if | ||
491 | * downstream devices report (via LTR) that they can tolerate at | ||
492 | * least that much latency. | ||
493 | * | ||
494 | * Based on PCIe r3.1, sec 5.5.3.3.1, Figures 5-16 and 5-17, and | ||
495 | * Table 5-11. T(POWER_OFF) is at most 2us and T(L1.2) is at | ||
496 | * least 4us. | ||
497 | */ | ||
498 | l1_2_threshold = 2 + 4 + t_common_mode + t_power_on; | ||
499 | encode_l12_threshold(l1_2_threshold, &scale, &value); | ||
500 | link->l1ss.ctl1 |= t_common_mode << 8 | scale << 29 | value << 16; | ||
479 | } | 501 | } |
480 | 502 | ||
481 | static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | 503 | static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) |
@@ -786,7 +808,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
786 | */ | 808 | */ |
787 | pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); | 809 | pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); |
788 | if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { | 810 | if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { |
789 | dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n"); | 811 | pci_info(child, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n"); |
790 | return -EINVAL; | 812 | return -EINVAL; |
791 | } | 813 | } |
792 | } | 814 | } |
@@ -1027,7 +1049,7 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) | |||
1027 | * ignored in this situation. | 1049 | * ignored in this situation. |
1028 | */ | 1050 | */ |
1029 | if (aspm_disabled) { | 1051 | if (aspm_disabled) { |
1030 | dev_warn(&pdev->dev, "can't disable ASPM; OS doesn't have ASPM control\n"); | 1052 | pci_warn(pdev, "can't disable ASPM; OS doesn't have ASPM control\n"); |
1031 | return; | 1053 | return; |
1032 | } | 1054 | } |
1033 | 1055 | ||