drivers/pci/controller/pci-loongson.c | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
From: Ziyao Li <liziyao@uniontech.com>
Older steppings of the Loongson 3C6000 series incorrectly report the
supported link speeds on their PCIe bridges (device IDs 3c19, 3c29) as
only 2.5 GT/s, despite the upstream bus supporting speeds from 2.5 GT/s
up to 16 GT/s.
As a result, since commit 774c71c52aa4 ("PCI/bwctrl: Enable only if more
than one speed is supported"), bwctrl will be disabled if there's only
one 2.5 GT/s value in vector `supported_speeds`.
Also, amdgpu reads the value by pcie_get_speed_cap() in amdgpu_device_
partner_bandwidth(), for its dynamic adjustment of PCIe clocks and
lanes in power management. We hope this can prevent similar problems
in future driver changes (similar checks may be implemented in other
GPU, storage controller, NIC, etc. drivers).
Manually override the `supported_speeds` field for affected PCIe bridges
with those found on the upstream bus to correctly reflect the supported
link speeds.
This patch was originally found from AOSC OS[1].
Link: https://github.com/AOSC-Tracking/linux/pull/2 #1
Tested-by: Lain Fearyncess Yang <fsf@live.com>
Tested-by: Ayden Meng <aydenmeng@yeah.net>
Signed-off-by: Ayden Meng <aydenmeng@yeah.net>
Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
[Xi Ruoyao: Fix falling through logic and add kernel log output.]
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Link: https://github.com/AOSC-Tracking/linux/commit/4392f441363abdf6fa0a0433d73175a17f493454
[Ziyao Li: move from drivers/pci/quirks.c to drivers/pci/controller/pci-loongson.c]
Signed-off-by: Ziyao Li <liziyao@uniontech.com>
Tested-by: Mingcong Bai <jeffbai@aosc.io>
---
Changes in v3:
- Adjust commit message
- Make the program flow more intuitive
- Link to v2: https://lore.kernel.org/r/20260104-loongson-pci1-v2-1-d151e57b6ef8@uniontech.com
Changes in v2:
- Link to v1: https://lore.kernel.org/r/20250822-loongson-pci1-v1-1-39aabbd11fbd@uniontech.com
- Move from arch/loongarch/pci/pci.c to drivers/pci/controller/pci-loongson.c
- Fix falling through logic and add kernel log output by Xi Ruoyao
---
drivers/pci/controller/pci-loongson.c | 38 +++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/drivers/pci/controller/pci-loongson.c b/drivers/pci/controller/pci-loongson.c
index bc630ab8a283..67a6d99b9e82 100644
--- a/drivers/pci/controller/pci-loongson.c
+++ b/drivers/pci/controller/pci-loongson.c
@@ -176,6 +176,44 @@ static void loongson_pci_msi_quirk(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_PCIE_PORT5, loongson_pci_msi_quirk);
+/*
+ * Older steppings of the Loongson 3C6000 series incorrectly report the
+ * supported link speeds on their PCIe bridges (device IDs 3c19, 3c29) as
+ * only 2.5 GT/s, despite the upstream bus supporting speeds from 2.5 GT/s
+ * up to 16 GT/s.
+ */
+static void loongson_pci_bridge_speed_quirk(struct pci_dev *pdev)
+{
+ u8 old_supported_speeds = pdev->supported_speeds;
+
+ switch (pdev->bus->max_bus_speed) {
+ case PCIE_SPEED_16_0GT:
+ pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_16_0GB;
+ fallthrough;
+ case PCIE_SPEED_8_0GT:
+ pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_8_0GB;
+ fallthrough;
+ case PCIE_SPEED_5_0GT:
+ pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_5_0GB;
+ fallthrough;
+ case PCIE_SPEED_2_5GT:
+ pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_2_5GB;
+ break;
+ default:
+ pci_warn(pdev, "unexpected max bus speed");
+
+ return;
+ }
+
+ if (pdev->supported_speeds != old_supported_speeds)
+ pci_info(pdev, "fixing up supported link speeds: 0x%x => 0x%x",
+ old_supported_speeds, pdev->supported_speeds);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_LOONGSON, 0x3c19,
+ loongson_pci_bridge_speed_quirk);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_LOONGSON, 0x3c29,
+ loongson_pci_bridge_speed_quirk);
+
static struct loongson_pci *pci_bus_to_loongson_pci(struct pci_bus *bus)
{
struct pci_config_window *cfg;
---
base-commit: ea1013c1539270e372fc99854bc6e4d94eaeff66
change-id: 20250822-loongson-pci1-4ded0d78f1bb
Best regards,
--
Ziyao Li <liziyao@uniontech.com>
Hi, Ziyao,
As far as I know, new chips may still use the same PCI ID, and even if
new chips fix this problem in hardware, this patch seems harmless. So
I suggest the subject to be:
PCI: loongson: Override PCIe bridge supported speeds for Loongson-3C6000 series.
On Fri, Jan 9, 2026 at 11:37 AM Ziyao Li via B4 Relay
<devnull+liziyao.uniontech.com@kernel.org> wrote:
>
> From: Ziyao Li <liziyao@uniontech.com>
>
> Older steppings of the Loongson 3C6000 series incorrectly report the
> supported link speeds on their PCIe bridges (device IDs 3c19, 3c29) as
> only 2.5 GT/s, despite the upstream bus supporting speeds from 2.5 GT/s
> up to 16 GT/s.
Please use Loongson-3C6000 instead of Loongson 3C6000, and use
0x3c19/0x3c29 instead of 3c19/3c29, thanks.
Huacai
>
> As a result, since commit 774c71c52aa4 ("PCI/bwctrl: Enable only if more
> than one speed is supported"), bwctrl will be disabled if there's only
> one 2.5 GT/s value in vector `supported_speeds`.
>
> Also, amdgpu reads the value by pcie_get_speed_cap() in amdgpu_device_
> partner_bandwidth(), for its dynamic adjustment of PCIe clocks and
> lanes in power management. We hope this can prevent similar problems
> in future driver changes (similar checks may be implemented in other
> GPU, storage controller, NIC, etc. drivers).
>
> Manually override the `supported_speeds` field for affected PCIe bridges
> with those found on the upstream bus to correctly reflect the supported
> link speeds.
>
> This patch was originally found from AOSC OS[1].
>
> Link: https://github.com/AOSC-Tracking/linux/pull/2 #1
> Tested-by: Lain Fearyncess Yang <fsf@live.com>
> Tested-by: Ayden Meng <aydenmeng@yeah.net>
> Signed-off-by: Ayden Meng <aydenmeng@yeah.net>
> Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
> [Xi Ruoyao: Fix falling through logic and add kernel log output.]
> Signed-off-by: Xi Ruoyao <xry111@xry111.site>
> Link: https://github.com/AOSC-Tracking/linux/commit/4392f441363abdf6fa0a0433d73175a17f493454
> [Ziyao Li: move from drivers/pci/quirks.c to drivers/pci/controller/pci-loongson.c]
> Signed-off-by: Ziyao Li <liziyao@uniontech.com>
> Tested-by: Mingcong Bai <jeffbai@aosc.io>
> ---
> Changes in v3:
> - Adjust commit message
> - Make the program flow more intuitive
> - Link to v2: https://lore.kernel.org/r/20260104-loongson-pci1-v2-1-d151e57b6ef8@uniontech.com
>
> Changes in v2:
> - Link to v1: https://lore.kernel.org/r/20250822-loongson-pci1-v1-1-39aabbd11fbd@uniontech.com
> - Move from arch/loongarch/pci/pci.c to drivers/pci/controller/pci-loongson.c
> - Fix falling through logic and add kernel log output by Xi Ruoyao
> ---
> drivers/pci/controller/pci-loongson.c | 38 +++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/drivers/pci/controller/pci-loongson.c b/drivers/pci/controller/pci-loongson.c
> index bc630ab8a283..67a6d99b9e82 100644
> --- a/drivers/pci/controller/pci-loongson.c
> +++ b/drivers/pci/controller/pci-loongson.c
> @@ -176,6 +176,44 @@ static void loongson_pci_msi_quirk(struct pci_dev *dev)
> }
> DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, DEV_LS7A_PCIE_PORT5, loongson_pci_msi_quirk);
>
> +/*
> + * Older steppings of the Loongson 3C6000 series incorrectly report the
> + * supported link speeds on their PCIe bridges (device IDs 3c19, 3c29) as
> + * only 2.5 GT/s, despite the upstream bus supporting speeds from 2.5 GT/s
> + * up to 16 GT/s.
> + */
> +static void loongson_pci_bridge_speed_quirk(struct pci_dev *pdev)
> +{
> + u8 old_supported_speeds = pdev->supported_speeds;
> +
> + switch (pdev->bus->max_bus_speed) {
> + case PCIE_SPEED_16_0GT:
> + pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_16_0GB;
> + fallthrough;
> + case PCIE_SPEED_8_0GT:
> + pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_8_0GB;
> + fallthrough;
> + case PCIE_SPEED_5_0GT:
> + pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_5_0GB;
> + fallthrough;
> + case PCIE_SPEED_2_5GT:
> + pdev->supported_speeds |= PCI_EXP_LNKCAP2_SLS_2_5GB;
> + break;
> + default:
> + pci_warn(pdev, "unexpected max bus speed");
> +
> + return;
> + }
> +
> + if (pdev->supported_speeds != old_supported_speeds)
> + pci_info(pdev, "fixing up supported link speeds: 0x%x => 0x%x",
> + old_supported_speeds, pdev->supported_speeds);
> +}
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_LOONGSON, 0x3c19,
> + loongson_pci_bridge_speed_quirk);
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_LOONGSON, 0x3c29,
> + loongson_pci_bridge_speed_quirk);
> +
> static struct loongson_pci *pci_bus_to_loongson_pci(struct pci_bus *bus)
> {
> struct pci_config_window *cfg;
>
> ---
> base-commit: ea1013c1539270e372fc99854bc6e4d94eaeff66
> change-id: 20250822-loongson-pci1-4ded0d78f1bb
>
> Best regards,
> --
> Ziyao Li <liziyao@uniontech.com>
>
>
>
© 2016 - 2026 Red Hat, Inc.