PCI: loongson: Do not ignore downstream devices on external bridges

Loongson PCI host controllers have a hardware quirk that requires
software to ignore downstream devices with device number > 0 on the
internal bridges. The current implementation applies the workaround to
all non-root buses, which breaks external bridges (e.g., PCIe switches)
with multiple downstream devices.

Fix it by only applying the workaround to internal bridges.

Tested on Loongson-LS3A4000-7A1000-NUC-SE, using AMD Promontory 21
chipset add-in card [1].

  $ lspci -tnnnvvv
  -[0000:00]-+-00.0  Loongson Technology LLC 7A1000 Chipset Hyper Transport Bridge Controller [0014:7a00]
             +-00.1  Loongson Technology LLC 7A2000 Chipset Hyper Transport Bridge Controller [0014:7a10]
             +-03.0  Loongson Technology LLC 2K1000/2000 / 7A1000 Chipset Gigabit Ethernet Controller [0014:7a03]
             +-04.0  Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB OHCI Controller [0014:7a24]
             +-04.1  Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB EHCI Controller [0014:7a14]
             +-05.0  Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB OHCI Controller [0014:7a24]
             +-05.1  Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB EHCI Controller [0014:7a14]
             +-06.0  Loongson Technology LLC 7A1000 Chipset Vivante GC1000 GPU [0014:7a15]
             +-06.1  Loongson Technology LLC 2K1000 / 7A1000 Chipset Display Controller [0014:7a06]
             +-07.0  Loongson Technology LLC 2K1000/2000/3000 / 3B6000M / 7A1000/2000 Chipset HD Audio Controller [0014:7a07]
             +-08.0  Loongson Technology LLC 2K1000 / 7A1000 Chipset 3Gb/s SATA AHCI Controller [0014:7a08]
             +-08.1  Loongson Technology LLC 2K1000 / 7A1000 Chipset 3Gb/s SATA AHCI Controller [0014:7a08]
             +-08.2  Loongson Technology LLC 2K1000 / 7A1000 Chipset 3Gb/s SATA AHCI Controller [0014:7a08]
             +-09.0-[01]----00.0  Qualcomm Technologies, Inc QCNFA765 Wireless Network Adapter [17cb:1103]
             +-0a.0-[02]----00.0  Etron Technology, Inc. EJ188/EJ198 USB 3.0 Host Controller [1b6f:7052]
             +-0f.0-[03-08]----00.0-[04-08]--+-00.0-[05]----00.0  Shenzhen Longsys Electronics Co., Ltd. FORESEE XP1000 / Lexar Professional CFexpress Type B Gold series, NM620 PCIe NVME SSD (DRAM-less) [1d97:5216]
             |                               +-08.0-[06]----00.0  MAXIO Technology (Hangzhou) Ltd. NVMe SSD Controller MAP1202 (DRAM-less) [1e4b:1202]
             |                               +-0c.0-[07]----00.0  Advanced Micro Devices, Inc. [AMD] 600 Series Chipset USB 3.2 Controller [1022:43f7]
             |                               \-0d.0-[08]----00.0  Advanced Micro Devices, Inc. [AMD] 600 Series Chipset SATA Controller [1022:43f6]
             \-16.0  Loongson Technology LLC 7A1000 Chipset SPI Controller [0014:7a0b]

Fixes: 2410e3301f ("PCI: loongson: Don't access non-existent devices")
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Co-developed-by: Lain "Fearyncess" Yang <i@lain.vg>
Signed-off-by: Lain "Fearyncess" Yang <i@lain.vg>
Signed-off-by: Rong Zhang <i@rong.moe>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://oshwhub.com/wesd/b650 [1]
Link: https://patch.msgid.link/20260501-ls7a-bridge-fixes-v2-1-69fa93683805@rong.moe
This commit is contained in:
Rong Zhang 2026-05-01 02:45:23 +08:00 committed by Manivannan Sadhasivam
parent 254f49634e
commit 1389ab9bf9

View File

@ -80,6 +80,18 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_LPC, system_bus_quirk);
static const struct pci_device_id loongson_internal_bridge_devids[] = {
{ PCI_VDEVICE(LOONGSON, DEV_LS2K_PCIE_PORT0) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT0) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT1) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT2) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT3) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT4) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT5) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT6) },
{ 0, },
};
/*
* Some Loongson PCIe ports have hardware limitations on their Maximum Read
* Request Size. They can't handle anything larger than this. Sane
@ -92,24 +104,13 @@ static void loongson_set_min_mrrs_quirk(struct pci_dev *pdev)
{
struct pci_bus *bus = pdev->bus;
struct pci_dev *bridge;
static const struct pci_device_id bridge_devids[] = {
{ PCI_VDEVICE(LOONGSON, DEV_LS2K_PCIE_PORT0) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT0) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT1) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT2) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT3) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT4) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT5) },
{ PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT6) },
{ 0, },
};
/* look for the matching bridge */
while (!pci_is_root_bus(bus)) {
bridge = bus->self;
bus = bus->parent;
if (pci_match_id(bridge_devids, bridge)) {
if (pci_match_id(loongson_internal_bridge_devids, bridge)) {
if (pcie_get_readrq(pdev) > 256) {
pci_info(pdev, "limiting MRRS to 256\n");
pcie_set_readrq(pdev, 256);
@ -230,11 +231,11 @@ static void __iomem *pci_loongson_map_bus(struct pci_bus *bus,
struct loongson_pci *priv = pci_bus_to_loongson_pci(bus);
/*
* Do not read more than one device on the bus other than
* the host bus.
* Do not read more than one device on the internal bridges.
*/
if ((priv->data->flags & FLAG_DEV_FIX) && bus->self) {
if (!pci_is_root_bus(bus) && (device > 0))
if (!pci_is_root_bus(bus) && (device > 0) &&
pci_match_id(loongson_internal_bridge_devids, bus->self))
return NULL;
}