Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed2888e9 authored by Jon Mason's avatar Jon Mason Committed by Linus Torvalds
Browse files

PCI: Remove MRRS modification from MPS setting code



Modifying the Maximum Read Request Size to 0 (value of 128Bytes) has
massive negative ramifications on some devices.  Without knowing which
devices have this issue, do not modify from the default value when
walking the PCI-E bus in pcie_bus_safe mode.  Also, make pcie_bus_safe
the default procedure.

Tested-by: default avatarSven Schnelle <svens@stackframe.org>
Tested-by: default avatarSimon Kirby <sim@hostway.ca>
Tested-by: default avatarStephen M. Cameron <scameron@beardog.cce.hp.com>
Reported-and-tested-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Reported-and-tested-by: default avatarNiels Ole Salscheider <niels_ole@salscheider-online.de>
References: https://bugzilla.kernel.org/show_bug.cgi?id=42162


Signed-off-by: default avatarJon Mason <mason@myri.com>
Acked-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5307f6d5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;

enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_PERFORMANCE;
enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE;

/*
 * The default CLS is used if arch didn't set CLS explicitly and not
+22 −19
Original line number Diff line number Diff line
@@ -1396,34 +1396,37 @@ static void pcie_write_mps(struct pci_dev *dev, int mps)

static void pcie_write_mrrs(struct pci_dev *dev, int mps)
{
	int rc, mrrs;
	int rc, mrrs, dev_mpss;

	if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
		int dev_mpss = 128 << dev->pcie_mpss;

		/* For Max performance, the MRRS must be set to the largest
		 * supported value.  However, it cannot be configured larger
		 * than the MPS the device or the bus can support.  This assumes
		 * that the largest MRRS available on the device cannot be
		 * smaller than the device MPSS.
	/* In the "safe" case, do not configure the MRRS.  There appear to be
	 * issues with setting MRRS to 0 on a number of devices.
	 */
		mrrs = mps < dev_mpss ? mps : dev_mpss;
	} else
		/* In the "safe" case, configure the MRRS for fairness on the
		 * bus by making all devices have the same size
		 */
		mrrs = mps;

	if (pcie_bus_config != PCIE_BUS_PERFORMANCE)
		return;

	dev_mpss = 128 << dev->pcie_mpss;

	/* For Max performance, the MRRS must be set to the largest supported
	 * value.  However, it cannot be configured larger than the MPS the
	 * device or the bus can support.  This assumes that the largest MRRS
	 * available on the device cannot be smaller than the device MPSS.
	 */
	mrrs = min(mps, dev_mpss);

	/* MRRS is a R/W register.  Invalid values can be written, but a
	 * subsiquent read will verify if the value is acceptable or not.
	 * subsequent read will verify if the value is acceptable or not.
	 * If the MRRS value provided is not acceptable (e.g., too large),
	 * shrink the value until it is acceptable to the HW.
 	 */
	while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {
		dev_warn(&dev->dev, "Attempting to modify the PCI-E MRRS value"
			 " to %d.  If any issues are encountered, please try "
			 "running with pci=pcie_bus_safe\n", mrrs);
		rc = pcie_set_readrq(dev, mrrs);
		if (rc)
			dev_err(&dev->dev, "Failed attempting to set the MRRS\n");
			dev_err(&dev->dev,
				"Failed attempting to set the MRRS\n");

		mrrs /= 2;
	}
@@ -1436,13 +1439,13 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
	if (!pci_is_pcie(dev))
		return 0;

	dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
	dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
		 pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));

	pcie_write_mps(dev, mps);
	pcie_write_mrrs(dev, mps);

	dev_info(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
	dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n",
		 pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));

	return 0;