aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/probe.c
diff options
context:
space:
mode:
authorYijing Wang <wangyijing@huawei.com>2013-08-26 04:33:06 -0400
committerBjorn Helgaas <bhelgaas@google.com>2013-08-26 16:49:28 -0400
commit5895af79158a55562753f7f05762f3bd766d32b9 (patch)
tree39eecfd0c9fa8c4963ec081ea171977e05b5b0b9 /drivers/pci/probe.c
parent3315472c474af8e1c2beb40d980dfc92f03e4d8e (diff)
PCI: Warn if unsafe MPS settings detected
If a BIOS configures MPS incorrectly, devices may not work normally. For example, if a bridge has MPS set larger than an endpoint below it, the endpoint may discard packets. To help diagnose this issue, print a warning if we find an endpoint MPS setting different than that of the upstream bridge. [bhelgaas: changelog, "bridge" temporary, warning text] Reference: https://bugzilla.kernel.org/show_bug.cgi?id=60799 Reported-by: Joe Jin <joe.jin@oracle.com> Signed-off-by: Yijing Wang <wangyijing@huawei.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: Jon Mason <jdmason@kudzu.us>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r--drivers/pci/probe.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 94c5a77ce853..cd5c4acb5367 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1582,6 +1582,22 @@ static void pcie_write_mrrs(struct pci_dev *dev)
1582 "with pci=pcie_bus_safe.\n"); 1582 "with pci=pcie_bus_safe.\n");
1583} 1583}
1584 1584
1585static void pcie_bus_detect_mps(struct pci_dev *dev)
1586{
1587 struct pci_dev *bridge = dev->bus->self;
1588 int mps, p_mps;
1589
1590 if (!bridge)
1591 return;
1592
1593 mps = pcie_get_mps(dev);
1594 p_mps = pcie_get_mps(bridge);
1595
1596 if (mps != p_mps)
1597 dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
1598 mps, pci_name(bridge), p_mps);
1599}
1600
1585static int pcie_bus_configure_set(struct pci_dev *dev, void *data) 1601static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
1586{ 1602{
1587 int mps, orig_mps; 1603 int mps, orig_mps;
@@ -1589,6 +1605,11 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
1589 if (!pci_is_pcie(dev)) 1605 if (!pci_is_pcie(dev))
1590 return 0; 1606 return 0;
1591 1607
1608 if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
1609 pcie_bus_detect_mps(dev);
1610 return 0;
1611 }
1612
1592 mps = 128 << *(u8 *)data; 1613 mps = 128 << *(u8 *)data;
1593 orig_mps = pcie_get_mps(dev); 1614 orig_mps = pcie_get_mps(dev);
1594 1615
@@ -1616,9 +1637,6 @@ void pcie_bus_configure_settings(struct pci_bus *bus)
1616 if (!pci_is_pcie(bus->self)) 1637 if (!pci_is_pcie(bus->self))
1617 return; 1638 return;
1618 1639
1619 if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
1620 return;
1621
1622 /* FIXME - Peer to peer DMA is possible, though the endpoint would need 1640 /* FIXME - Peer to peer DMA is possible, though the endpoint would need
1623 * to be aware of the MPS of the destination. To work around this, 1641 * to be aware of the MPS of the destination. To work around this,
1624 * simply force the MPS of the entire system to the smallest possible. 1642 * simply force the MPS of the entire system to the smallest possible.