From patchwork Tue Jan 3 06:34:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajat Jain X-Patchwork-Id: 9494463 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F335F606B4 for ; Tue, 3 Jan 2017 06:36:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E7339266F3 for ; Tue, 3 Jan 2017 06:36:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DC018269DA; Tue, 3 Jan 2017 06:36:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 71BB426861 for ; Tue, 3 Jan 2017 06:36:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932970AbdACGgR (ORCPT ); Tue, 3 Jan 2017 01:36:17 -0500 Received: from mail-pg0-f50.google.com ([74.125.83.50]:36660 "EHLO mail-pg0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934524AbdACGeg (ORCPT ); Tue, 3 Jan 2017 01:34:36 -0500 Received: by mail-pg0-f50.google.com with SMTP id f188so211333091pgc.3 for ; Mon, 02 Jan 2017 22:34:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=O/n5VOmX8DObvUv1NSFDzMMuIEw7PI5AyaQDHHeS3ho=; b=WSKTROilw/zKaOcGf3ZJXP5gtbvlKtVKUpzcbuBPztlwI7DMIzimshrepasof93+SL KLMI6Uax/JOckyHKX9q2ui6tDBqQmJTndCbvJBgey88wb5jkrLcro58nY3xHW7Lpd63p XUBL/vbg5hIlBkOL8KpXep7bWNBD7XwuEuo5x2EmZtaPtiYWUCB3BJZBjoUCHEjVqBTo 47ngP1SwT/TTETfKYi31N/pEGlpUpvNGlINPSAvpqPKjcJmLKCvbdk3BlIkjWHYZMrNk M7wd/ybJmRIurns3An3ubrUIE2WZ4VHUVR8xolpGe+lO9NksiHXxcOL6kmfZh176v2RL mIzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=O/n5VOmX8DObvUv1NSFDzMMuIEw7PI5AyaQDHHeS3ho=; b=uaBTMqnAB6w6r3XBG9Odcct4OuxzFfyI5q5pImJ3EQDvzgF98ihNr+z+xPaaFwYonK jfKw3DCaw5WXS475EFP/PrecsMUp5nTxBPIT6SrY5ZAvGnTwlZVRyjkNfdHLd/bzYgS1 fRJLsmxS9eGDtduXcCK8mjJsQyawMDBChYPGG3r9jesawxX+CqNnrPwOIQLMJHCdMDg0 Dl0fXZ16XNIoly5zL7URD3GWWuKwWiOa3kO3qp3twJ5QM/SwJrbYBuwQpwcaBScnsH7h jZNfRPpwKD5NLlYbatTLYauvxfLJRe8sPlXpiPZTJnfG5H8xXno3zkxg6V1Uxyon6Iyc AgvA== X-Gm-Message-State: AIkVDXIRmEpVh3/NF+86HMVU5adG9bUiZiwmFQzIdbkToSH2lOkCAkWIIUbKAfyOO3a4x69C X-Received: by 10.84.192.1 with SMTP id b1mr132379122pld.113.1483425275207; Mon, 02 Jan 2017 22:34:35 -0800 (PST) Received: from rajat.mtv.corp.google.com ([172.22.64.13]) by smtp.gmail.com with ESMTPSA id g28sm72936251pgn.13.2017.01.02.22.34.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 02 Jan 2017 22:34:34 -0800 (PST) From: Rajat Jain To: Bjorn Helgaas , Keith Busch , Andreas Ziegler , Jonathan Yong , Shawn Lin , David Daney , Julia Lawall , Ram Amrani , Doug Ledford , Wang Sheng-Hui , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Rajat Jain , Rajat Jain , Brian Norris Subject: [PATCH 3/6] PCI/ASPM: Read and setup L1 substate capabilities Date: Mon, 2 Jan 2017 22:34:12 -0800 Message-Id: <1483425255-101923-4-git-send-email-rajatja@google.com> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 In-Reply-To: <1483425255-101923-1-git-send-email-rajatja@google.com> References: <1483425255-101923-1-git-send-email-rajatja@google.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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, ®16); 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;