diff options
| author | Peter Oruba <peter.oruba@amd.com> | 2007-05-15 07:59:13 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-11 19:02:07 -0400 |
| commit | d556ad4bbe75faf17b239e151a9f003322b2e851 (patch) | |
| tree | 794e4f21a9c6e76328feccf313e4d268d3ec5146 | |
| parent | e4585da22ad04a055cbb5c863a37aa8cc02eac89 (diff) | |
PCI: add PCI-X/PCI-Express read control interfaces
This patch introduces an interface to read and write PCI-X / PCI-Express
maximum read byte count values from PCI config space. There is a second
function that returns the maximum _designed_ read byte count, which marks the
maximum value for a device, since some drivers try to set MMRBC to the
highest allowed value and rely on such a function.
Based on patch set by Stephen Hemminger <shemminger@linux-foundation.org>
Cc: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Peter Oruba <peter.oruba@amd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/pci/pci.c | 160 | ||||
| -rw-r--r-- | drivers/pci/quirks.c | 16 | ||||
| -rw-r--r-- | include/linux/pci.h | 7 |
3 files changed, 182 insertions, 1 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index fd47ac0c4730..1bb879959a20 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -1375,6 +1375,166 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) | |||
| 1375 | #endif | 1375 | #endif |
| 1376 | 1376 | ||
| 1377 | /** | 1377 | /** |
| 1378 | * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count | ||
| 1379 | * @dev: PCI device to query | ||
| 1380 | * | ||
| 1381 | * Returns mmrbc: maximum designed memory read count in bytes | ||
| 1382 | * or appropriate error value. | ||
| 1383 | */ | ||
| 1384 | int pcix_get_max_mmrbc(struct pci_dev *dev) | ||
| 1385 | { | ||
| 1386 | int ret, err, cap; | ||
| 1387 | u32 stat; | ||
| 1388 | |||
| 1389 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | ||
| 1390 | if (!cap) | ||
| 1391 | return -EINVAL; | ||
| 1392 | |||
| 1393 | err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat); | ||
| 1394 | if (err) | ||
| 1395 | return -EINVAL; | ||
| 1396 | |||
| 1397 | ret = (stat & PCI_X_STATUS_MAX_READ) >> 12; | ||
| 1398 | |||
| 1399 | return ret; | ||
| 1400 | } | ||
| 1401 | EXPORT_SYMBOL(pcix_get_max_mmrbc); | ||
| 1402 | |||
| 1403 | /** | ||
| 1404 | * pcix_get_mmrbc - get PCI-X maximum memory read byte count | ||
| 1405 | * @dev: PCI device to query | ||
| 1406 | * | ||
| 1407 | * Returns mmrbc: maximum memory read count in bytes | ||
| 1408 | * or appropriate error value. | ||
| 1409 | */ | ||
| 1410 | int pcix_get_mmrbc(struct pci_dev *dev) | ||
| 1411 | { | ||
| 1412 | int ret, cap; | ||
| 1413 | u32 cmd; | ||
| 1414 | |||
| 1415 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | ||
| 1416 | if (!cap) | ||
| 1417 | return -EINVAL; | ||
| 1418 | |||
| 1419 | ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); | ||
| 1420 | if (!ret) | ||
| 1421 | ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2); | ||
| 1422 | |||
| 1423 | return ret; | ||
| 1424 | } | ||
| 1425 | EXPORT_SYMBOL(pcix_get_mmrbc); | ||
| 1426 | |||
| 1427 | /** | ||
| 1428 | * pcix_set_mmrbc - set PCI-X maximum memory read byte count | ||
| 1429 | * @dev: PCI device to query | ||
| 1430 | * @mmrbc: maximum memory read count in bytes | ||
| 1431 | * valid values are 512, 1024, 2048, 4096 | ||
| 1432 | * | ||
| 1433 | * If possible sets maximum memory read byte count, some bridges have erratas | ||
| 1434 | * that prevent this. | ||
| 1435 | */ | ||
| 1436 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc) | ||
| 1437 | { | ||
| 1438 | int cap, err = -EINVAL; | ||
| 1439 | u32 stat, cmd, v, o; | ||
| 1440 | |||
| 1441 | if (mmrbc < 512 || mmrbc > 4096 || (mmrbc & (mmrbc-1))) | ||
| 1442 | goto out; | ||
| 1443 | |||
| 1444 | v = ffs(mmrbc) - 10; | ||
| 1445 | |||
| 1446 | cap = pci_find_capability(dev, PCI_CAP_ID_PCIX); | ||
| 1447 | if (!cap) | ||
| 1448 | goto out; | ||
| 1449 | |||
| 1450 | err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat); | ||
| 1451 | if (err) | ||
| 1452 | goto out; | ||
| 1453 | |||
| 1454 | if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21) | ||
| 1455 | return -E2BIG; | ||
| 1456 | |||
| 1457 | err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd); | ||
| 1458 | if (err) | ||
| 1459 | goto out; | ||
| 1460 | |||
| 1461 | o = (cmd & PCI_X_CMD_MAX_READ) >> 2; | ||
| 1462 | if (o != v) { | ||
| 1463 | if (v > o && dev->bus && | ||
| 1464 | (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC)) | ||
| 1465 | return -EIO; | ||
| 1466 | |||
| 1467 | cmd &= ~PCI_X_CMD_MAX_READ; | ||
| 1468 | cmd |= v << 2; | ||
| 1469 | err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd); | ||
| 1470 | } | ||
| 1471 | out: | ||
| 1472 | return err; | ||
| 1473 | } | ||
| 1474 | EXPORT_SYMBOL(pcix_set_mmrbc); | ||
| 1475 | |||
| 1476 | /** | ||
| 1477 | * pcie_get_readrq - get PCI Express read request size | ||
| 1478 | * @dev: PCI device to query | ||
| 1479 | * | ||
| 1480 | * Returns maximum memory read request in bytes | ||
| 1481 | * or appropriate error value. | ||
| 1482 | */ | ||
| 1483 | int pcie_get_readrq(struct pci_dev *dev) | ||
| 1484 | { | ||
| 1485 | int ret, cap; | ||
| 1486 | u16 ctl; | ||
| 1487 | |||
| 1488 | cap = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
| 1489 | if (!cap) | ||
| 1490 | return -EINVAL; | ||
| 1491 | |||
| 1492 | ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); | ||
| 1493 | if (!ret) | ||
| 1494 | ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12); | ||
| 1495 | |||
| 1496 | return ret; | ||
| 1497 | } | ||
| 1498 | EXPORT_SYMBOL(pcie_get_readrq); | ||
| 1499 | |||
| 1500 | /** | ||
| 1501 | * pcie_set_readrq - set PCI Express maximum memory read request | ||
| 1502 | * @dev: PCI device to query | ||
| 1503 | * @count: maximum memory read count in bytes | ||
| 1504 | * valid values are 128, 256, 512, 1024, 2048, 4096 | ||
| 1505 | * | ||
| 1506 | * If possible sets maximum read byte count | ||
| 1507 | */ | ||
| 1508 | int pcie_set_readrq(struct pci_dev *dev, int rq) | ||
| 1509 | { | ||
| 1510 | int cap, err = -EINVAL; | ||
| 1511 | u16 ctl, v; | ||
| 1512 | |||
| 1513 | if (rq < 128 || rq > 4096 || (rq & (rq-1))) | ||
| 1514 | goto out; | ||
| 1515 | |||
| 1516 | v = (ffs(rq) - 8) << 12; | ||
| 1517 | |||
| 1518 | cap = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
| 1519 | if (!cap) | ||
| 1520 | goto out; | ||
| 1521 | |||
| 1522 | err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); | ||
| 1523 | if (err) | ||
| 1524 | goto out; | ||
| 1525 | |||
| 1526 | if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) { | ||
| 1527 | ctl &= ~PCI_EXP_DEVCTL_READRQ; | ||
| 1528 | ctl |= v; | ||
| 1529 | err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | out: | ||
| 1533 | return err; | ||
| 1534 | } | ||
| 1535 | EXPORT_SYMBOL(pcie_set_readrq); | ||
| 1536 | |||
| 1537 | /** | ||
| 1378 | * pci_select_bars - Make BAR mask from the type of resource | 1538 | * pci_select_bars - Make BAR mask from the type of resource |
| 1379 | * @dev: the PCI device for which BAR mask is made | 1539 | * @dev: the PCI device for which BAR mask is made |
| 1380 | * @flags: resource type mask to be selected | 1540 | * @flags: resource type mask to be selected |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 01d8f8a8843c..75bd6a8648f6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -627,6 +627,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_ | |||
| 627 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); | 627 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic); |
| 628 | #endif /* CONFIG_X86_IO_APIC */ | 628 | #endif /* CONFIG_X86_IO_APIC */ |
| 629 | 629 | ||
| 630 | /* | ||
| 631 | * Some settings of MMRBC can lead to data corruption so block changes. | ||
| 632 | * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide | ||
| 633 | */ | ||
| 634 | static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev) | ||
| 635 | { | ||
| 636 | unsigned char revid; | ||
| 637 | |||
| 638 | pci_read_config_byte(dev, PCI_REVISION_ID, &revid); | ||
| 639 | if (dev->subordinate && revid <= 0x12) { | ||
| 640 | printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X MMRBC\n", | ||
| 641 | revid); | ||
| 642 | dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC; | ||
| 643 | } | ||
| 644 | } | ||
| 645 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_mmrbc); | ||
| 630 | 646 | ||
| 631 | /* | 647 | /* |
| 632 | * FIXME: it is questionable that quirk_via_acpi | 648 | * FIXME: it is questionable that quirk_via_acpi |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 086a0e5a6318..ac403d74a222 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -111,7 +111,8 @@ enum pcie_reset_state { | |||
| 111 | 111 | ||
| 112 | typedef unsigned short __bitwise pci_bus_flags_t; | 112 | typedef unsigned short __bitwise pci_bus_flags_t; |
| 113 | enum pci_bus_flags { | 113 | enum pci_bus_flags { |
| 114 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, | 114 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, |
| 115 | PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, | ||
| 115 | }; | 116 | }; |
| 116 | 117 | ||
| 117 | struct pci_cap_saved_state { | 118 | struct pci_cap_saved_state { |
| @@ -549,6 +550,10 @@ void pci_intx(struct pci_dev *dev, int enable); | |||
| 549 | void pci_msi_off(struct pci_dev *dev); | 550 | void pci_msi_off(struct pci_dev *dev); |
| 550 | int pci_set_dma_mask(struct pci_dev *dev, u64 mask); | 551 | int pci_set_dma_mask(struct pci_dev *dev, u64 mask); |
| 551 | int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); | 552 | int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); |
| 553 | int pcix_get_max_mmrbc(struct pci_dev *dev); | ||
| 554 | int pcix_get_mmrbc(struct pci_dev *dev); | ||
| 555 | int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc); | ||
| 556 | int pcie_set_readrq(struct pci_dev *dev, int rq); | ||
| 552 | void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); | 557 | void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); |
| 553 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); | 558 | int __must_check pci_assign_resource(struct pci_dev *dev, int i); |
| 554 | int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); | 559 | int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i); |
