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: Sven Schnelle <svens@stackframe.org>
Tested-by: Simon Kirby <sim@hostway.ca>
Tested-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Reported-and-tested-by: Eric Dumazet <eric.dumazet@gmail.com>
Reported-and-tested-by: Niels Ole Salscheider <niels_ole@salscheider-online.de>
References: https://bugzilla.kernel.org/show_bug.cgi?id=42162
Signed-off-by: Jon Mason <mason@myri.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Jon Mason 2011-09-08 16:41:18 -05:00 committed by Linus Torvalds
parent 5307f6d5fb
commit ed2888e906
2 changed files with 23 additions and 20 deletions

View File

@ -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_io_size = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_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 * The default CLS is used if arch didn't set CLS explicitly and not

View File

@ -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) 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) { /* In the "safe" case, do not configure the MRRS. There appear to be
int dev_mpss = 128 << dev->pcie_mpss; * issues with setting MRRS to 0 on a number of devices.
*/
/* For Max performance, the MRRS must be set to the largest if (pcie_bus_config != PCIE_BUS_PERFORMANCE)
* supported value. However, it cannot be configured larger return;
* 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 = 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;
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 /* 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), * If the MRRS value provided is not acceptable (e.g., too large),
* shrink the value until it is acceptable to the HW. * shrink the value until it is acceptable to the HW.
*/ */
while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) { 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); rc = pcie_set_readrq(dev, mrrs);
if (rc) 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; mrrs /= 2;
} }
@ -1436,13 +1439,13 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
if (!pci_is_pcie(dev)) if (!pci_is_pcie(dev))
return 0; 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_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
pcie_write_mps(dev, mps); pcie_write_mps(dev, mps);
pcie_write_mrrs(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)); pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev));
return 0; return 0;