PCI: Disable MPS configuration by default

Add the ability to disable PCI-E MPS turning and using the BIOS
configured MPS defaults. Due to the number of issues recently
discovered on some x86 chipsets, make this the default behavior.

Also, add the option for peer to peer DMA MPS configuration. Peer to
peer DMA is outside the scope of this patch, but MPS configuration could
prevent it from working by having the MPS on one root port different
than the MPS on another. To work around this, simply make the system
wide MPS the smallest possible value (128B).

Signed-off-by: Jon Mason <mason@myri.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Jon Mason and committed by Linus Torvalds 5f39e670 05faadcf

Changed files
+20 -3
drivers
include
linux
+5 -1
drivers/pci/pci.c
··· 77 77 unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE; 78 78 unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE; 79 79 80 - enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_SAFE; 80 + enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF; 81 81 82 82 /* 83 83 * The default CLS is used if arch didn't set CLS explicitly and not ··· 3568 3568 pci_hotplug_io_size = memparse(str + 9, &str); 3569 3569 } else if (!strncmp(str, "hpmemsize=", 10)) { 3570 3570 pci_hotplug_mem_size = memparse(str + 10, &str); 3571 + } else if (!strncmp(str, "pcie_bus_tune_off", 17)) { 3572 + pcie_bus_config = PCIE_BUS_TUNE_OFF; 3571 3573 } else if (!strncmp(str, "pcie_bus_safe", 13)) { 3572 3574 pcie_bus_config = PCIE_BUS_SAFE; 3573 3575 } else if (!strncmp(str, "pcie_bus_perf", 13)) { 3574 3576 pcie_bus_config = PCIE_BUS_PERFORMANCE; 3577 + } else if (!strncmp(str, "pcie_bus_peer2peer", 18)) { 3578 + pcie_bus_config = PCIE_BUS_PEER2PEER; 3575 3579 } else { 3576 3580 printk(KERN_ERR "PCI: Unknown option `%s'\n", 3577 3581 str);
+13 -1
drivers/pci/probe.c
··· 1458 1458 */ 1459 1459 void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss) 1460 1460 { 1461 - u8 smpss = mpss; 1461 + u8 smpss; 1462 1462 1463 1463 if (!pci_is_pcie(bus->self)) 1464 1464 return; 1465 1465 1466 + if (pcie_bus_config == PCIE_BUS_TUNE_OFF) 1467 + return; 1468 + 1469 + /* FIXME - Peer to peer DMA is possible, though the endpoint would need 1470 + * to be aware to the MPS of the destination. To work around this, 1471 + * simply force the MPS of the entire system to the smallest possible. 1472 + */ 1473 + if (pcie_bus_config == PCIE_BUS_PEER2PEER) 1474 + smpss = 0; 1475 + 1466 1476 if (pcie_bus_config == PCIE_BUS_SAFE) { 1477 + smpss = mpss; 1478 + 1467 1479 pcie_find_smpss(bus->self, &smpss); 1468 1480 pci_walk_bus(bus, pcie_find_smpss, &smpss); 1469 1481 }
+2 -1
include/linux/pci.h
··· 621 621 extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss); 622 622 623 623 enum pcie_bus_config_types { 624 - PCIE_BUS_PERFORMANCE, 624 + PCIE_BUS_TUNE_OFF, 625 625 PCIE_BUS_SAFE, 626 + PCIE_BUS_PERFORMANCE, 626 627 PCIE_BUS_PEER2PEER, 627 628 }; 628 629