aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-10-14 15:56:15 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2011-10-27 15:45:44 -0400
commita1c473aa11e61bc871be16279c9bf976acf22504 (patch)
tree13f1c4565817bab8660e2e38f8fedc5344519788 /drivers/pci
parent62f392ea5b5f87b641e16e61a4cedda21ef7341f (diff)
pci: Clamp pcie_set_readrq() when using "performance" settings
When configuring the PCIe settings for "performance", we allow parents to have a larger Max Payload Size than children and rely on children Max Read Request Size to not be larger than their own MPS to avoid having the host bridge generate responses they can't cope with. However, various drivers in Linux call pci_set_readrq() with arbitrary values, assuming this to be a simple performance tweak. This breaks under our "performance" configuration. Fix that by making sure the value programmed by pcie_set_readrq() is never larger than the configured MPS for that device. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Jon Mason <mason@myri.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7cd417e94058..6f45a73c6e9f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3202,8 +3202,6 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
3202 if (rq < 128 || rq > 4096 || !is_power_of_2(rq)) 3202 if (rq < 128 || rq > 4096 || !is_power_of_2(rq))
3203 goto out; 3203 goto out;
3204 3204
3205 v = (ffs(rq) - 8) << 12;
3206
3207 cap = pci_pcie_cap(dev); 3205 cap = pci_pcie_cap(dev);
3208 if (!cap) 3206 if (!cap)
3209 goto out; 3207 goto out;
@@ -3211,6 +3209,22 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
3211 err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); 3209 err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
3212 if (err) 3210 if (err)
3213 goto out; 3211 goto out;
3212 /*
3213 * If using the "performance" PCIe config, we clamp the
3214 * read rq size to the max packet size to prevent the
3215 * host bridge generating requests larger than we can
3216 * cope with
3217 */
3218 if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
3219 int mps = pcie_get_mps(dev);
3220
3221 if (mps < 0)
3222 return mps;
3223 if (mps < rq)
3224 rq = mps;
3225 }
3226
3227 v = (ffs(rq) - 8) << 12;
3214 3228
3215 if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) { 3229 if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
3216 ctl &= ~PCI_EXP_DEVCTL_READRQ; 3230 ctl &= ~PCI_EXP_DEVCTL_READRQ;