From nobody Fri Apr 3 03:53:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EEAAAC54EE9 for ; Sat, 17 Sep 2022 12:03:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229612AbiIQMDR (ORCPT ); Sat, 17 Sep 2022 08:03:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229568AbiIQMDM (ORCPT ); Sat, 17 Sep 2022 08:03:12 -0400 X-Greylist: delayed 6951 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Sat, 17 Sep 2022 05:03:10 PDT Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E12AA3054F for ; Sat, 17 Sep 2022 05:03:10 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id 13F2192009C; Sat, 17 Sep 2022 14:03:10 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 0E49D92009B; Sat, 17 Sep 2022 13:03:10 +0100 (BST) Date: Sat, 17 Sep 2022 13:03:09 +0100 (BST) From: "Maciej W. Rozycki" To: Bjorn Helgaas cc: Stefan Roese , Jim Wilson , David Abdurachmanov , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 1/5] PCI: Consistently report presence of PCIe link registers In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Consistently with commit c8b303d0206b ("PCI: Remove PCIe Capability=20 version checks") only consider the PCI Express capability's Link Control=20 2, etc. registers present if the Link Control register is. Before said commit with PCI Express capability versions higher than one=20 all link registers used to be considered present, however starting from=20 said commit Link Control, etc. original registers are only considered=20 present in devices with links, but Link Control 2, etc. registers=20 continue being considered always present even though likewise they are=20 only present in devices with links. Fix the inconsistency then. Signed-off-by: Maciej W. Rozycki --- New change in v5. --- drivers/pci/access.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) linux-pcie-cap-has-lnkctl2.diff Index: linux-macro/drivers/pci/access.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/access.c +++ linux-macro/drivers/pci/access.c @@ -350,6 +350,11 @@ bool pcie_cap_has_lnkctl(const struct pc type =3D=3D PCI_EXP_TYPE_PCIE_BRIDGE; } =20 +static inline bool pcie_cap_has_lnkctl2(const struct pci_dev *dev) +{ + return pcie_cap_has_lnkctl(dev) && pcie_cap_version(dev) > 1; +} + static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev) { return pcie_downstream_port(dev) && @@ -390,10 +395,11 @@ static bool pcie_capability_reg_implemen return pcie_cap_has_rtctl(dev); case PCI_EXP_DEVCAP2: case PCI_EXP_DEVCTL2: + return pcie_cap_version(dev) > 1; case PCI_EXP_LNKCAP2: case PCI_EXP_LNKCTL2: case PCI_EXP_LNKSTA2: - return pcie_cap_version(dev) > 1; + return pcie_cap_has_lnkctl2(dev); default: return false; } From nobody Fri Apr 3 03:53:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78595ECAAD3 for ; Sat, 17 Sep 2022 12:03:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229623AbiIQMDW (ORCPT ); Sat, 17 Sep 2022 08:03:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56970 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229613AbiIQMDS (ORCPT ); Sat, 17 Sep 2022 08:03:18 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id A62563204E for ; Sat, 17 Sep 2022 05:03:15 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id EE15F92009C; Sat, 17 Sep 2022 14:03:14 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id E70C492009B; Sat, 17 Sep 2022 13:03:14 +0100 (BST) Date: Sat, 17 Sep 2022 13:03:14 +0100 (BST) From: "Maciej W. Rozycki" To: Bjorn Helgaas cc: Stefan Roese , Jim Wilson , David Abdurachmanov , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 2/5] PCI: Export `pcie_cap_has_lnkctl2' In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Export `pcie_cap_has_lnkctl2' for external use. Signed-off-by: Maciej W. Rozycki --- New change in v5. --- drivers/pci/access.c | 2 +- drivers/pci/pci.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) linux-pcie-cap-has-lnkctl2-export.diff Index: linux-macro/drivers/pci/access.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/access.c +++ linux-macro/drivers/pci/access.c @@ -350,7 +350,7 @@ bool pcie_cap_has_lnkctl(const struct pc type =3D=3D PCI_EXP_TYPE_PCIE_BRIDGE; } =20 -static inline bool pcie_cap_has_lnkctl2(const struct pci_dev *dev) +bool pcie_cap_has_lnkctl2(const struct pci_dev *dev) { return pcie_cap_has_lnkctl(dev) && pcie_cap_version(dev) > 1; } Index: linux-macro/drivers/pci/pci.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/pci.h +++ linux-macro/drivers/pci/pci.h @@ -15,6 +15,7 @@ extern const unsigned char pcie_link_spe extern bool pci_early_dump; =20 bool pcie_cap_has_lnkctl(const struct pci_dev *dev); +bool pcie_cap_has_lnkctl2(const struct pci_dev *dev); bool pcie_cap_has_rtctl(const struct pci_dev *dev); =20 /* Functions internal to the PCI core code */ From nobody Fri Apr 3 03:53:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE573C54EE9 for ; Sat, 17 Sep 2022 12:03:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229728AbiIQMDf (ORCPT ); Sat, 17 Sep 2022 08:03:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56994 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229658AbiIQMDV (ORCPT ); Sat, 17 Sep 2022 08:03:21 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id BAE0C39B93 for ; Sat, 17 Sep 2022 05:03:20 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id E39DC92009C; Sat, 17 Sep 2022 14:03:19 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id DCEA292009B; Sat, 17 Sep 2022 13:03:19 +0100 (BST) Date: Sat, 17 Sep 2022 13:03:19 +0100 (BST) From: "Maciej W. Rozycki" To: Bjorn Helgaas cc: Stefan Roese , Jim Wilson , David Abdurachmanov , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 3/5] PCI: Export PCI link retrain timeout In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rename LINK_RETRAIN_TIMEOUT to PCIE_LINK_RETRAIN_TIMEOUT and make it available via "pci.h" for PCI drivers to use. Signed-off-by: Maciej W. Rozycki --- New change in v5. --- drivers/pci/pci.h | 2 ++ drivers/pci/pcie/aspm.c | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) linux-pcie-link-retrain-timeout.diff Index: linux-macro/drivers/pci/pci.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/pci.h +++ linux-macro/drivers/pci/pci.h @@ -11,6 +11,8 @@ =20 #define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */ =20 +#define PCIE_LINK_RETRAIN_TIMEOUT HZ + extern const unsigned char pcie_link_speed[]; extern bool pci_early_dump; =20 Index: linux-macro/drivers/pci/pcie/aspm.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/pcie/aspm.c +++ linux-macro/drivers/pci/pcie/aspm.c @@ -89,8 +89,6 @@ static const char *policy_str[] =3D { [POLICY_POWER_SUPERSAVE] =3D "powersupersave" }; =20 -#define LINK_RETRAIN_TIMEOUT HZ - /* * The L1 PM substate capability is only implemented in function 0 in a * multi function device. @@ -212,7 +210,7 @@ static bool pcie_retrain_link(struct pci } =20 /* Wait for link training end. Break out after waiting for timeout */ - end_jiffies =3D jiffies + LINK_RETRAIN_TIMEOUT; + end_jiffies =3D jiffies + PCIE_LINK_RETRAIN_TIMEOUT; do { pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_LT)) From nobody Fri Apr 3 03:53:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8AAC0C54EE9 for ; Sat, 17 Sep 2022 12:03:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229774AbiIQMDn (ORCPT ); Sat, 17 Sep 2022 08:03:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57452 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229681AbiIQMDb (ORCPT ); Sat, 17 Sep 2022 08:03:31 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 522AA31EE8 for ; Sat, 17 Sep 2022 05:03:24 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id D92579200B3; Sat, 17 Sep 2022 14:03:23 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id D600692009E; Sat, 17 Sep 2022 13:03:23 +0100 (BST) Date: Sat, 17 Sep 2022 13:03:23 +0100 (BST) From: "Maciej W. Rozycki" To: Bjorn Helgaas cc: Stefan Roese , Jim Wilson , David Abdurachmanov , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 4/5] PCI: Execute `quirk_enable_clear_retrain_link' earlier In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Make `quirk_enable_clear_retrain_link' `pci_fixup_early' so that any later=20 fixups can rely on `clear_retrain_link' to have been already initialised. Signed-off-by: Maciej W. Rozycki --- New change in v5. --- drivers/pci/quirks.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) linux-pcie-clear-retrain-link-early.diff Index: linux-macro/drivers/pci/quirks.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/quirks.c +++ linux-macro/drivers/pci/quirks.c @@ -2407,9 +2407,9 @@ static void quirk_enable_clear_retrain_l dev->clear_retrain_link =3D 1; pci_info(dev, "Enable PCIe Retrain Link quirk\n"); } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear= _retrain_link); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear= _retrain_link); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear= _retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe110, quirk_enable_clear_= retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe111, quirk_enable_clear_= retrain_link); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PERICOM, 0xe130, quirk_enable_clear_= retrain_link); =20 static void fixup_rev1_53c810(struct pci_dev *dev) { From nobody Fri Apr 3 03:53:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D903FECAAD3 for ; Sat, 17 Sep 2022 12:04:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229528AbiIQMED (ORCPT ); Sat, 17 Sep 2022 08:04:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229685AbiIQMDm (ORCPT ); Sat, 17 Sep 2022 08:03:42 -0400 Received: from angie.orcam.me.uk (angie.orcam.me.uk [IPv6:2001:4190:8020::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 342833AB26; Sat, 17 Sep 2022 05:03:39 -0700 (PDT) Received: by angie.orcam.me.uk (Postfix, from userid 500) id 6F3F692009C; Sat, 17 Sep 2022 14:03:38 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id 6858C92009B; Sat, 17 Sep 2022 13:03:38 +0100 (BST) Date: Sat, 17 Sep 2022 13:03:38 +0100 (BST) From: "Maciej W. Rozycki" To: Bjorn Helgaas cc: Stefan Roese , Jim Wilson , David Abdurachmanov , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 5/5] PCI: Work around PCIe link training failures In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Attempt to handle cases such as with a downstream port of the ASMedia=20 ASM2824 PCIe switch where link training never completes and the link=20 continues switching between speeds indefinitely with the data link layer=20 never reaching the active state. It has been observed with a downstream port of the ASMedia ASM2824 Gen 3=20 switch wired to the upstream port of the Pericom PI7C9X2G304 Gen 2=20 switch, using a Delock Riser Card PCI Express x1 > 2 x PCIe x1 device,=20 P/N 41433, wired to a SiFive HiFive Unmatched board. In this setup the=20 switches are supposed to negotiate the link speed of preferably 5.0GT/s,=20 falling back to 2.5GT/s. Instead the link continues oscillating between the two speeds, at the=20 rate of 34-35 times per second, with link training reported repeatedly=20 active ~84% of the time. Forcibly limiting the target link speed to=20 2.5GT/s with the upstream ASM2824 device however makes the two switches=20 communicate correctly. Removing the speed restriction afterwards makes=20 the two devices switch to 5.0GT/s then. Make use of these observations then and detect the inability to train=20 the link, by checking for the Data Link Layer Link Active status bit=20 being off while the Link Bandwidth Management Status indicating that=20 hardware has changed the link speed or width in an attempt to correct=20 unreliable link operation. Restrict the speed to 2.5GT/s then with the Target Link Speed field,=20 request a retrain and wait 200ms for the data link to go up. If this=20 turns out successful, then lift the restriction, letting the devices=20 negotiate a higher speed. Also check for a 2.5GT/s speed restriction the firmware may have already=20 arranged and lift it too with ports of devices known to continue working=20 afterwards, currently the ASM2824 only, that already report their data=20 link being up. Signed-off-by: Maciej W. Rozycki Link: https://lore.kernel.org/lkml/alpine.DEB.2.21.2203022037020.56670@angi= e.orcam.me.uk/ Link: https://source.denx.de/u-boot/u-boot/-/commit/a398a51ccc68 --- Changes from v4: - Remove inclusion no longer needed. - Make the quirk generic based on probing device features rather than=20 specific to the ASM2824 part only; take the Retrain Link bit erratum=20 into account. - Still lift the 2.5GT/s speed restriction with the ASM2824 only. - Increase retrain timeout from 200ms to 1s (PCIE_LINK_RETRAIN_TIMEOUT). - Remove retrain success notification. - Use PCIe helpers rather than generic PCI functions throughout. - Trim down and update the wording of the change description for the=20 switch from an ASM2824-specific to a generic fixup. Changes from v3: - Remove the entry for the ASM2824. Changes from v2: - Regenerate for 5.17-rc2 for a merge conflict. - Replace BUG_ON for a missing PCI Express capability with WARN_ON and an early return. Changes from v1: - Regenerate for a merge conflict. --- drivers/pci/quirks.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++= +++++ 1 file changed, 118 insertions(+) linux-pcie-asm2824-manual-retrain.diff Index: linux-macro/drivers/pci/quirks.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-macro.orig/drivers/pci/quirks.c +++ linux-macro/drivers/pci/quirks.c @@ -5956,3 +5956,121 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56c0, aspm_l1_acceptable_l= atency); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56c1, aspm_l1_acceptable_l= atency); #endif + +/* + * Retrain the link of a downstream PCIe port by hand if necessary. + * + * This is needed at least where a downstream port of the ASMedia ASM2824 + * Gen 3 switch is wired to the upstream port of the Pericom PI7C9X2G304 + * Gen 2 switch, and observed with the Delock Riser Card PCI Express x1 > + * 2 x PCIe x1 device, P/N 41433, plugged into the SiFive HiFive Unmatched + * board. + * + * In such a configuration the switches are supposed to negotiate the link + * speed of preferably 5.0GT/s, falling back to 2.5GT/s. However the link + * continues switching between the two speeds indefinitely and the data + * link layer never reaches the active state, with link training reported + * repeatedly active ~84% of the time. Forcing the target link speed to + * 2.5GT/s with the upstream ASM2824 device makes the two switches talk to + * each other correctly however. And more interestingly retraining with a + * higher target link speed afterwards lets the two successfully negotiate + * 5.0GT/s. + * + * With the ASM2824 we can rely on the otherwise optional Data Link Layer + * Link Active status bit and in the failed link training scenario it will + * be off along with the Link Bandwidth Management Status indicating that + * hardware has changed the link speed or width in an attempt to correct + * unreliable link operation. For a port that has been left unconnected + * both bits will be clear. So use this information to detect the problem + * rather than polling the Link Training bit and watching out for flips or + * at least the active status. + * + * Since the exact nature of the problem isn't known and in principle this + * could trigger where an ASM2824 device is downstream rather upstream, + * apply this erratum workaround to any downstream ports as long as they + * support Link Active reporting and have the Link Control 2 register. + * Restrict the speed to 2.5GT/s then with the Target Link Speed field, + * request a retrain and wait 200ms for the data link to go up. + * + * If this turns out successful and we know by the Vendor:Device ID it is + * safe to do so, then lift the restriction, letting the devices negotiate + * a higher speed. Also check for a similar 2.5GT/s speed restriction the + * firmware may have already arranged and lift it with ports that already + * report their data link being up. + */ +static void pcie_downstream_link_retrain(struct pci_dev *dev) +{ + static const struct pci_device_id ids[] =3D { + { PCI_VDEVICE(ASMEDIA, 0x2824) }, /* ASMedia ASM2824 */ + {} + }; + u16 lnksta, lnkctl2; + u32 lnkcap; + + if (!pci_is_pcie(dev) || !pcie_downstream_port(dev) + || !pcie_cap_has_lnkctl2(dev)) + return; + + /* It's too early yet to use `dev->link_active_reporting'. */ + pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); + if (!(lnkcap & PCI_EXP_LNKCAP_DLLLARC)) + return; + + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + if ((lnksta & (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_DLLLA)) =3D=3D + PCI_EXP_LNKSTA_LBMS) { + unsigned long timeout; + u16 lnkctl; + + pci_info(dev, "broken device, retraining non-functional downstream link = at 2.5GT/s\n"); + + pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &lnkctl); + lnkctl |=3D PCI_EXP_LNKCTL_RL; + lnkctl2 &=3D ~PCI_EXP_LNKCTL2_TLS; + lnkctl2 |=3D PCI_EXP_LNKCTL2_TLS_2_5GT; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnkctl); + /* + * Due to an erratum in some devices the Retrain Link bit + * needs to be cleared again manually to allow the link + * training to succeed. + */ + lnkctl &=3D ~PCI_EXP_LNKCTL_RL; + if (dev->clear_retrain_link) + pcie_capability_write_word(dev, PCI_EXP_LNKCTL, + lnkctl); + + timeout =3D jiffies + PCIE_LINK_RETRAIN_TIMEOUT; + do { + pcie_capability_read_word(dev, PCI_EXP_LNKSTA, + &lnksta); + if (lnksta & PCI_EXP_LNKSTA_DLLLA) + break; + usleep_range(10000, 20000); + } while (time_before(jiffies, timeout)); + + if (!(lnksta & PCI_EXP_LNKSTA_DLLLA)) { + pci_info(dev, "retraining failed\n"); + return; + } + } + + if ((lnksta & PCI_EXP_LNKSTA_DLLLA) && + (lnkctl2 & PCI_EXP_LNKCTL2_TLS) =3D=3D PCI_EXP_LNKCTL2_TLS_2_5GT && + pci_match_id(ids, dev)) { + u16 lnkctl; + + pci_info(dev, "removing 2.5GT/s downstream link speed restriction\n"); + pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &lnkctl); + lnkctl |=3D PCI_EXP_LNKCTL_RL; + lnkctl2 &=3D ~PCI_EXP_LNKCTL2_TLS; + lnkctl2 |=3D lnkcap & PCI_EXP_LNKCAP_SLS; + pcie_capability_write_word(dev, PCI_EXP_LNKCTL2, lnkctl2); + pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnkctl); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, + pcie_downstream_link_retrain); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_ANY_ID, PCI_ANY_ID, + pcie_downstream_link_retrain);