diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2017-02-15 12:56:07 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-02-15 12:56:07 -0500 |
commit | 8f417ca9ebfa8701a41db64f5ed9cbb01b8e4219 (patch) | |
tree | 897b28da87379412b084c895174b7b84ee3efcb2 | |
parent | ca0ef7fecc881a7e8d11db2d8852ab580cd29e03 (diff) | |
parent | a142f4d3e5c54db5e942fa6ee5f3dc0e8c83207b (diff) |
Merge branch 'pci/aspm' into next
* pci/aspm:
PCI/ASPM: Add comment about L1 substate latency
PCI/ASPM: Configure L1 substate settings
PCI/ASPM: Calculate and save the L1.2 timing parameters
PCI/ASPM: Read and set up L1 substate capabilities
PCI/ASPM: Add support for L1 substates
PCI/ASPM: Add L1 substate capability structure register definitions
-rw-r--r-- | drivers/pci/pcie/Kconfig | 8 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 291 | ||||
-rw-r--r-- | include/uapi/linux/pci_regs.h | 16 |
3 files changed, 302 insertions, 13 deletions
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 7ce77635e5ad..ac53edbc9613 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
@@ -71,6 +71,14 @@ config PCIEASPM_POWERSAVE | |||
71 | Enable PCI Express ASPM L0s and L1 where possible, even if the | 71 | Enable PCI Express ASPM L0s and L1 where possible, even if the |
72 | BIOS did not. | 72 | BIOS did not. |
73 | 73 | ||
74 | config PCIEASPM_POWER_SUPERSAVE | ||
75 | bool "Power Supersave" | ||
76 | depends on PCIEASPM | ||
77 | help | ||
78 | Same as PCIEASPM_POWERSAVE, except it also enables L1 substates where | ||
79 | possible. This would result in higher power savings while staying in L1 | ||
80 | where the components support it. | ||
81 | |||
74 | config PCIEASPM_PERFORMANCE | 82 | config PCIEASPM_PERFORMANCE |
75 | bool "Performance" | 83 | bool "Performance" |
76 | depends on PCIEASPM | 84 | depends on PCIEASPM |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 17ac1dce3286..a9bcd56e41ed 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -30,8 +30,29 @@ | |||
30 | #define ASPM_STATE_L0S_UP (1) /* Upstream direction L0s state */ | 30 | #define ASPM_STATE_L0S_UP (1) /* Upstream direction L0s state */ |
31 | #define ASPM_STATE_L0S_DW (2) /* Downstream direction L0s state */ | 31 | #define ASPM_STATE_L0S_DW (2) /* Downstream direction L0s state */ |
32 | #define ASPM_STATE_L1 (4) /* L1 state */ | 32 | #define ASPM_STATE_L1 (4) /* L1 state */ |
33 | #define ASPM_STATE_L1_1 (8) /* ASPM L1.1 state */ | ||
34 | #define ASPM_STATE_L1_2 (0x10) /* ASPM L1.2 state */ | ||
35 | #define ASPM_STATE_L1_1_PCIPM (0x20) /* PCI PM L1.1 state */ | ||
36 | #define ASPM_STATE_L1_2_PCIPM (0x40) /* PCI PM L1.2 state */ | ||
37 | #define ASPM_STATE_L1_SS_PCIPM (ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1_2_PCIPM) | ||
38 | #define ASPM_STATE_L1_2_MASK (ASPM_STATE_L1_2 | ASPM_STATE_L1_2_PCIPM) | ||
39 | #define ASPM_STATE_L1SS (ASPM_STATE_L1_1 | ASPM_STATE_L1_1_PCIPM |\ | ||
40 | ASPM_STATE_L1_2_MASK) | ||
33 | #define ASPM_STATE_L0S (ASPM_STATE_L0S_UP | ASPM_STATE_L0S_DW) | 41 | #define ASPM_STATE_L0S (ASPM_STATE_L0S_UP | ASPM_STATE_L0S_DW) |
34 | #define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1) | 42 | #define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1 | \ |
43 | ASPM_STATE_L1SS) | ||
44 | |||
45 | /* | ||
46 | * When L1 substates are enabled, the LTR L1.2 threshold is a timing parameter | ||
47 | * that decides whether L1.1 or L1.2 is entered (Refer PCIe spec for details). | ||
48 | * Not sure is there is a way to "calculate" this on the fly, but maybe we | ||
49 | * could turn it into a parameter in future. This value has been taken from | ||
50 | * the following files from Intel's coreboot (which is the only code I found | ||
51 | * to have used this): | ||
52 | * https://www.coreboot.org/pipermail/coreboot-gerrit/2015-March/021134.html | ||
53 | * https://review.coreboot.org/#/c/8832/ | ||
54 | */ | ||
55 | #define LTR_L1_2_THRESHOLD_BITS ((1 << 21) | (1 << 23) | (1 << 30)) | ||
35 | 56 | ||
36 | struct aspm_latency { | 57 | struct aspm_latency { |
37 | u32 l0s; /* L0s latency (nsec) */ | 58 | u32 l0s; /* L0s latency (nsec) */ |
@@ -40,6 +61,7 @@ struct aspm_latency { | |||
40 | 61 | ||
41 | struct pcie_link_state { | 62 | struct pcie_link_state { |
42 | struct pci_dev *pdev; /* Upstream component of the Link */ | 63 | struct pci_dev *pdev; /* Upstream component of the Link */ |
64 | struct pci_dev *downstream; /* Downstream component, function 0 */ | ||
43 | struct pcie_link_state *root; /* pointer to the root port link */ | 65 | struct pcie_link_state *root; /* pointer to the root port link */ |
44 | struct pcie_link_state *parent; /* pointer to the parent Link state */ | 66 | struct pcie_link_state *parent; /* pointer to the parent Link state */ |
45 | struct list_head sibling; /* node in link_list */ | 67 | struct list_head sibling; /* node in link_list */ |
@@ -47,11 +69,11 @@ struct pcie_link_state { | |||
47 | struct list_head link; /* node in parent's children list */ | 69 | struct list_head link; /* node in parent's children list */ |
48 | 70 | ||
49 | /* ASPM state */ | 71 | /* ASPM state */ |
50 | u32 aspm_support:3; /* Supported ASPM state */ | 72 | u32 aspm_support:7; /* Supported ASPM state */ |
51 | u32 aspm_enabled:3; /* Enabled ASPM state */ | 73 | u32 aspm_enabled:7; /* Enabled ASPM state */ |
52 | u32 aspm_capable:3; /* Capable ASPM state with latency */ | 74 | u32 aspm_capable:7; /* Capable ASPM state with latency */ |
53 | u32 aspm_default:3; /* Default ASPM state by BIOS */ | 75 | u32 aspm_default:7; /* Default ASPM state by BIOS */ |
54 | u32 aspm_disable:3; /* Disabled ASPM state */ | 76 | u32 aspm_disable:7; /* Disabled ASPM state */ |
55 | 77 | ||
56 | /* Clock PM state */ | 78 | /* Clock PM state */ |
57 | u32 clkpm_capable:1; /* Clock PM capable? */ | 79 | u32 clkpm_capable:1; /* Clock PM capable? */ |
@@ -66,6 +88,14 @@ struct pcie_link_state { | |||
66 | * has one slot under it, so at most there are 8 functions. | 88 | * has one slot under it, so at most there are 8 functions. |
67 | */ | 89 | */ |
68 | struct aspm_latency acceptable[8]; | 90 | struct aspm_latency acceptable[8]; |
91 | |||
92 | /* L1 PM Substate info */ | ||
93 | struct { | ||
94 | u32 up_cap_ptr; /* L1SS cap ptr in upstream dev */ | ||
95 | u32 dw_cap_ptr; /* L1SS cap ptr in downstream dev */ | ||
96 | u32 ctl1; /* value to be programmed in ctl1 */ | ||
97 | u32 ctl2; /* value to be programmed in ctl2 */ | ||
98 | } l1ss; | ||
69 | }; | 99 | }; |
70 | 100 | ||
71 | static int aspm_disabled, aspm_force; | 101 | static int aspm_disabled, aspm_force; |
@@ -76,11 +106,14 @@ static LIST_HEAD(link_list); | |||
76 | #define POLICY_DEFAULT 0 /* BIOS default setting */ | 106 | #define POLICY_DEFAULT 0 /* BIOS default setting */ |
77 | #define POLICY_PERFORMANCE 1 /* high performance */ | 107 | #define POLICY_PERFORMANCE 1 /* high performance */ |
78 | #define POLICY_POWERSAVE 2 /* high power saving */ | 108 | #define POLICY_POWERSAVE 2 /* high power saving */ |
109 | #define POLICY_POWER_SUPERSAVE 3 /* possibly even more power saving */ | ||
79 | 110 | ||
80 | #ifdef CONFIG_PCIEASPM_PERFORMANCE | 111 | #ifdef CONFIG_PCIEASPM_PERFORMANCE |
81 | static int aspm_policy = POLICY_PERFORMANCE; | 112 | static int aspm_policy = POLICY_PERFORMANCE; |
82 | #elif defined CONFIG_PCIEASPM_POWERSAVE | 113 | #elif defined CONFIG_PCIEASPM_POWERSAVE |
83 | static int aspm_policy = POLICY_POWERSAVE; | 114 | static int aspm_policy = POLICY_POWERSAVE; |
115 | #elif defined CONFIG_PCIEASPM_POWER_SUPERSAVE | ||
116 | static int aspm_policy = POLICY_POWER_SUPERSAVE; | ||
84 | #else | 117 | #else |
85 | static int aspm_policy; | 118 | static int aspm_policy; |
86 | #endif | 119 | #endif |
@@ -88,7 +121,8 @@ static int aspm_policy; | |||
88 | static const char *policy_str[] = { | 121 | static const char *policy_str[] = { |
89 | [POLICY_DEFAULT] = "default", | 122 | [POLICY_DEFAULT] = "default", |
90 | [POLICY_PERFORMANCE] = "performance", | 123 | [POLICY_PERFORMANCE] = "performance", |
91 | [POLICY_POWERSAVE] = "powersave" | 124 | [POLICY_POWERSAVE] = "powersave", |
125 | [POLICY_POWER_SUPERSAVE] = "powersupersave" | ||
92 | }; | 126 | }; |
93 | 127 | ||
94 | #define LINK_RETRAIN_TIMEOUT HZ | 128 | #define LINK_RETRAIN_TIMEOUT HZ |
@@ -101,6 +135,9 @@ static int policy_to_aspm_state(struct pcie_link_state *link) | |||
101 | return 0; | 135 | return 0; |
102 | case POLICY_POWERSAVE: | 136 | case POLICY_POWERSAVE: |
103 | /* Enable ASPM L0s/L1 */ | 137 | /* Enable ASPM L0s/L1 */ |
138 | return (ASPM_STATE_L0S | ASPM_STATE_L1); | ||
139 | case POLICY_POWER_SUPERSAVE: | ||
140 | /* Enable Everything */ | ||
104 | return ASPM_STATE_ALL; | 141 | return ASPM_STATE_ALL; |
105 | case POLICY_DEFAULT: | 142 | case POLICY_DEFAULT: |
106 | return link->aspm_default; | 143 | return link->aspm_default; |
@@ -115,7 +152,8 @@ static int policy_to_clkpm_state(struct pcie_link_state *link) | |||
115 | /* Disable ASPM and Clock PM */ | 152 | /* Disable ASPM and Clock PM */ |
116 | return 0; | 153 | return 0; |
117 | case POLICY_POWERSAVE: | 154 | case POLICY_POWERSAVE: |
118 | /* Disable Clock PM */ | 155 | case POLICY_POWER_SUPERSAVE: |
156 | /* Enable Clock PM */ | ||
119 | return 1; | 157 | return 1; |
120 | case POLICY_DEFAULT: | 158 | case POLICY_DEFAULT: |
121 | return link->clkpm_default; | 159 | return link->clkpm_default; |
@@ -278,11 +316,33 @@ static u32 calc_l1_acceptable(u32 encoding) | |||
278 | return (1000 << encoding); | 316 | return (1000 << encoding); |
279 | } | 317 | } |
280 | 318 | ||
319 | /* Convert L1SS T_pwr encoding to usec */ | ||
320 | static u32 calc_l1ss_pwron(struct pci_dev *pdev, u32 scale, u32 val) | ||
321 | { | ||
322 | switch (scale) { | ||
323 | case 0: | ||
324 | return val * 2; | ||
325 | case 1: | ||
326 | return val * 10; | ||
327 | case 2: | ||
328 | return val * 100; | ||
329 | } | ||
330 | dev_err(&pdev->dev, "%s: Invalid T_PwrOn scale: %u\n", | ||
331 | __func__, scale); | ||
332 | return 0; | ||
333 | } | ||
334 | |||
281 | struct aspm_register_info { | 335 | struct aspm_register_info { |
282 | u32 support:2; | 336 | u32 support:2; |
283 | u32 enabled:2; | 337 | u32 enabled:2; |
284 | u32 latency_encoding_l0s; | 338 | u32 latency_encoding_l0s; |
285 | u32 latency_encoding_l1; | 339 | u32 latency_encoding_l1; |
340 | |||
341 | /* L1 substates */ | ||
342 | u32 l1ss_cap_ptr; | ||
343 | u32 l1ss_cap; | ||
344 | u32 l1ss_ctl1; | ||
345 | u32 l1ss_ctl2; | ||
286 | }; | 346 | }; |
287 | 347 | ||
288 | static void pcie_get_aspm_reg(struct pci_dev *pdev, | 348 | static void pcie_get_aspm_reg(struct pci_dev *pdev, |
@@ -297,6 +357,22 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev, | |||
297 | info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; | 357 | info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; |
298 | pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, ®16); | 358 | pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, ®16); |
299 | info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; | 359 | info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; |
360 | |||
361 | /* Read L1 PM substate capabilities */ | ||
362 | info->l1ss_cap = info->l1ss_ctl1 = info->l1ss_ctl2 = 0; | ||
363 | info->l1ss_cap_ptr = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS); | ||
364 | if (!info->l1ss_cap_ptr) | ||
365 | return; | ||
366 | pci_read_config_dword(pdev, info->l1ss_cap_ptr + PCI_L1SS_CAP, | ||
367 | &info->l1ss_cap); | ||
368 | if (!(info->l1ss_cap & PCI_L1SS_CAP_L1_PM_SS)) { | ||
369 | info->l1ss_cap = 0; | ||
370 | return; | ||
371 | } | ||
372 | pci_read_config_dword(pdev, info->l1ss_cap_ptr + PCI_L1SS_CTL1, | ||
373 | &info->l1ss_ctl1); | ||
374 | pci_read_config_dword(pdev, info->l1ss_cap_ptr + PCI_L1SS_CTL2, | ||
375 | &info->l1ss_ctl2); | ||
300 | } | 376 | } |
301 | 377 | ||
302 | static void pcie_aspm_check_latency(struct pci_dev *endpoint) | 378 | static void pcie_aspm_check_latency(struct pci_dev *endpoint) |
@@ -327,6 +403,14 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint) | |||
327 | * Check L1 latency. | 403 | * Check L1 latency. |
328 | * Every switch on the path to root complex need 1 | 404 | * Every switch on the path to root complex need 1 |
329 | * more microsecond for L1. Spec doesn't mention L0s. | 405 | * more microsecond for L1. Spec doesn't mention L0s. |
406 | * | ||
407 | * The exit latencies for L1 substates are not advertised | ||
408 | * by a device. Since the spec also doesn't mention a way | ||
409 | * to determine max latencies introduced by enabling L1 | ||
410 | * substates on the components, it is not clear how to do | ||
411 | * a L1 substate exit latency check. We assume that the | ||
412 | * L1 exit latencies advertised by a device include L1 | ||
413 | * substate latencies (and hence do not do any check). | ||
330 | */ | 414 | */ |
331 | latency = max_t(u32, link->latency_up.l1, link->latency_dw.l1); | 415 | latency = max_t(u32, link->latency_up.l1, link->latency_dw.l1); |
332 | if ((link->aspm_capable & ASPM_STATE_L1) && | 416 | if ((link->aspm_capable & ASPM_STATE_L1) && |
@@ -338,6 +422,60 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint) | |||
338 | } | 422 | } |
339 | } | 423 | } |
340 | 424 | ||
425 | /* | ||
426 | * The L1 PM substate capability is only implemented in function 0 in a | ||
427 | * multi function device. | ||
428 | */ | ||
429 | static struct pci_dev *pci_function_0(struct pci_bus *linkbus) | ||
430 | { | ||
431 | struct pci_dev *child; | ||
432 | |||
433 | list_for_each_entry(child, &linkbus->devices, bus_list) | ||
434 | if (PCI_FUNC(child->devfn) == 0) | ||
435 | return child; | ||
436 | return NULL; | ||
437 | } | ||
438 | |||
439 | /* Calculate L1.2 PM substate timing parameters */ | ||
440 | static void aspm_calc_l1ss_info(struct pcie_link_state *link, | ||
441 | struct aspm_register_info *upreg, | ||
442 | struct aspm_register_info *dwreg) | ||
443 | { | ||
444 | u32 val1, val2, scale1, scale2; | ||
445 | |||
446 | link->l1ss.up_cap_ptr = upreg->l1ss_cap_ptr; | ||
447 | link->l1ss.dw_cap_ptr = dwreg->l1ss_cap_ptr; | ||
448 | link->l1ss.ctl1 = link->l1ss.ctl2 = 0; | ||
449 | |||
450 | if (!(link->aspm_support & ASPM_STATE_L1_2_MASK)) | ||
451 | return; | ||
452 | |||
453 | /* Choose the greater of the two T_cmn_mode_rstr_time */ | ||
454 | val1 = (upreg->l1ss_cap >> 8) & 0xFF; | ||
455 | val2 = (upreg->l1ss_cap >> 8) & 0xFF; | ||
456 | if (val1 > val2) | ||
457 | link->l1ss.ctl1 |= val1 << 8; | ||
458 | else | ||
459 | link->l1ss.ctl1 |= val2 << 8; | ||
460 | /* | ||
461 | * We currently use LTR L1.2 threshold to be fixed constant picked from | ||
462 | * Intel's coreboot. | ||
463 | */ | ||
464 | link->l1ss.ctl1 |= LTR_L1_2_THRESHOLD_BITS; | ||
465 | |||
466 | /* Choose the greater of the two T_pwr_on */ | ||
467 | val1 = (upreg->l1ss_cap >> 19) & 0x1F; | ||
468 | scale1 = (upreg->l1ss_cap >> 16) & 0x03; | ||
469 | val2 = (dwreg->l1ss_cap >> 19) & 0x1F; | ||
470 | scale2 = (dwreg->l1ss_cap >> 16) & 0x03; | ||
471 | |||
472 | if (calc_l1ss_pwron(link->pdev, scale1, val1) > | ||
473 | calc_l1ss_pwron(link->downstream, scale2, val2)) | ||
474 | link->l1ss.ctl2 |= scale1 | (val1 << 3); | ||
475 | else | ||
476 | link->l1ss.ctl2 |= scale2 | (val2 << 3); | ||
477 | } | ||
478 | |||
341 | static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | 479 | static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) |
342 | { | 480 | { |
343 | struct pci_dev *child, *parent = link->pdev; | 481 | struct pci_dev *child, *parent = link->pdev; |
@@ -353,8 +491,9 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
353 | 491 | ||
354 | /* Get upstream/downstream components' register state */ | 492 | /* Get upstream/downstream components' register state */ |
355 | pcie_get_aspm_reg(parent, &upreg); | 493 | pcie_get_aspm_reg(parent, &upreg); |
356 | child = list_entry(linkbus->devices.next, struct pci_dev, bus_list); | 494 | child = pci_function_0(linkbus); |
357 | pcie_get_aspm_reg(child, &dwreg); | 495 | pcie_get_aspm_reg(child, &dwreg); |
496 | link->downstream = child; | ||
358 | 497 | ||
359 | /* | 498 | /* |
360 | * If ASPM not supported, don't mess with the clocks and link, | 499 | * If ASPM not supported, don't mess with the clocks and link, |
@@ -397,6 +536,28 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
397 | link->latency_up.l1 = calc_l1_latency(upreg.latency_encoding_l1); | 536 | link->latency_up.l1 = calc_l1_latency(upreg.latency_encoding_l1); |
398 | link->latency_dw.l1 = calc_l1_latency(dwreg.latency_encoding_l1); | 537 | link->latency_dw.l1 = calc_l1_latency(dwreg.latency_encoding_l1); |
399 | 538 | ||
539 | /* Setup L1 substate */ | ||
540 | if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_ASPM_L1_1) | ||
541 | link->aspm_support |= ASPM_STATE_L1_1; | ||
542 | if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_ASPM_L1_2) | ||
543 | link->aspm_support |= ASPM_STATE_L1_2; | ||
544 | if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_1) | ||
545 | link->aspm_support |= ASPM_STATE_L1_1_PCIPM; | ||
546 | if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_2) | ||
547 | link->aspm_support |= ASPM_STATE_L1_2_PCIPM; | ||
548 | |||
549 | if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_1) | ||
550 | link->aspm_enabled |= ASPM_STATE_L1_1; | ||
551 | if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_2) | ||
552 | link->aspm_enabled |= ASPM_STATE_L1_2; | ||
553 | if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_1) | ||
554 | link->aspm_enabled |= ASPM_STATE_L1_1_PCIPM; | ||
555 | if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2) | ||
556 | link->aspm_enabled |= ASPM_STATE_L1_2_PCIPM; | ||
557 | |||
558 | if (link->aspm_support & ASPM_STATE_L1SS) | ||
559 | aspm_calc_l1ss_info(link, &upreg, &dwreg); | ||
560 | |||
400 | /* Save default state */ | 561 | /* Save default state */ |
401 | link->aspm_default = link->aspm_enabled; | 562 | link->aspm_default = link->aspm_enabled; |
402 | 563 | ||
@@ -435,6 +596,92 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
435 | } | 596 | } |
436 | } | 597 | } |
437 | 598 | ||
599 | static void pci_clear_and_set_dword(struct pci_dev *pdev, int pos, | ||
600 | u32 clear, u32 set) | ||
601 | { | ||
602 | u32 val; | ||
603 | |||
604 | pci_read_config_dword(pdev, pos, &val); | ||
605 | val &= ~clear; | ||
606 | val |= set; | ||
607 | pci_write_config_dword(pdev, pos, val); | ||
608 | } | ||
609 | |||
610 | /* Configure the ASPM L1 substates */ | ||
611 | static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state) | ||
612 | { | ||
613 | u32 val, enable_req; | ||
614 | struct pci_dev *child = link->downstream, *parent = link->pdev; | ||
615 | u32 up_cap_ptr = link->l1ss.up_cap_ptr; | ||
616 | u32 dw_cap_ptr = link->l1ss.dw_cap_ptr; | ||
617 | |||
618 | enable_req = (link->aspm_enabled ^ state) & state; | ||
619 | |||
620 | /* | ||
621 | * Here are the rules specified in the PCIe spec for enabling L1SS: | ||
622 | * - When enabling L1.x, enable bit at parent first, then at child | ||
623 | * - When disabling L1.x, disable bit at child first, then at parent | ||
624 | * - When enabling ASPM L1.x, need to disable L1 | ||
625 | * (at child followed by parent). | ||
626 | * - The ASPM/PCIPM L1.2 must be disabled while programming timing | ||
627 | * parameters | ||
628 | * | ||
629 | * To keep it simple, disable all L1SS bits first, and later enable | ||
630 | * what is needed. | ||
631 | */ | ||
632 | |||
633 | /* Disable all L1 substates */ | ||
634 | pci_clear_and_set_dword(child, dw_cap_ptr + PCI_L1SS_CTL1, | ||
635 | PCI_L1SS_CTL1_L1SS_MASK, 0); | ||
636 | pci_clear_and_set_dword(parent, up_cap_ptr + PCI_L1SS_CTL1, | ||
637 | PCI_L1SS_CTL1_L1SS_MASK, 0); | ||
638 | /* | ||
639 | * If needed, disable L1, and it gets enabled later | ||
640 | * in pcie_config_aspm_link(). | ||
641 | */ | ||
642 | if (enable_req & (ASPM_STATE_L1_1 | ASPM_STATE_L1_2)) { | ||
643 | pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL, | ||
644 | PCI_EXP_LNKCTL_ASPM_L1, 0); | ||
645 | pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL, | ||
646 | PCI_EXP_LNKCTL_ASPM_L1, 0); | ||
647 | } | ||
648 | |||
649 | if (enable_req & ASPM_STATE_L1_2_MASK) { | ||
650 | |||
651 | /* Program T_pwr_on in both ports */ | ||
652 | pci_write_config_dword(parent, up_cap_ptr + PCI_L1SS_CTL2, | ||
653 | link->l1ss.ctl2); | ||
654 | pci_write_config_dword(child, dw_cap_ptr + PCI_L1SS_CTL2, | ||
655 | link->l1ss.ctl2); | ||
656 | |||
657 | /* Program T_cmn_mode in parent */ | ||
658 | pci_clear_and_set_dword(parent, up_cap_ptr + PCI_L1SS_CTL1, | ||
659 | 0xFF00, link->l1ss.ctl1); | ||
660 | |||
661 | /* Program LTR L1.2 threshold in both ports */ | ||
662 | pci_clear_and_set_dword(parent, dw_cap_ptr + PCI_L1SS_CTL1, | ||
663 | 0xE3FF0000, link->l1ss.ctl1); | ||
664 | pci_clear_and_set_dword(child, dw_cap_ptr + PCI_L1SS_CTL1, | ||
665 | 0xE3FF0000, link->l1ss.ctl1); | ||
666 | } | ||
667 | |||
668 | val = 0; | ||
669 | if (state & ASPM_STATE_L1_1) | ||
670 | val |= PCI_L1SS_CTL1_ASPM_L1_1; | ||
671 | if (state & ASPM_STATE_L1_2) | ||
672 | val |= PCI_L1SS_CTL1_ASPM_L1_2; | ||
673 | if (state & ASPM_STATE_L1_1_PCIPM) | ||
674 | val |= PCI_L1SS_CTL1_PCIPM_L1_1; | ||
675 | if (state & ASPM_STATE_L1_2_PCIPM) | ||
676 | val |= PCI_L1SS_CTL1_PCIPM_L1_2; | ||
677 | |||
678 | /* Enable what we need to enable */ | ||
679 | pci_clear_and_set_dword(parent, up_cap_ptr + PCI_L1SS_CTL1, | ||
680 | PCI_L1SS_CAP_L1_PM_SS, val); | ||
681 | pci_clear_and_set_dword(child, dw_cap_ptr + PCI_L1SS_CTL1, | ||
682 | PCI_L1SS_CAP_L1_PM_SS, val); | ||
683 | } | ||
684 | |||
438 | static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) | 685 | static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) |
439 | { | 686 | { |
440 | pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, | 687 | pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, |
@@ -444,11 +691,23 @@ static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) | |||
444 | static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) | 691 | static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) |
445 | { | 692 | { |
446 | u32 upstream = 0, dwstream = 0; | 693 | u32 upstream = 0, dwstream = 0; |
447 | struct pci_dev *child, *parent = link->pdev; | 694 | struct pci_dev *child = link->downstream, *parent = link->pdev; |
448 | struct pci_bus *linkbus = parent->subordinate; | 695 | struct pci_bus *linkbus = parent->subordinate; |
449 | 696 | ||
450 | /* Nothing to do if the link is already in the requested state */ | 697 | /* Enable only the states that were not explicitly disabled */ |
451 | state &= (link->aspm_capable & ~link->aspm_disable); | 698 | state &= (link->aspm_capable & ~link->aspm_disable); |
699 | |||
700 | /* Can't enable any substates if L1 is not enabled */ | ||
701 | if (!(state & ASPM_STATE_L1)) | ||
702 | state &= ~ASPM_STATE_L1SS; | ||
703 | |||
704 | /* Spec says both ports must be in D0 before enabling PCI PM substates*/ | ||
705 | if (parent->current_state != PCI_D0 || child->current_state != PCI_D0) { | ||
706 | state &= ~ASPM_STATE_L1_SS_PCIPM; | ||
707 | state |= (link->aspm_enabled & ASPM_STATE_L1_SS_PCIPM); | ||
708 | } | ||
709 | |||
710 | /* Nothing to do if the link is already in the requested state */ | ||
452 | if (link->aspm_enabled == state) | 711 | if (link->aspm_enabled == state) |
453 | return; | 712 | return; |
454 | /* Convert ASPM state to upstream/downstream ASPM register state */ | 713 | /* Convert ASPM state to upstream/downstream ASPM register state */ |
@@ -460,6 +719,10 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) | |||
460 | upstream |= PCI_EXP_LNKCTL_ASPM_L1; | 719 | upstream |= PCI_EXP_LNKCTL_ASPM_L1; |
461 | dwstream |= PCI_EXP_LNKCTL_ASPM_L1; | 720 | dwstream |= PCI_EXP_LNKCTL_ASPM_L1; |
462 | } | 721 | } |
722 | |||
723 | if (link->aspm_capable & ASPM_STATE_L1SS) | ||
724 | pcie_config_aspm_l1ss(link, state); | ||
725 | |||
463 | /* | 726 | /* |
464 | * Spec 2.0 suggests all functions should be configured the | 727 | * Spec 2.0 suggests all functions should be configured the |
465 | * same setting for ASPM. Enabling ASPM L1 should be done in | 728 | * same setting for ASPM. Enabling ASPM L1 should be done in |
@@ -612,7 +875,8 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
612 | * the BIOS's expectation, we'll do so once pci_enable_device() is | 875 | * the BIOS's expectation, we'll do so once pci_enable_device() is |
613 | * called. | 876 | * called. |
614 | */ | 877 | */ |
615 | if (aspm_policy != POLICY_POWERSAVE) { | 878 | if (aspm_policy != POLICY_POWERSAVE && |
879 | aspm_policy != POLICY_POWER_SUPERSAVE) { | ||
616 | pcie_config_aspm_path(link); | 880 | pcie_config_aspm_path(link); |
617 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); | 881 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); |
618 | } | 882 | } |
@@ -712,7 +976,8 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) | |||
712 | if (aspm_disabled || !link) | 976 | if (aspm_disabled || !link) |
713 | return; | 977 | return; |
714 | 978 | ||
715 | if (aspm_policy != POLICY_POWERSAVE) | 979 | if (aspm_policy != POLICY_POWERSAVE && |
980 | aspm_policy != POLICY_POWER_SUPERSAVE) | ||
716 | return; | 981 | return; |
717 | 982 | ||
718 | down_read(&pci_bus_sem); | 983 | down_read(&pci_bus_sem); |
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 174d1147081b..f48d06e2bb4d 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h | |||
@@ -682,6 +682,7 @@ | |||
682 | #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ | 682 | #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ |
683 | #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ | 683 | #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ |
684 | #define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ | 684 | #define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ |
685 | #define PCI_EXT_CAP_ID_L1SS 0x1E /* L1 PM Substates */ | ||
685 | #define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */ | 686 | #define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */ |
686 | #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM | 687 | #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM |
687 | 688 | ||
@@ -985,4 +986,19 @@ | |||
985 | #define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */ | 986 | #define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */ |
986 | #define PCI_PTM_CTRL_ROOT 0x00000002 /* Root select */ | 987 | #define PCI_PTM_CTRL_ROOT 0x00000002 /* Root select */ |
987 | 988 | ||
989 | /* L1 PM Substates */ | ||
990 | #define PCI_L1SS_CAP 4 /* capability register */ | ||
991 | #define PCI_L1SS_CAP_PCIPM_L1_2 1 /* PCI PM L1.2 Support */ | ||
992 | #define PCI_L1SS_CAP_PCIPM_L1_1 2 /* PCI PM L1.1 Support */ | ||
993 | #define PCI_L1SS_CAP_ASPM_L1_2 4 /* ASPM L1.2 Support */ | ||
994 | #define PCI_L1SS_CAP_ASPM_L1_1 8 /* ASPM L1.1 Support */ | ||
995 | #define PCI_L1SS_CAP_L1_PM_SS 16 /* L1 PM Substates Support */ | ||
996 | #define PCI_L1SS_CTL1 8 /* Control Register 1 */ | ||
997 | #define PCI_L1SS_CTL1_PCIPM_L1_2 1 /* PCI PM L1.2 Enable */ | ||
998 | #define PCI_L1SS_CTL1_PCIPM_L1_1 2 /* PCI PM L1.1 Support */ | ||
999 | #define PCI_L1SS_CTL1_ASPM_L1_2 4 /* ASPM L1.2 Support */ | ||
1000 | #define PCI_L1SS_CTL1_ASPM_L1_1 8 /* ASPM L1.1 Support */ | ||
1001 | #define PCI_L1SS_CTL1_L1SS_MASK 0x0000000F | ||
1002 | #define PCI_L1SS_CTL2 0xC /* Control Register 2 */ | ||
1003 | |||
988 | #endif /* LINUX_PCI_REGS_H */ | 1004 | #endif /* LINUX_PCI_REGS_H */ |