| From aa0ce96d72dd2e1b0dfd0fb868f82876e7790878 Mon Sep 17 00:00:00 2001 |
| From: Ashok Raj <ashok.raj@intel.com> |
| Date: Fri, 27 Mar 2020 14:16:15 -0700 |
| Subject: PCI: Program MPS for RCiEP devices |
| |
| From: Ashok Raj <ashok.raj@intel.com> |
| |
| commit aa0ce96d72dd2e1b0dfd0fb868f82876e7790878 upstream. |
| |
| Root Complex Integrated Endpoints (RCiEPs) do not have an upstream bridge, |
| so pci_configure_mps() previously ignored them, which may result in reduced |
| performance. |
| |
| Instead, program the Max_Payload_Size of RCiEPs to the maximum supported |
| value (unless it is limited for the PCIE_BUS_PEER2PEER case). This also |
| affects the subsequent programming of Max_Read_Request_Size because Linux |
| programs MRRS based on the MPS value. |
| |
| Fixes: 9dae3a97297f ("PCI: Move MPS configuration check to pci_configure_device()") |
| Link: https://lore.kernel.org/r/1585343775-4019-1-git-send-email-ashok.raj@intel.com |
| Tested-by: Dave Jiang <dave.jiang@intel.com> |
| Signed-off-by: Ashok Raj <ashok.raj@intel.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/pci/probe.c | 22 +++++++++++++++++++++- |
| 1 file changed, 21 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/pci/probe.c |
| +++ b/drivers/pci/probe.c |
| @@ -1934,13 +1934,33 @@ static void pci_configure_mps(struct pci |
| struct pci_dev *bridge = pci_upstream_bridge(dev); |
| int mps, mpss, p_mps, rc; |
| |
| - if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge)) |
| + if (!pci_is_pcie(dev)) |
| return; |
| |
| /* MPS and MRRS fields are of type 'RsvdP' for VFs, short-circuit out */ |
| if (dev->is_virtfn) |
| return; |
| |
| + /* |
| + * For Root Complex Integrated Endpoints, program the maximum |
| + * supported value unless limited by the PCIE_BUS_PEER2PEER case. |
| + */ |
| + if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) { |
| + if (pcie_bus_config == PCIE_BUS_PEER2PEER) |
| + mps = 128; |
| + else |
| + mps = 128 << dev->pcie_mpss; |
| + rc = pcie_set_mps(dev, mps); |
| + if (rc) { |
| + pci_warn(dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n", |
| + mps); |
| + } |
| + return; |
| + } |
| + |
| + if (!bridge || !pci_is_pcie(bridge)) |
| + return; |
| + |
| mps = pcie_get_mps(dev); |
| p_mps = pcie_get_mps(bridge); |
| |