PCI: Add Extended Tag + MRRS quirk for Xeon 6

When bifurcated to x2, Xeon 6 Root Port performance is sensitive to the
configuration of Extended Tags, Max Read Request Size (MRRS), and 10-Bit
Tag Requester (note: there is currently no 10-Bit Tag support in the
kernel). While those can be configured to the recommended values by FW,
kernel may decide to overwrite the initial values.

Add a quirk that disallows enabling Extended Tags and setting MRRS
larger than 128B for devices under Xeon 6 Root Ports if the Root Port
is bifurcated to x2. Use the host bridge's enable_device hook to
overwrite MRRS if it's set to >128B for the device to be enabled.

The earlier attempts to implement this quirk polluted PCI core code with
the checks necessary to support this quirk. Using the enable_device hook
keeps the quirk well-contained, away from the PCI core code.

Suggested-by: Lukas Wunner <lukas@wunner.de>
Link: https://cdrdv2.intel.com/v1/dl/getContent/837176
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
[bhelgaas: 2x -> x2, rename quirk]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Link: https://patch.msgid.link/20250610114802.7460-1-ilpo.jarvinen@linux.intel.com
This commit is contained in:
Ilpo Järvinen
2025-06-10 14:48:02 +03:00
committed by Bjorn Helgaas
parent c763fae8c4
commit a22250fe93

View File

@@ -294,6 +294,46 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_r
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk);
/*
* PCIe devices underneath Xeon 6 PCIe Root Port bifurcated to x2 have lower
* performance with Extended Tags and MRRS > 128B. Work around the performance
* problems by disabling Extended Tags and limiting MRRS to 128B.
*
* https://cdrdv2.intel.com/v1/dl/getContent/837176
*/
static int limit_mrrs_to_128(struct pci_host_bridge *b, struct pci_dev *pdev)
{
int readrq = pcie_get_readrq(pdev);
if (readrq > 128)
pcie_set_readrq(pdev, 128);
return 0;
}
static void pci_xeon_x2_bifurc_quirk(struct pci_dev *pdev)
{
struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
u32 linkcap;
pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &linkcap);
if (FIELD_GET(PCI_EXP_LNKCAP_MLW, linkcap) != 0x2)
return;
bridge->no_ext_tags = 1;
bridge->enable_device = limit_mrrs_to_128;
pci_info(pdev, "Disabling Extended Tags and limiting MRRS to 128B (performance reasons due to x2 PCIe link)\n");
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db0, pci_xeon_x2_bifurc_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db1, pci_xeon_x2_bifurc_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db2, pci_xeon_x2_bifurc_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db3, pci_xeon_x2_bifurc_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db6, pci_xeon_x2_bifurc_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db7, pci_xeon_x2_bifurc_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db8, pci_xeon_x2_bifurc_quirk);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0db9, pci_xeon_x2_bifurc_quirk);
/*
* Fixup to mark boot BIOS video selected by BIOS before it changes
*