linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Rajat Jain <rajatja@google.com>
To: Bjorn Helgaas <bhelgaas@google.com>,
	Keith Busch <keith.busch@intel.com>,
	Andreas Ziegler <andreas.ziegler@fau.de>,
	Jonathan Yong <jonathan.yong@intel.com>,
	Shawn Lin <shawn.lin@rock-chips.com>,
	David Daney <david.daney@cavium.com>,
	Julia Lawall <Julia.Lawall@lip6.fr>,
	Ram Amrani <Ram.Amrani@cavium.com>,
	Doug Ledford <dledford@redhat.com>,
	Wang Sheng-Hui <shhuiw@foxmail.com>,
	linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Rajat Jain <rajatja@google.com>,
	Rajat Jain <rajatxjain@gmail.com>,
	Brian Norris <briannorris@google.com>
Subject: [PATCH 3/6] PCI/ASPM: Read and setup L1 substate capabilities
Date: Mon,  2 Jan 2017 22:34:12 -0800	[thread overview]
Message-ID: <1483425255-101923-4-git-send-email-rajatja@google.com> (raw)
In-Reply-To: <1483425255-101923-1-git-send-email-rajatja@google.com>

The PCIe spec says that only function 0 of a multi-function
downstream component would implement the capability structure.

This patch adds code to read the L1 substate capability structures
of upstream and downstream components of the link, and sets it up
in the device structure.

Signed-off-by: Rajat Jain <rajatja@google.com>
---
 drivers/pci/pcie/aspm.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 402c229..7a3ad85 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -49,6 +49,7 @@ struct aspm_latency {
 
 struct pcie_link_state {
 	struct pci_dev *pdev;		/* Upstream component of the Link */
+	struct pci_dev *downstream;	/* Downstream component, function 0 */
 	struct pcie_link_state *root;	/* pointer to the root port link */
 	struct pcie_link_state *parent;	/* pointer to the parent Link state */
 	struct list_head sibling;	/* node in link_list */
@@ -300,6 +301,12 @@ struct aspm_register_info {
 	u32 enabled:2;
 	u32 latency_encoding_l0s;
 	u32 latency_encoding_l1;
+
+	/* L1 substates */
+	u32 l1ss_cap_ptr;
+	u32 l1ss_cap;
+	u32 l1ss_ctl1;
+	u32 l1ss_ctl2;
 };
 
 static void pcie_get_aspm_reg(struct pci_dev *pdev,
@@ -314,6 +321,22 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev,
 	info->latency_encoding_l1  = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
 	pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &reg16);
 	info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC;
+
+	/* Read L1 PM substate capabilities */
+	info->l1ss_cap = info->l1ss_ctl1 = info->l1ss_ctl2 = 0;
+	info->l1ss_cap_ptr = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS);
+	if (!info->l1ss_cap_ptr)
+		return;
+	pci_read_config_dword(pdev, info->l1ss_cap_ptr + PCI_L1SS_CAP,
+			      &info->l1ss_cap);
+	if (!(info->l1ss_cap & PCI_L1SS_CAP_L1_PM_SS)) {
+		info->l1ss_cap = 0;
+		return;
+	}
+	pci_read_config_dword(pdev, info->l1ss_cap_ptr + PCI_L1SS_CTL1,
+			      &info->l1ss_ctl1);
+	pci_read_config_dword(pdev, info->l1ss_cap_ptr + PCI_L1SS_CTL2,
+			      &info->l1ss_ctl2);
 }
 
 static void pcie_aspm_check_latency(struct pci_dev *endpoint)
@@ -355,6 +378,20 @@ static void pcie_aspm_check_latency(struct pci_dev *endpoint)
 	}
 }
 
+/*
+ * The L1 PM substate capability is only implemented in function 0 in a
+ * multi function device.
+ */
+static inline struct pci_dev *pci_function_0(struct pci_bus *linkbus)
+{
+	struct pci_dev *child;
+
+	list_for_each_entry(child, &linkbus->devices, bus_list)
+		if (PCI_FUNC(child->devfn) == 0)
+			return child;
+	return NULL;
+}
+
 static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 {
 	struct pci_dev *child, *parent = link->pdev;
@@ -370,8 +407,9 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 
 	/* Get upstream/downstream components' register state */
 	pcie_get_aspm_reg(parent, &upreg);
-	child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
+	child = pci_function_0(linkbus);
 	pcie_get_aspm_reg(child, &dwreg);
+	link->downstream = child;
 
 	/*
 	 * If ASPM not supported, don't mess with the clocks and link,
@@ -414,6 +452,25 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
 	link->latency_up.l1 = calc_l1_latency(upreg.latency_encoding_l1);
 	link->latency_dw.l1 = calc_l1_latency(dwreg.latency_encoding_l1);
 
+	/* Setup L1 substate */
+	if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_ASPM_L1_1)
+		link->aspm_support |= ASPM_STATE_L1_1;
+	if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_ASPM_L1_2)
+		link->aspm_support |= ASPM_STATE_L1_2;
+	if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_1)
+		link->aspm_support |= ASPM_STATE_L1_1_PCIPM;
+	if (upreg.l1ss_cap & dwreg.l1ss_cap & PCI_L1SS_CAP_PCIPM_L1_2)
+		link->aspm_support |= ASPM_STATE_L1_2_PCIPM;
+
+	if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_1)
+		link->aspm_enabled |= ASPM_STATE_L1_1;
+	if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_ASPM_L1_2)
+		link->aspm_enabled |= ASPM_STATE_L1_2;
+	if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_1)
+		link->aspm_enabled |= ASPM_STATE_L1_1_PCIPM;
+	if (upreg.l1ss_ctl1 & dwreg.l1ss_ctl1 & PCI_L1SS_CTL1_PCIPM_L1_2)
+		link->aspm_enabled |= ASPM_STATE_L1_2_PCIPM;
+
 	/* Save default state */
 	link->aspm_default = link->aspm_enabled;
 
-- 
2.8.0.rc3.226.g39d4020

  parent reply	other threads:[~2017-01-03  6:34 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-03  6:34 [PATCH 0/6] PCI/ASPM: Add PCIe L1 PM substate support Rajat Jain
2017-01-03  6:34 ` [PATCH 1/6] PCI: Add L1 substate capability structure register definitions Rajat Jain
2017-01-03  6:34 ` [PATCH 2/6] PCI/ASPM: Introduce L1 substates and a Kconfig for it Rajat Jain
2017-01-03  6:34 ` Rajat Jain [this message]
2017-01-03  6:34 ` [PATCH 4/6] PCI/ASPM: Calculate and save the L1.2 timing parameters Rajat Jain
2017-01-03  6:34 ` [PATCH 5/6] PCI/ASPM: Actually configure the L1 substate settings to the device Rajat Jain
2017-03-08 18:44   ` James Morse
2017-03-08 22:39     ` Bjorn Helgaas
2017-03-08 23:08       ` Rajat Jain
2017-03-09 11:00         ` James Morse
2017-01-03  6:34 ` [PATCH 6/6] PCI/ASPM: Add comment about L1 substate latency Rajat Jain
2017-02-14 23:45 ` [PATCH 0/6] PCI/ASPM: Add PCIe L1 PM substate support Bjorn Helgaas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1483425255-101923-4-git-send-email-rajatja@google.com \
    --to=rajatja@google.com \
    --cc=Julia.Lawall@lip6.fr \
    --cc=Ram.Amrani@cavium.com \
    --cc=andreas.ziegler@fau.de \
    --cc=bhelgaas@google.com \
    --cc=briannorris@google.com \
    --cc=david.daney@cavium.com \
    --cc=dledford@redhat.com \
    --cc=jonathan.yong@intel.com \
    --cc=keith.busch@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=rajatxjain@gmail.com \
    --cc=shawn.lin@rock-chips.com \
    --cc=shhuiw@foxmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).