diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 795c9026d55f..6ab6bd3df4b2 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -856,6 +856,8 @@ void set_pcie_port_type(struct pci_dev *pdev) | |||
856 | pdev->pcie_cap = pos; | 856 | pdev->pcie_cap = pos; |
857 | pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); | 857 | pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); |
858 | pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; | 858 | pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; |
859 | pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); | ||
860 | pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; | ||
859 | } | 861 | } |
860 | 862 | ||
861 | void set_pcie_hotplug_bridge(struct pci_dev *pdev) | 863 | void set_pcie_hotplug_bridge(struct pci_dev *pdev) |
@@ -1326,6 +1328,163 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) | |||
1326 | return nr; | 1328 | return nr; |
1327 | } | 1329 | } |
1328 | 1330 | ||
1331 | static int pcie_find_smpss(struct pci_dev *dev, void *data) | ||
1332 | { | ||
1333 | u8 *smpss = data; | ||
1334 | |||
1335 | if (!pci_is_pcie(dev)) | ||
1336 | return 0; | ||
1337 | |||
1338 | /* For PCIE hotplug enabled slots not connected directly to a | ||
1339 | * PCI-E root port, there can be problems when hotplugging | ||
1340 | * devices. This is due to the possibility of hotplugging a | ||
1341 | * device into the fabric with a smaller MPS that the devices | ||
1342 | * currently running have configured. Modifying the MPS on the | ||
1343 | * running devices could cause a fatal bus error due to an | ||
1344 | * incoming frame being larger than the newly configured MPS. | ||
1345 | * To work around this, the MPS for the entire fabric must be | ||
1346 | * set to the minimum size. Any devices hotplugged into this | ||
1347 | * fabric will have the minimum MPS set. If the PCI hotplug | ||
1348 | * slot is directly connected to the root port and there are not | ||
1349 | * other devices on the fabric (which seems to be the most | ||
1350 | * common case), then this is not an issue and MPS discovery | ||
1351 | * will occur as normal. | ||
1352 | */ | ||
1353 | if (dev->is_hotplug_bridge && (!list_is_singular(&dev->bus->devices) || | ||
1354 | (dev->bus->self && | ||
1355 | dev->bus->self->pcie_type != PCI_EXP_TYPE_ROOT_PORT))) | ||
1356 | *smpss = 0; | ||
1357 | |||
1358 | if (*smpss > dev->pcie_mpss) | ||
1359 | *smpss = dev->pcie_mpss; | ||
1360 | |||
1361 | return 0; | ||
1362 | } | ||
1363 | |||
1364 | static void pcie_write_mps(struct pci_dev *dev, int mps) | ||
1365 | { | ||
1366 | int rc, dev_mpss; | ||
1367 | |||
1368 | dev_mpss = 128 << dev->pcie_mpss; | ||
1369 | |||
1370 | if (pcie_bus_config == PCIE_BUS_PERFORMANCE) { | ||
1371 | if (dev->bus->self) { | ||
1372 | dev_dbg(&dev->bus->dev, "Bus MPSS %d\n", | ||
1373 | 128 << dev->bus->self->pcie_mpss); | ||
1374 | |||
1375 | /* For "MPS Force Max", the assumption is made that | ||
1376 | * downstream communication will never be larger than | ||
1377 | * the MRRS. So, the MPS only needs to be configured | ||
1378 | * for the upstream communication. This being the case, | ||
1379 | * walk from the top down and set the MPS of the child | ||
1380 | * to that of the parent bus. | ||
1381 | */ | ||
1382 | mps = 128 << dev->bus->self->pcie_mpss; | ||
1383 | if (mps > dev_mpss) | ||
1384 | dev_warn(&dev->dev, "MPS configured higher than" | ||
1385 | " maximum supported by the device. If" | ||
1386 | " a bus issue occurs, try running with" | ||
1387 | " pci=pcie_bus_safe.\n"); | ||
1388 | } | ||
1389 | |||
1390 | dev->pcie_mpss = ffs(mps) - 8; | ||
1391 | } | ||
1392 | |||
1393 | rc = pcie_set_mps(dev, mps); | ||
1394 | if (rc) | ||
1395 | dev_err(&dev->dev, "Failed attempting to set the MPS\n"); | ||
1396 | } | ||
1397 | |||
1398 | static void pcie_write_mrrs(struct pci_dev *dev, int mps) | ||
1399 | { | ||
1400 | int rc, mrrs, dev_mpss; | ||
1401 | |||
1402 | /* In the "safe" case, do not configure the MRRS. There appear to be | ||
1403 | * issues with setting MRRS to 0 on a number of devices. | ||
1404 | */ | ||
1405 | |||
1406 | if (pcie_bus_config != PCIE_BUS_PERFORMANCE) | ||
1407 | return; | ||
1408 | |||
1409 | dev_mpss = 128 << dev->pcie_mpss; | ||
1410 | |||
1411 | /* For Max performance, the MRRS must be set to the largest supported | ||
1412 | * value. However, it cannot be configured larger than the MPS the | ||
1413 | * device or the bus can support. This assumes that the largest MRRS | ||
1414 | * available on the device cannot be smaller than the device MPSS. | ||
1415 | */ | ||
1416 | mrrs = min(mps, dev_mpss); | ||
1417 | |||
1418 | /* MRRS is a R/W register. Invalid values can be written, but a | ||
1419 | * subsequent read will verify if the value is acceptable or not. | ||
1420 | * If the MRRS value provided is not acceptable (e.g., too large), | ||
1421 | * shrink the value until it is acceptable to the HW. | ||
1422 | */ | ||
1423 | while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) { | ||
1424 | dev_warn(&dev->dev, "Attempting to modify the PCI-E MRRS value" | ||
1425 | " to %d. If any issues are encountered, please try " | ||
1426 | "running with pci=pcie_bus_safe\n", mrrs); | ||
1427 | rc = pcie_set_readrq(dev, mrrs); | ||
1428 | if (rc) | ||
1429 | dev_err(&dev->dev, | ||
1430 | "Failed attempting to set the MRRS\n"); | ||
1431 | |||
1432 | mrrs /= 2; | ||
1433 | } | ||
1434 | } | ||
1435 | |||
1436 | static int pcie_bus_configure_set(struct pci_dev *dev, void *data) | ||
1437 | { | ||
1438 | int mps = 128 << *(u8 *)data; | ||
1439 | |||
1440 | if (!pci_is_pcie(dev)) | ||
1441 | return 0; | ||
1442 | |||
1443 | dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n", | ||
1444 | pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev)); | ||
1445 | |||
1446 | pcie_write_mps(dev, mps); | ||
1447 | pcie_write_mrrs(dev, mps); | ||
1448 | |||
1449 | dev_dbg(&dev->dev, "Dev MPS %d MPSS %d MRRS %d\n", | ||
1450 | pcie_get_mps(dev), 128<<dev->pcie_mpss, pcie_get_readrq(dev)); | ||
1451 | |||
1452 | return 0; | ||
1453 | } | ||
1454 | |||
1455 | /* pcie_bus_configure_mps requires that pci_walk_bus work in a top-down, | ||
1456 | * parents then children fashion. If this changes, then this code will not | ||
1457 | * work as designed. | ||
1458 | */ | ||
1459 | void pcie_bus_configure_settings(struct pci_bus *bus, u8 mpss) | ||
1460 | { | ||
1461 | u8 smpss; | ||
1462 | |||
1463 | if (!pci_is_pcie(bus->self)) | ||
1464 | return; | ||
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 | |||
1476 | if (pcie_bus_config == PCIE_BUS_SAFE) { | ||
1477 | smpss = mpss; | ||
1478 | |||
1479 | pcie_find_smpss(bus->self, &smpss); | ||
1480 | pci_walk_bus(bus, pcie_find_smpss, &smpss); | ||
1481 | } | ||
1482 | |||
1483 | pcie_bus_configure_set(bus->self, &smpss); | ||
1484 | pci_walk_bus(bus, pcie_bus_configure_set, &smpss); | ||
1485 | } | ||
1486 | EXPORT_SYMBOL_GPL(pcie_bus_configure_settings); | ||
1487 | |||
1329 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) | 1488 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) |
1330 | { | 1489 | { |
1331 | unsigned int devfn, pass, max = bus->secondary; | 1490 | unsigned int devfn, pass, max = bus->secondary; |