提交 5895af79 编写于 作者: Y Yijing Wang 提交者: Bjorn Helgaas

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=60799Reported-by: NJoe Jin <joe.jin@oracle.com>
Signed-off-by: NYijing Wang <wangyijing@huawei.com>
Signed-off-by: NBjorn Helgaas <bhelgaas@google.com>
Cc: Jon Mason <jdmason@kudzu.us>
上级 3315472c
......@@ -1582,6 +1582,22 @@ static void pcie_write_mrrs(struct pci_dev *dev)
"with pci=pcie_bus_safe.\n");
}
static void pcie_bus_detect_mps(struct pci_dev *dev)
{
struct pci_dev *bridge = dev->bus->self;
int mps, p_mps;
if (!bridge)
return;
mps = pcie_get_mps(dev);
p_mps = pcie_get_mps(bridge);
if (mps != p_mps)
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",
mps, pci_name(bridge), p_mps);
}
static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
{
int mps, orig_mps;
......@@ -1589,6 +1605,11 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
if (!pci_is_pcie(dev))
return 0;
if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
pcie_bus_detect_mps(dev);
return 0;
}
mps = 128 << *(u8 *)data;
orig_mps = pcie_get_mps(dev);
......@@ -1616,9 +1637,6 @@ void pcie_bus_configure_settings(struct pci_bus *bus)
if (!pci_is_pcie(bus->self))
return;
if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
return;
/* FIXME - Peer to peer DMA is possible, though the endpoint would need
* to be aware of the MPS of the destination. To work around this,
* simply force the MPS of the entire system to the smallest possible.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册