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
This commit is contained in:
commit
07f2daad09
@ -1672,12 +1672,8 @@ void pcibios_scan_phb(struct pci_controller *hose)
|
|||||||
/* Configure PCI Express settings */
|
/* Configure PCI Express settings */
|
||||||
if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
|
if (bus && !pci_has_flag(PCI_PROBE_ONLY)) {
|
||||||
struct pci_bus *child;
|
struct pci_bus *child;
|
||||||
list_for_each_entry(child, &bus->children, node) {
|
list_for_each_entry(child, &bus->children, node)
|
||||||
struct pci_dev *self = child->self;
|
pcie_bus_configure_settings(child);
|
||||||
if (!self)
|
|
||||||
continue;
|
|
||||||
pcie_bus_configure_settings(child, self->pcie_mpss);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,13 +508,8 @@ static void fixup_read_and_payload_sizes(struct pci_controller *controller)
|
|||||||
rc_dev_cap.word);
|
rc_dev_cap.word);
|
||||||
|
|
||||||
/* Configure PCI Express MPS setting. */
|
/* Configure PCI Express MPS setting. */
|
||||||
list_for_each_entry(child, &root_bus->children, node) {
|
list_for_each_entry(child, &root_bus->children, node)
|
||||||
struct pci_dev *self = child->self;
|
pcie_bus_configure_settings(child);
|
||||||
if (!self)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pcie_bus_configure_settings(child, self->pcie_mpss);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the mac_config register in trio based on the MPS/MRS of the link.
|
* Set the mac_config register in trio based on the MPS/MRS of the link.
|
||||||
|
@ -568,13 +568,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
|||||||
*/
|
*/
|
||||||
if (bus) {
|
if (bus) {
|
||||||
struct pci_bus *child;
|
struct pci_bus *child;
|
||||||
list_for_each_entry(child, &bus->children, node) {
|
list_for_each_entry(child, &bus->children, node)
|
||||||
struct pci_dev *self = child->self;
|
pcie_bus_configure_settings(child);
|
||||||
if (!self)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
pcie_bus_configure_settings(child, self->pcie_mpss);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bus && node != -1) {
|
if (bus && node != -1) {
|
||||||
|
@ -160,9 +160,8 @@ void pci_configure_slot(struct pci_dev *dev)
|
|||||||
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
|
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dev->bus && dev->bus->self)
|
if (dev->bus)
|
||||||
pcie_bus_configure_settings(dev->bus,
|
pcie_bus_configure_settings(dev->bus);
|
||||||
dev->bus->self->pcie_mpss);
|
|
||||||
|
|
||||||
memset(&hpp, 0, sizeof(hpp));
|
memset(&hpp, 0, sizeof(hpp));
|
||||||
ret = pci_get_hp_params(dev, &hpp);
|
ret = pci_get_hp_params(dev, &hpp);
|
||||||
|
@ -3939,8 +3939,6 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
|
|||||||
if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
|
if (pcie_bus_config == PCIE_BUS_PERFORMANCE) {
|
||||||
int mps = pcie_get_mps(dev);
|
int mps = pcie_get_mps(dev);
|
||||||
|
|
||||||
if (mps < 0)
|
|
||||||
return mps;
|
|
||||||
if (mps < rq)
|
if (mps < rq)
|
||||||
rq = mps;
|
rq = mps;
|
||||||
}
|
}
|
||||||
@ -3957,7 +3955,6 @@ EXPORT_SYMBOL(pcie_set_readrq);
|
|||||||
* @dev: PCI device to query
|
* @dev: PCI device to query
|
||||||
*
|
*
|
||||||
* Returns maximum payload size in bytes
|
* Returns maximum payload size in bytes
|
||||||
* or appropriate error value.
|
|
||||||
*/
|
*/
|
||||||
int pcie_get_mps(struct pci_dev *dev)
|
int pcie_get_mps(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
|
@ -1491,24 +1491,23 @@ static int pcie_find_smpss(struct pci_dev *dev, void *data)
|
|||||||
if (!pci_is_pcie(dev))
|
if (!pci_is_pcie(dev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* For PCIE hotplug enabled slots not connected directly to a
|
/*
|
||||||
* PCI-E root port, there can be problems when hotplugging
|
* We don't have a way to change MPS settings on devices that have
|
||||||
* devices. This is due to the possibility of hotplugging a
|
* drivers attached. A hot-added device might support only the minimum
|
||||||
* device into the fabric with a smaller MPS that the devices
|
* MPS setting (MPS=128). Therefore, if the fabric contains a bridge
|
||||||
* currently running have configured. Modifying the MPS on the
|
* where devices may be hot-added, we limit the fabric MPS to 128 so
|
||||||
* running devices could cause a fatal bus error due to an
|
* hot-added devices will work correctly.
|
||||||
* incoming frame being larger than the newly configured MPS.
|
*
|
||||||
* To work around this, the MPS for the entire fabric must be
|
* However, if we hot-add a device to a slot directly below a Root
|
||||||
* set to the minimum size. Any devices hotplugged into this
|
* Port, it's impossible for there to be other existing devices below
|
||||||
* fabric will have the minimum MPS set. If the PCI hotplug
|
* the port. We don't limit the MPS in this case because we can
|
||||||
* slot is directly connected to the root port and there are not
|
* reconfigure MPS on both the Root Port and the hot-added device,
|
||||||
* other devices on the fabric (which seems to be the most
|
* and there are no other devices involved.
|
||||||
* common case), then this is not an issue and MPS discovery
|
*
|
||||||
* will occur as normal.
|
* Note that this PCIE_BUS_SAFE path assumes no peer-to-peer DMA.
|
||||||
*/
|
*/
|
||||||
if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) ||
|
if (dev->is_hotplug_bridge &&
|
||||||
(dev->bus->self &&
|
pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
|
||||||
pci_pcie_type(dev->bus->self) != PCI_EXP_TYPE_ROOT_PORT)))
|
|
||||||
*smpss = 0;
|
*smpss = 0;
|
||||||
|
|
||||||
if (*smpss > dev->pcie_mpss)
|
if (*smpss > dev->pcie_mpss)
|
||||||
@ -1583,6 +1582,22 @@ static void pcie_write_mrrs(struct pci_dev *dev)
|
|||||||
"with pci=pcie_bus_safe.\n");
|
"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)
|
static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
|
||||||
{
|
{
|
||||||
int mps, orig_mps;
|
int mps, orig_mps;
|
||||||
@ -1590,13 +1605,18 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
|
|||||||
if (!pci_is_pcie(dev))
|
if (!pci_is_pcie(dev))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (pcie_bus_config == PCIE_BUS_TUNE_OFF) {
|
||||||
|
pcie_bus_detect_mps(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
mps = 128 << *(u8 *)data;
|
mps = 128 << *(u8 *)data;
|
||||||
orig_mps = pcie_get_mps(dev);
|
orig_mps = pcie_get_mps(dev);
|
||||||
|
|
||||||
pcie_write_mps(dev, mps);
|
pcie_write_mps(dev, mps);
|
||||||
pcie_write_mrrs(dev);
|
pcie_write_mrrs(dev);
|
||||||
|
|
||||||
dev_info(&dev->dev, "PCI-E Max Payload Size set to %4d/%4d (was %4d), "
|
dev_info(&dev->dev, "Max Payload Size set to %4d/%4d (was %4d), "
|
||||||
"Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss,
|
"Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss,
|
||||||
orig_mps, pcie_get_readrq(dev));
|
orig_mps, pcie_get_readrq(dev));
|
||||||
|
|
||||||
@ -1607,25 +1627,25 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)
|
|||||||
* parents then children fashion. If this changes, then this code will not
|
* parents then children fashion. If this changes, then this code will not
|
||||||
* work as designed.
|
* work as designed.
|
||||||
*/
|
*/
|
||||||
void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss)
|
void pcie_bus_configure_settings(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
u8 smpss;
|
u8 smpss;
|
||||||
|
|
||||||
|
if (!bus->self)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!pci_is_pcie(bus->self))
|
if (!pci_is_pcie(bus->self))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pcie_bus_config == PCIE_BUS_TUNE_OFF)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* FIXME - Peer to peer DMA is possible, though the endpoint would need
|
/* FIXME - Peer to peer DMA is possible, though the endpoint would need
|
||||||
* to be aware to the MPS of the destination. To work around this,
|
* 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.
|
* simply force the MPS of the entire system to the smallest possible.
|
||||||
*/
|
*/
|
||||||
if (pcie_bus_config == PCIE_BUS_PEER2PEER)
|
if (pcie_bus_config == PCIE_BUS_PEER2PEER)
|
||||||
smpss = 0;
|
smpss = 0;
|
||||||
|
|
||||||
if (pcie_bus_config == PCIE_BUS_SAFE) {
|
if (pcie_bus_config == PCIE_BUS_SAFE) {
|
||||||
smpss = mpss;
|
smpss = bus->self->pcie_mpss;
|
||||||
|
|
||||||
pcie_find_smpss(bus->self, &smpss);
|
pcie_find_smpss(bus->self, &smpss);
|
||||||
pci_walk_bus(bus, pcie_find_smpss, &smpss);
|
pci_walk_bus(bus, pcie_find_smpss, &smpss);
|
||||||
|
@ -675,7 +675,7 @@ struct pci_driver {
|
|||||||
/* these external functions are only available when PCI support is enabled */
|
/* these external functions are only available when PCI support is enabled */
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
|
|
||||||
void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
|
void pcie_bus_configure_settings(struct pci_bus *bus);
|
||||||
|
|
||||||
enum pcie_bus_config_types {
|
enum pcie_bus_config_types {
|
||||||
PCIE_BUS_TUNE_OFF,
|
PCIE_BUS_TUNE_OFF,
|
||||||
|
Loading…
Reference in New Issue
Block a user