mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
Merge branch 'pci/controller/loongson'
- Ignore downstream devices only on internal bridges to avoid Loongson hardware issue (Rong Zhang) - Quirk old Loongson-3C6000 bridges that advertise incorrect supported link speeds (Ziyao Li) * pci/controller/loongson: PCI: loongson: Override PCIe bridge supported speeds for Loongson-3C6000 series PCI: loongson: Do not ignore downstream devices on external bridges
This commit is contained in:
commit
a5c8e1ffe9
|
|
@ -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);
|
||||
|
|
@ -176,6 +177,42 @@ 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 0x3c19,
|
||||
* 0x3c29) 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, "fixed 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;
|
||||
|
|
@ -230,11 +267,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user