Skip to content

Commit

Permalink
PCI: loongson: Limit MRRS to 256
Browse files Browse the repository at this point in the history
commit ef61a04 upstream.

This is a partial revert of 8b3517f ("PCI: loongson: Prevent LS7A MRRS
increases") for MIPS-based Loongson.

Some MIPS Loongson systems don't support arbitrary Max_Read_Request_Size
(MRRS) settings.  8b3517f ("PCI: loongson: Prevent LS7A MRRS
increases") worked around that by (1) assuming that firmware configured
MRRS to the maximum supported value and (2) preventing the PCI core from
increasing MRRS.

Unfortunately, some firmware doesn't set that maximum MRRS correctly, which
results in devices not being initialized correctly.  One symptom, from the
Debian report below, is this:

  ata4.00: exception Emask 0x0 SAct 0x20000000 SErr 0x0 action 0x6 frozen
  ata4.00: failed command: WRITE FPDMA QUEUED
  ata4.00: cmd 61/20:e8:00:f0:e1/00:00:00:00:00/40 tag 29 ncq dma 16384 out
           res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4 (timeout)
  ata4.00: status: { DRDY }
  ata4: hard resetting link

Limit MRRS to 256 because MIPS Loongson with higher MRRS support is
considered rare.

This must be done at device enablement stage because the MRRS setting may
get lost if PCI_COMMAND_MASTER on the parent bridge is cleared, and we are
only sure parent bridge is enabled at this point.

Fixes: 8b3517f ("PCI: loongson: Prevent LS7A MRRS increases")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217680
Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1035587
Link: https://lore.kernel.org/r/20231201115028.84351-1-jiaxun.yang@flygoat.com
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Huacai Chen <chenhuacai@loongson.cn>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
FlyGoat authored and gregkh committed Dec 20, 2023
1 parent 5cc8d88 commit 4fb5358
Showing 1 changed file with 41 additions and 5 deletions.
46 changes: 41 additions & 5 deletions drivers/pci/controller/pci-loongson.c
Expand Up @@ -80,13 +80,49 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
DEV_LS7A_LPC, system_bus_quirk);

/*
* Some Loongson PCIe ports have hardware limitations on their Maximum Read
* Request Size. They can't handle anything larger than this. Sane
* firmware will set proper MRRS at boot, so we only need no_inc_mrrs for
* bridges. However, some MIPS Loongson firmware doesn't set MRRS properly,
* so we have to enforce maximum safe MRRS, which is 256 bytes.
*/
#ifdef CONFIG_MIPS
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 (pcie_get_readrq(pdev) > 256) {
pci_info(pdev, "limiting MRRS to 256\n");
pcie_set_readrq(pdev, 256);
}
break;
}
}
}
DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, loongson_set_min_mrrs_quirk);
#endif

static void loongson_mrrs_quirk(struct pci_dev *pdev)
{
/*
* Some Loongson PCIe ports have h/w limitations of maximum read
* request size. They can't handle anything larger than this. So
* force this limit on any devices attached under these ports.
*/
struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);

bridge->no_inc_mrrs = 1;
Expand Down

0 comments on commit 4fb5358

Please sign in to comment.