diff options
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 8 | ||||
-rw-r--r-- | arch/tile/kernel/pci_gx.c | 9 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 9 | ||||
-rw-r--r-- | drivers/pci/hotplug/pcihp_slot.c | 5 | ||||
-rw-r--r-- | drivers/pci/pci.c | 3 | ||||
-rw-r--r-- | drivers/pci/probe.c | 66 | ||||
-rw-r--r-- | include/linux/pci.h | 2 |
7 files changed, 52 insertions, 50 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index f46914a0f33e..d35ec34de1b4 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -1672,12 +1672,8 @@ void pcibios_scan_phb(struct pci_controller *hose) | |||
1672 | /* Configure PCI Express settings */ | 1672 | /* Configure PCI Express settings */ |
1673 | if (bus && !pci_has_flag(PCI_PROBE_ONLY)) { | 1673 | if (bus && !pci_has_flag(PCI_PROBE_ONLY)) { |
1674 | struct pci_bus *child; | 1674 | struct pci_bus *child; |
1675 | list_for_each_entry(child, &bus->children, node) { | 1675 | list_for_each_entry(child, &bus->children, node) |
1676 | struct pci_dev *self = child->self; | 1676 | pcie_bus_configure_settings(child); |
1677 | if (!self) | ||
1678 | continue; | ||
1679 | pcie_bus_configure_settings(child, self->pcie_mpss); | ||
1680 | } | ||
1681 | } | 1677 | } |
1682 | } | 1678 | } |
1683 | 1679 | ||
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c index 11425633b2d7..6640e7bbeaa2 100644 --- a/arch/tile/kernel/pci_gx.c +++ b/arch/tile/kernel/pci_gx.c | |||
@@ -508,13 +508,8 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller) | |||
508 | rc_dev_cap.word); | 508 | rc_dev_cap.word); |
509 | 509 | ||
510 | /* Configure PCI Express MPS setting. */ | 510 | /* Configure PCI Express MPS setting. */ |
511 | list_for_each_entry(child, &root_bus->children, node) { | 511 | list_for_each_entry(child, &root_bus->children, node) |
512 | struct pci_dev *self = child->self; | 512 | pcie_bus_configure_settings(child); |
513 | if (!self) | ||
514 | continue; | ||
515 | |||
516 | pcie_bus_configure_settings(child, self->pcie_mpss); | ||
517 | } | ||
518 | 513 | ||
519 | /* | 514 | /* |
520 | * Set the mac_config register in trio based on the MPS/MRS of the link. | 515 | * Set the mac_config register in trio based on the MPS/MRS of the link. |
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index d641897a1f4e..b30e937689d6 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -568,13 +568,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
568 | */ | 568 | */ |
569 | if (bus) { | 569 | if (bus) { |
570 | struct pci_bus *child; | 570 | struct pci_bus *child; |
571 | list_for_each_entry(child, &bus->children, node) { | 571 | list_for_each_entry(child, &bus->children, node) |
572 | struct pci_dev *self = child->self; | 572 | pcie_bus_configure_settings(child); |
573 | if (!self) | ||
574 | continue; | ||
575 | |||
576 | pcie_bus_configure_settings(child, self->pcie_mpss); | ||
577 | } | ||
578 | } | 573 | } |
579 | 574 | ||
580 | if (bus && node != -1) { | 575 | if (bus && node != -1) { |
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index fec2d5b75440..16f920352317 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c | |||
@@ -160,9 +160,8 @@ void pci_configure_slot(struct pci_dev *dev) | |||
160 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | 160 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) |
161 | return; | 161 | return; |
162 | 162 | ||
163 | if (dev->bus && dev->bus->self) | 163 | if (dev->bus) |
164 | pcie_bus_configure_settings(dev->bus, | 164 | pcie_bus_configure_settings(dev->bus); |
165 | dev->bus->self->pcie_mpss); | ||
166 | 165 | ||
167 | memset(&hpp, 0, sizeof(hpp)); | 166 | memset(&hpp, 0, sizeof(hpp)); |
168 | ret = pci_get_hp_params(dev, &hpp); | 167 | ret = pci_get_hp_params(dev, &hpp); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d3fdce8f3d65..4e15bc9712fd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -3939,8 +3939,6 @@ int pcie_set_readrq(struct pci_dev *dev, int rq) | |||
3939 | if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { | 3939 | if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { |
3940 | int mps = pcie_get_mps(dev); | 3940 | int mps = pcie_get_mps(dev); |
3941 | 3941 | ||
3942 | if (mps < 0) | ||
3943 | return mps; | ||
3944 | if (mps < rq) | 3942 | if (mps < rq) |
3945 | rq = mps; | 3943 | rq = mps; |
3946 | } | 3944 | } |
@@ -3957,7 +3955,6 @@ EXPORT_SYMBOL(pcie_set_readrq); | |||
3957 | * @dev: PCI device to query | 3955 | * @dev: PCI device to query |
3958 | * | 3956 | * |
3959 | * Returns maximum payload size in bytes | 3957 | * Returns maximum payload size in bytes |
3960 | * or appropriate error value. | ||
3961 | */ | 3958 | */ |
3962 | int pcie_get_mps(struct pci_dev *dev) | 3959 | int pcie_get_mps(struct pci_dev *dev) |
3963 | { | 3960 | { |
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); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 82d1c78d3d91..b3b716524be5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -675,7 +675,7 @@ struct pci_driver { | |||
675 | /* these external functions are only available when PCI support is enabled */ | 675 | /* these external functions are only available when PCI support is enabled */ |
676 | #ifdef CONFIG_PCI | 676 | #ifdef CONFIG_PCI |
677 | 677 | ||
678 | void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss); | 678 | void pcie_bus_configure_settings(struct pci_bus *bus); |
679 | 679 | ||
680 | enum pcie_bus_config_types { | 680 | enum pcie_bus_config_types { |
681 | PCIE_BUS_TUNE_OFF, | 681 | PCIE_BUS_TUNE_OFF, |