From nobody Mon Dec 1 22:07:40 2025 Received: from angie.orcam.me.uk (angie.orcam.me.uk [78.133.224.34]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 70D3378F5D; Mon, 1 Dec 2025 03:52:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=78.133.224.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764561151; cv=none; b=i/LIundDPnhTZaCTYpW9rFYkkWiwUTeC2mXT0PAcPeX+X8Yx2QSO9x0G7cB0coSlnJLq6FfiY8nJEqNL9ipJZStoPLrymQMJ/NqyQScph9u7qdA9q4xjNPSDXr8ZGHcbMTCMey3rIr8nYQHSHgqKouIs14CXfwCbFnn8Be/DCmg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764561151; c=relaxed/simple; bh=gG6BIB4kxG2KD7FoboQCbZfhC1hmKdFO2n/DpiqXCz4=; h=Date:From:To:cc:Subject:Message-ID:MIME-Version:Content-Type; b=mS0Y2pCa6LFgIFbNYlAHm+9SvDpUi70r3OXdRLFsIXJ365fppNWtHTv2oVdITuuWzsVQiUlS0w4ggbZggrwthUoehu6OAL75RBsLznkCPCkUgzk22vZBHArxXhxlqDKqfAERZBXpxeHonfJIk92klmXSgNcsrLxhPUEoYkF65M8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=orcam.me.uk; spf=none smtp.mailfrom=orcam.me.uk; arc=none smtp.client-ip=78.133.224.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=orcam.me.uk Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=orcam.me.uk Received: by angie.orcam.me.uk (Postfix, from userid 500) id DE36D92009C; Mon, 1 Dec 2025 04:52:26 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by angie.orcam.me.uk (Postfix) with ESMTP id D092792009B; Mon, 1 Dec 2025 03:52:26 +0000 (GMT) Date: Mon, 1 Dec 2025 03:52:26 +0000 (GMT) From: "Maciej W. Rozycki" To: Bjorn Helgaas , Matthew W Carlis , ALOK TIWARI cc: ashishk@purestorage.com, bamstadt@purestorage.com, msaggi@purestorage.com, sconnor@purestorage.com, Lukas Wunner , =?UTF-8?Q?Ilpo_J=C3=A4rvinen?= , Jiwei , guojinhui.liam@bytedance.com, ahuang12@lenovo.com, sunjw10@lenovo.com, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] PCI: Always lift 2.5GT/s restriction in PCIe failed link retraining Message-ID: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Discard Vendor:Device ID matching in the PCIe failed link retraining=20 quirk and ignore the link status for the removal of the 2.5GT/s speed=20 clamp, whether applied by the quirk itself or the firmware earlier on. =20 Revert to the original target link speed if this final link retraining=20 has failed. This is so that link training noise in hot-plug scenarios does not make=20 a link remain clamped to the 2.5GT/s speed where an event race has led=20 the quirk to apply the speed clamp for one device, only to leave it in=20 place for a subsequent device to be plugged in. Fixes: a89c82249c37 ("PCI: Work around PCIe link training failures") Signed-off-by: Maciej W. Rozycki Cc: # v6.5+ --- drivers/pci/quirks.c | 50 ++++++++++++++++++----------------------------= ---- 1 file changed, 18 insertions(+), 32 deletions(-) linux-pcie-failed-link-retrain-unclamp-always.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 @@ -79,11 +79,10 @@ static bool pcie_lbms_seen(struct pci_de * Restrict the speed to 2.5GT/s then with the Target Link Speed field, * request a retrain and check the result. * - * 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. + * If this turns out successful, or where a 2.5GT/s speed restriction has + * been previously arranged by the firmware and the port reports its link + * already being up, lift the restriction, in a hope it is safe to do so, + * letting the devices negotiate a higher speed. * * Otherwise revert the speed to the original setting and request a retrain * again to remove any residual state, ignoring the result as it's supposed @@ -94,52 +93,39 @@ static bool pcie_lbms_seen(struct pci_de */ int pcie_failed_link_retrain(struct pci_dev *dev) { - static const struct pci_device_id ids[] =3D { - { PCI_VDEVICE(ASMEDIA, 0x2824) }, /* ASMedia ASM2824 */ - {} - }; - u16 lnksta, lnkctl2; + u16 lnksta, lnkctl2, oldlnkctl2; int ret =3D -ENOTTY; + u32 lnkcap; =20 if (!pci_is_pcie(dev) || !pcie_downstream_port(dev) || !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting) return ret; =20 pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &oldlnkctl2); if (!(lnksta & PCI_EXP_LNKSTA_DLLLA) && pcie_lbms_seen(dev, lnksta)) { - u16 oldlnkctl2; - pci_info(dev, "broken device, retraining non-functional downstream link = at 2.5GT/s\n"); =20 - pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &oldlnkctl2); ret =3D pcie_set_target_speed(dev, PCIE_SPEED_2_5GT, false); - if (ret) { - pci_info(dev, "retraining failed\n"); - pcie_set_target_speed(dev, PCIE_LNKCTL2_TLS2SPEED(oldlnkctl2), - true); - return ret; - } - - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); + if (ret) + goto err; } =20 pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); - - if ((lnksta & PCI_EXP_LNKSTA_DLLLA) && - (lnkctl2 & PCI_EXP_LNKCTL2_TLS) =3D=3D PCI_EXP_LNKCTL2_TLS_2_5GT && - pci_match_id(ids, dev)) { - u32 lnkcap; - + pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); + if ((lnkctl2 & PCI_EXP_LNKCTL2_TLS) =3D=3D PCI_EXP_LNKCTL2_TLS_2_5GT && + (lnkcap & PCI_EXP_LNKCAP_SLS) !=3D PCI_EXP_LNKCAP_SLS_2_5GB) { pci_info(dev, "removing 2.5GT/s downstream link speed restriction\n"); - pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); ret =3D pcie_set_target_speed(dev, PCIE_LNKCAP_SLS2SPEED(lnkcap), false); - if (ret) { - pci_info(dev, "retraining failed\n"); - return ret; - } + if (ret) + goto err; } =20 return ret; +err: + pci_info(dev, "retraining failed\n"); + pcie_set_target_speed(dev, PCIE_LNKCTL2_TLS2SPEED(oldlnkctl2), true); + return ret; } =20 static ktime_t fixup_debug_start(struct pci_dev *dev,