linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] PCI/ASPM: Add helper to enable ASPM link
@ 2020-09-30  8:24 Kai-Heng Feng
  2020-09-30  8:24 ` [PATCH 2/2] PCI: vmd: Enable ASPM for mobile platforms Kai-Heng Feng
  0 siblings, 1 reply; 11+ messages in thread
From: Kai-Heng Feng @ 2020-09-30  8:24 UTC (permalink / raw)
  To: bhelgaas, jonathan.derrick
  Cc: Kai-Heng Feng, Heiner Kallweit, Rafael J. Wysocki, Chris Packham,
	Yicong Yang, open list:PCI SUBSYSTEM, open list

Platform firmware may not be able to access config space to program
ASPM. For instance, devices behind Intel VMD are not configured by the
BIOS.

So add a helper to let drivers have an option to enable ASPM.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
 drivers/pci/pcie/aspm.c | 73 ++++++++++++++++++++++++++++++-----------
 include/linux/pci.h     |  7 ++++
 2 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 253c30cc1967..b5ac6a99e016 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1080,6 +1080,58 @@ static struct pcie_link_state *pcie_aspm_get_link(struct pci_dev *pdev)
 	return bridge->link_state;
 }
 
+static u32 pcie_aspm_convert_state(int state)
+{
+	u32 aspm = 0;
+
+	if (state & PCIE_LINK_STATE_L0S)
+		aspm |= ASPM_STATE_L0S;
+	if (state & PCIE_LINK_STATE_L1)
+		/* L1 PM substates require L1 */
+		aspm |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
+	if (state & PCIE_LINK_STATE_L1_1)
+		aspm |= ASPM_STATE_L1_1;
+	if (state & PCIE_LINK_STATE_L1_2)
+		aspm |= ASPM_STATE_L1_2;
+	if (state & PCIE_LINK_STATE_L1_1_PCIPM)
+		aspm |= ASPM_STATE_L1_1_PCIPM;
+	if (state & PCIE_LINK_STATE_L1_2_PCIPM)
+		aspm |= ASPM_STATE_L1_2_PCIPM;
+
+	return aspm;
+}
+
+static void pci_set_link_state(struct pci_dev *pdev, bool enable, int state)
+{
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+
+	mutex_lock(&aspm_lock);
+	if (enable)
+		link->aspm_default = pcie_aspm_convert_state(state);
+	else
+		link->aspm_disable = pcie_aspm_convert_state(state);
+	pcie_config_aspm_link(link, policy_to_aspm_state(link));
+
+	if (state & PCIE_LINK_STATE_CLKPM) {
+		link->clkpm_default = enable;
+		link->clkpm_disable = !enable;
+	}
+	pcie_set_clkpm(link, policy_to_clkpm_state(link));
+	mutex_unlock(&aspm_lock);
+}
+
+int pci_enable_link_state(struct pci_dev *pdev, int state)
+{
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+
+	if (!link)
+		return -EINVAL;
+
+	pci_set_link_state(pdev, true, state);
+	return 0;
+}
+EXPORT_SYMBOL(pci_enable_link_state);
+
 static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
 {
 	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
@@ -1101,26 +1153,7 @@ static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
 
 	if (sem)
 		down_read(&pci_bus_sem);
-	mutex_lock(&aspm_lock);
-	if (state & PCIE_LINK_STATE_L0S)
-		link->aspm_disable |= ASPM_STATE_L0S;
-	if (state & PCIE_LINK_STATE_L1)
-		/* L1 PM substates require L1 */
-		link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
-	if (state & PCIE_LINK_STATE_L1_1)
-		link->aspm_disable |= ASPM_STATE_L1_1;
-	if (state & PCIE_LINK_STATE_L1_2)
-		link->aspm_disable |= ASPM_STATE_L1_2;
-	if (state & PCIE_LINK_STATE_L1_1_PCIPM)
-		link->aspm_disable |= ASPM_STATE_L1_1_PCIPM;
-	if (state & PCIE_LINK_STATE_L1_2_PCIPM)
-		link->aspm_disable |= ASPM_STATE_L1_2_PCIPM;
-	pcie_config_aspm_link(link, policy_to_aspm_state(link));
-
-	if (state & PCIE_LINK_STATE_CLKPM)
-		link->clkpm_disable = 1;
-	pcie_set_clkpm(link, policy_to_clkpm_state(link));
-	mutex_unlock(&aspm_lock);
+	pci_set_link_state(pdev, false, state);
 	if (sem)
 		up_read(&pci_bus_sem);
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 835530605c0d..a6a7830ec258 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1568,14 +1568,21 @@ extern bool pcie_ports_native;
 #define PCIE_LINK_STATE_L1_2		BIT(4)
 #define PCIE_LINK_STATE_L1_1_PCIPM	BIT(5)
 #define PCIE_LINK_STATE_L1_2_PCIPM	BIT(6)
+#define PCIE_LINK_STATE_ALL		(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |\
+					 PCIE_LINK_STATE_CLKPM | PCIE_LINK_STATE_L1_1 |\
+					 PCIE_LINK_STATE_L1_2 | PCIE_LINK_STATE_L1_1_PCIPM |\
+					 PCIE_LINK_STATE_L1_2_PCIPM)
 
 #ifdef CONFIG_PCIEASPM
+int pci_enable_link_state(struct pci_dev *pdev, int state);
 int pci_disable_link_state(struct pci_dev *pdev, int state);
 int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
 void pcie_no_aspm(void);
 bool pcie_aspm_support_enabled(void);
 bool pcie_aspm_enabled(struct pci_dev *pdev);
 #else
+static inline int pci_enable_link_state(struct pci_dev *pdev, int state)
+{ return 0; }
 static inline int pci_disable_link_state(struct pci_dev *pdev, int state)
 { return 0; }
 static inline int pci_disable_link_state_locked(struct pci_dev *pdev, int state)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-10-09 14:34 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-30  8:24 [PATCH 1/2] PCI/ASPM: Add helper to enable ASPM link Kai-Heng Feng
2020-09-30  8:24 ` [PATCH 2/2] PCI: vmd: Enable ASPM for mobile platforms Kai-Heng Feng
2020-10-02 22:18   ` Bjorn Helgaas
2020-10-05 18:40     ` Kai-Heng Feng
2020-10-05 19:19       ` Bjorn Helgaas
2020-10-07  4:26         ` Kai-Heng Feng
2020-10-07  9:28           ` Ian Kumlien
2020-10-07 13:30           ` Bjorn Helgaas
2020-10-07 13:44             ` Ian Kumlien
2020-10-08  4:19             ` Kai-Heng Feng
2020-10-09 14:34               ` Ian Kumlien

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).