On Wed, May 25, 2011 at 3:16 PM, <Jordan_Hargrave@xxxxxxxx> wrote: > Hmm. I just added very similar code for setting PCIEmaxpayload during PCIE hotplug insertion. > perhaps these two should be merged? Yes, the code is nearly identical, as it is performing the same function. Perhaps that code should be moved to a more common place (bus.c?), and called at both necessary locations. Also, there probably should be a flag to denote where it is being called, as it is a BIOS bug in my case. Thanks, Jon > > --jordan hargrave > Dell Enterprise Linux Engineering > >> -----Original Message----- >> From: linux-pci-owner@xxxxxxxxxxxxxxx [mailto:linux-pci- >> owner@xxxxxxxxxxxxxxx] On Behalf Of Jon Mason >> Sent: Wednesday, May 25, 2011 2:01 PM >> To: Jesse Barnes >> Cc: linux-pci@xxxxxxxxxxxxxxx; Andrew Gallatin >> Subject: [PATCH] PCI: Max Payload Size BIOS workaround >> >> Ensure that the max payload size on the root port is the same as the >> max >> payload size on all intermediate bridges and devices. This is required >> to work around buggy BIOS revisions found on various whitebox >> motherboards which do not configure mps beyond one level below the root >> port. >> >> Signed-off-by: Jon Mason <mason@xxxxxxxx> >> Signed-off-by: Andrew Gallatin <gallatin@xxxxxxxx> >> --- >> drivers/pci/bus.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ >> 1 files changed, 44 insertions(+), 0 deletions(-) >> >> diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c >> index 69546e9..fc16b67 100644 >> --- a/drivers/pci/bus.c >> +++ b/drivers/pci/bus.c >> @@ -175,6 +175,49 @@ int pci_bus_add_child(struct pci_bus *bus) >> return retval; >> } >> >> +/* >> + * Ensure that the max payload size on the root port is the same as >> the max >> + * payload size on all intermediate bridges. This is required to work >> around >> + * buggy BIOS revisions found on various whitebox motherboards which >> do not >> + * configure mps beyond one level below the root port. >> + */ >> +static void pci_mps_workaround(struct pci_dev *child, struct pci_dev >> *parent) >> +{ >> + u16 val, pmps, cmps; >> + int cap, rc; >> + >> + if (!parent) >> + return; >> + >> + cap = pci_find_capability(parent, PCI_CAP_ID_EXP); >> + if (!cap) >> + return; >> + >> + rc = pci_read_config_word(parent, cap + PCI_EXP_DEVCTL, &val); >> + if (rc) >> + return; >> + >> + pmps = val & PCI_EXP_DEVCTL_PAYLOAD; >> + >> + cap = pci_find_capability(child, PCI_CAP_ID_EXP); >> + if (!cap) >> + return; >> + >> + rc = pci_read_config_word(child, cap + PCI_EXP_DEVCTL, &val); >> + if (rc) >> + return; >> + >> + cmps = val & PCI_EXP_DEVCTL_PAYLOAD; >> + >> + if (pmps != cmps) { >> + printk(KERN_WARNING "Child MPS of %d != Parent MPS of %d! >> " >> + "Most likely caused by bad BIOS. Working >> around...\n", >> + 128 << (cmps >> 5), 128 << (pmps >> 5)); >> + val = (val & ~ PCI_EXP_DEVCTL_PAYLOAD) | pmps; >> + pci_write_config_word(child, cap + PCI_EXP_DEVCTL, val); >> + } >> +} >> + >> /** >> * pci_bus_add_devices - insert newly discovered PCI devices >> * @bus: bus to check for new devices >> @@ -194,6 +237,7 @@ void pci_bus_add_devices(const struct pci_bus *bus) >> int retval; >> >> list_for_each_entry(dev, &bus->devices, bus_list) { >> + pci_mps_workaround(dev, dev->bus->self); >> /* Skip already-added devices */ >> if (dev->is_added) >> continue; >> -- >> 1.7.4.1 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-pci" in >> the body of a message to majordomo@xxxxxxxxxxxxxxx >> More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html