aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajat Jain <rajatja@google.com>2017-01-03 01:34:11 -0500
committerBjorn Helgaas <bhelgaas@google.com>2017-02-14 18:43:51 -0500
commitb2103ccbb67e3ef0f7a75d21c989f9614ddbcaca (patch)
treef4690841da7a101ab9ecd4a96e3968ec5c2d017b
parent0fc1223f0e77a748f7040562faaa7027f7db71ca (diff)
PCI/ASPM: Add support for L1 substates
Add support for ASPM L1 substates. For details about L1 substates, see the PCIe r3.1 spec, which includes the ECN below in secs 5.5 and 7.33. Add macros for the 4 new L1 substates, and add a new ASPM "POWER_SUPERSAVE" policy that can be used to enable L1 substates on a system if desired. The new policy is in a sense, a superset of the existing POWERSAVE policy. The 4 policies are now: DEFAULT: Reads and uses whatever ASPM states BIOS enabled PERFORMANCE: Everything except L0 disabled. POWERSAVE: L0s and L1 enabled (but not L1 substates) POWER_SUPERSAVE: L0s + L1 + L1 substates also enabled [bhelgaas: add PCIe r3.1 spec reference] Link: https://pcisig.com/sites/default/files/specification_documents/ECN_L1_PM_Substates_with_CLKREQ_31_May_2013_Rev10a.pdf Signed-off-by: Rajat Jain <rajatja@google.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/pcie/Kconfig8
-rw-r--r--drivers/pci/pcie/aspm.c39
2 files changed, 37 insertions, 10 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
74config 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
74config PCIEASPM_PERFORMANCE 82config 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..a74fb3a8333f 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -30,8 +30,17 @@
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)
35 44
36struct aspm_latency { 45struct aspm_latency {
37 u32 l0s; /* L0s latency (nsec) */ 46 u32 l0s; /* L0s latency (nsec) */
@@ -47,11 +56,11 @@ struct pcie_link_state {
47 struct list_head link; /* node in parent's children list */ 56 struct list_head link; /* node in parent's children list */
48 57
49 /* ASPM state */ 58 /* ASPM state */
50 u32 aspm_support:3; /* Supported ASPM state */ 59 u32 aspm_support:7; /* Supported ASPM state */
51 u32 aspm_enabled:3; /* Enabled ASPM state */ 60 u32 aspm_enabled:7; /* Enabled ASPM state */
52 u32 aspm_capable:3; /* Capable ASPM state with latency */ 61 u32 aspm_capable:7; /* Capable ASPM state with latency */
53 u32 aspm_default:3; /* Default ASPM state by BIOS */ 62 u32 aspm_default:7; /* Default ASPM state by BIOS */
54 u32 aspm_disable:3; /* Disabled ASPM state */ 63 u32 aspm_disable:7; /* Disabled ASPM state */
55 64
56 /* Clock PM state */ 65 /* Clock PM state */
57 u32 clkpm_capable:1; /* Clock PM capable? */ 66 u32 clkpm_capable:1; /* Clock PM capable? */
@@ -76,11 +85,14 @@ static LIST_HEAD(link_list);
76#define POLICY_DEFAULT 0 /* BIOS default setting */ 85#define POLICY_DEFAULT 0 /* BIOS default setting */
77#define POLICY_PERFORMANCE 1 /* high performance */ 86#define POLICY_PERFORMANCE 1 /* high performance */
78#define POLICY_POWERSAVE 2 /* high power saving */ 87#define POLICY_POWERSAVE 2 /* high power saving */
88#define POLICY_POWER_SUPERSAVE 3 /* possibly even more power saving */
79 89
80#ifdef CONFIG_PCIEASPM_PERFORMANCE 90#ifdef CONFIG_PCIEASPM_PERFORMANCE
81static int aspm_policy = POLICY_PERFORMANCE; 91static int aspm_policy = POLICY_PERFORMANCE;
82#elif defined CONFIG_PCIEASPM_POWERSAVE 92#elif defined CONFIG_PCIEASPM_POWERSAVE
83static int aspm_policy = POLICY_POWERSAVE; 93static int aspm_policy = POLICY_POWERSAVE;
94#elif defined CONFIG_PCIEASPM_POWER_SUPERSAVE
95static int aspm_policy = POLICY_POWER_SUPERSAVE;
84#else 96#else
85static int aspm_policy; 97static int aspm_policy;
86#endif 98#endif
@@ -88,7 +100,8 @@ static int aspm_policy;
88static const char *policy_str[] = { 100static const char *policy_str[] = {
89 [POLICY_DEFAULT] = "default", 101 [POLICY_DEFAULT] = "default",
90 [POLICY_PERFORMANCE] = "performance", 102 [POLICY_PERFORMANCE] = "performance",
91 [POLICY_POWERSAVE] = "powersave" 103 [POLICY_POWERSAVE] = "powersave",
104 [POLICY_POWER_SUPERSAVE] = "powersupersave"
92}; 105};
93 106
94#define LINK_RETRAIN_TIMEOUT HZ 107#define LINK_RETRAIN_TIMEOUT HZ
@@ -101,6 +114,9 @@ static int policy_to_aspm_state(struct pcie_link_state *link)
101 return 0; 114 return 0;
102 case POLICY_POWERSAVE: 115 case POLICY_POWERSAVE:
103 /* Enable ASPM L0s/L1 */ 116 /* Enable ASPM L0s/L1 */
117 return (ASPM_STATE_L0S | ASPM_STATE_L1);
118 case POLICY_POWER_SUPERSAVE:
119 /* Enable Everything */
104 return ASPM_STATE_ALL; 120 return ASPM_STATE_ALL;
105 case POLICY_DEFAULT: 121 case POLICY_DEFAULT:
106 return link->aspm_default; 122 return link->aspm_default;
@@ -115,7 +131,8 @@ static int policy_to_clkpm_state(struct pcie_link_state *link)
115 /* Disable ASPM and Clock PM */ 131 /* Disable ASPM and Clock PM */
116 return 0; 132 return 0;
117 case POLICY_POWERSAVE: 133 case POLICY_POWERSAVE:
118 /* Disable Clock PM */ 134 case POLICY_POWER_SUPERSAVE:
135 /* Enable Clock PM */
119 return 1; 136 return 1;
120 case POLICY_DEFAULT: 137 case POLICY_DEFAULT:
121 return link->clkpm_default; 138 return link->clkpm_default;
@@ -612,7 +629,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 629 * the BIOS's expectation, we'll do so once pci_enable_device() is
613 * called. 630 * called.
614 */ 631 */
615 if (aspm_policy != POLICY_POWERSAVE) { 632 if (aspm_policy != POLICY_POWERSAVE &&
633 aspm_policy != POLICY_POWER_SUPERSAVE) {
616 pcie_config_aspm_path(link); 634 pcie_config_aspm_path(link);
617 pcie_set_clkpm(link, policy_to_clkpm_state(link)); 635 pcie_set_clkpm(link, policy_to_clkpm_state(link));
618 } 636 }
@@ -712,7 +730,8 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
712 if (aspm_disabled || !link) 730 if (aspm_disabled || !link)
713 return; 731 return;
714 732
715 if (aspm_policy != POLICY_POWERSAVE) 733 if (aspm_policy != POLICY_POWERSAVE &&
734 aspm_policy != POLICY_POWER_SUPERSAVE)
716 return; 735 return;
717 736
718 down_read(&pci_bus_sem); 737 down_read(&pci_bus_sem);