diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2013-08-26 17:40:34 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-08-26 17:40:34 -0400 |
commit | 07f2daad094bc9e9770143cd2d619de24d84bb3e (patch) | |
tree | 202f930177f85456a129cfb3f7b5abc9615d52a4 /drivers/pci/probe.c | |
parent | 1193725f543c92a77c73769bc2fbe48c53275f53 (diff) | |
parent | 5895af79158a55562753f7f05762f3bd766d32b9 (diff) |
Merge branch 'pci/yijing-mps-v8' into next
* pci/yijing-mps-v8:
PCI: Warn if unsafe MPS settings detected
PCI: Fix MPS peer-to-peer DMA comment syntax
PCI: Don't restrict MPS for slots below Root Ports
PCI: Simplify MPS test for Downstream Port
PCI: Remove unnecessary check for pcie_get_mps() failure
PCI: Simplify pcie_bus_configure_settings() interface
PCI: Drop "PCI-E" prefix from Max Payload Size message
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 4ab388a6cc26..a57762fbe10e 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1491,24 +1491,23 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data) | |||
1491 | if (!pci_is_pcie(dev)) | 1491 | if (!pci_is_pcie(dev)) |
1492 | return 0; | 1492 | return 0; |
1493 | 1493 | ||
1494 | /* For PCIE hotplug enabled slots not connected directly to a | 1494 | /* |
1495 | * PCI-E root port, there can be problems when hotplugging | 1495 | * We don't have a way to change MPS settings on devices that have |
1496 | * devices. This is due to the possibility of hotplugging a | 1496 | * drivers attached. A hot-added device might support only the minimum |
1497 | * device into the fabric with a smaller MPS that the devices | 1497 | * MPS setting (MPS=128). Therefore, if the fabric contains a bridge |
1498 | * currently running have configured. Modifying the MPS on the | 1498 | * where devices may be hot-added, we limit the fabric MPS to 128 so |
1499 | * running devices could cause a fatal bus error due to an | 1499 | * hot-added devices will work correctly. |
1500 | * incoming frame being larger than the newly configured MPS. | 1500 | * |
1501 | * To work around this, the MPS for the entire fabric must be | 1501 | * However, if we hot-add a device to a slot directly below a Root |
1502 | * set to the minimum size. Any devices hotplugged into this | 1502 | * Port, it's impossible for there to be other existing devices below |
1503 | * fabric will have the minimum MPS set. If the PCI hotplug | 1503 | * the port. We don't limit the MPS in this case because we can |
1504 | * slot is directly connected to the root port and there are not | 1504 | * reconfigure MPS on both the Root Port and the hot-added device, |
1505 | * other devices on the fabric (which seems to be the most | 1505 | * and there are no other devices involved. |
1506 | * common case), then this is not an issue and MPS discovery | 1506 | * |
1507 | * will occur as normal. | 1507 | * Note that this PCIE_BUS_SAFE path assumes no peer-to-peer DMA. |
1508 | */ | 1508 | */ |
1509 | if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) || | 1509 | if (dev->is_hotplug_bridge && |
1510 | (dev->bus->self && | 1510 | pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) |
1511 | pci_pcie_type(dev->bus->self) != PCI_EXP_TYPE_ROOT_PORT))) | ||
1512 | *smpss = 0; | 1511 | *smpss = 0; |
1513 | 1512 | ||
1514 | if (*smpss > dev->pcie_mpss) | 1513 | if (*smpss > dev->pcie_mpss) |
@@ -1583,6 +1582,22 @@ static void pcie_write_mrrs(struct pci_dev *dev) | |||
1583 | "with pci=pcie_bus_safe.\n"); | 1582 | "with pci=pcie_bus_safe.\n"); |
1584 | } | 1583 | } |
1585 | 1584 | ||
1585 | static 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 | |||
1586 | static int pcie_bus_configure_set(struct pci_dev *dev, void *data) | 1601 | static int pcie_bus_configure_set(struct pci_dev *dev, void *data) |
1587 | { | 1602 | { |
1588 | int mps, orig_mps; | 1603 | int mps, orig_mps; |
@@ -1590,13 +1605,18 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data) | |||
1590 | if (!pci_is_pcie(dev)) | 1605 | if (!pci_is_pcie(dev)) |
1591 | return 0; | 1606 | return 0; |
1592 | 1607 | ||
1608 | if (pcie_bus_config == PCIE_BUS_TUNE_OFF) { | ||
1609 | pcie_bus_detect_mps(dev); | ||
1610 | return 0; | ||
1611 | } | ||
1612 | |||
1593 | mps = 128 << *(u8 *)data; | 1613 | mps = 128 << *(u8 *)data; |
1594 | orig_mps = pcie_get_mps(dev); | 1614 | orig_mps = pcie_get_mps(dev); |
1595 | 1615 | ||
1596 | pcie_write_mps(dev, mps); | 1616 | pcie_write_mps(dev, mps); |
1597 | pcie_write_mrrs(dev); | 1617 | pcie_write_mrrs(dev); |
1598 | 1618 | ||
1599 | dev_info(&dev->dev, "PCI-E Max Payload Size set to %4d/%4d (was %4d), " | 1619 | dev_info(&dev->dev, "Max Payload Size set to %4d/%4d (was %4d), " |
1600 | "Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss, | 1620 | "Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss, |
1601 | orig_mps, pcie_get_readrq(dev)); | 1621 | orig_mps, pcie_get_readrq(dev)); |
1602 | 1622 | ||
@@ -1607,25 +1627,25 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data) | |||
1607 | * parents then children fashion. If this changes, then this code will not | 1627 | * parents then children fashion. If this changes, then this code will not |
1608 | * work as designed. | 1628 | * work as designed. |
1609 | */ | 1629 | */ |
1610 | void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss) | 1630 | void pcie_bus_configure_settings(struct pci_bus *bus) |
1611 | { | 1631 | { |
1612 | u8 smpss; | 1632 | u8 smpss; |
1613 | 1633 | ||
1614 | if (!pci_is_pcie(bus->self)) | 1634 | if (!bus->self) |
1615 | return; | 1635 | return; |
1616 | 1636 | ||
1617 | if (pcie_bus_config == PCIE_BUS_TUNE_OFF) | 1637 | if (!pci_is_pcie(bus->self)) |
1618 | return; | 1638 | return; |
1619 | 1639 | ||
1620 | /* 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 |
1621 | * to be aware to the MPS of the destination. To work around this, | 1641 | * to be aware of the MPS of the destination. To work around this, |
1622 | * 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. |
1623 | */ | 1643 | */ |
1624 | if (pcie_bus_config == PCIE_BUS_PEER2PEER) | 1644 | if (pcie_bus_config == PCIE_BUS_PEER2PEER) |
1625 | smpss = 0; | 1645 | smpss = 0; |
1626 | 1646 | ||
1627 | if (pcie_bus_config == PCIE_BUS_SAFE) { | 1647 | if (pcie_bus_config == PCIE_BUS_SAFE) { |
1628 | smpss = mpss; | 1648 | smpss = bus->self->pcie_mpss; |
1629 | 1649 | ||
1630 | pcie_find_smpss(bus->self, &smpss); | 1650 | pcie_find_smpss(bus->self, &smpss); |
1631 | pci_walk_bus(bus, pcie_find_smpss, &smpss); | 1651 | pci_walk_bus(bus, pcie_find_smpss, &smpss); |