aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2014-02-03 16:27:46 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-02-11 15:52:19 -0500
commitd99321b63b1f2cd386cdf20aefe4d8d3d414cb5b (patch)
treea318f81753df96ace991c620ef69ff6e546c0d05
parent5757a769ea4e094df6ec92d9ce7d05a90d5bf3e6 (diff)
PCI: Enable quirks for PCIe ACS on Intel PCH root ports
Many of the currently available Intel PCH-based root ports do not provide PCIe ACS capabilities. Without this, we must assume that peer-to-peer traffic between multifunction root ports and between devices behind root ports is possible. This lack of isolation is exposed by grouping the devices together in the same IOMMU group. If we want to expose these devices to userspace, vfio uses IOMMU groups as the unit of ownership, thus making it very difficult to assign individual devices to separate users. The good news is that the chipset does provide ACS-like isolation capabilities, but we do need to verify and enable those capabilities if the BIOS has not done so. This patch implements the device specific enabling and testing of equivalent ACS function for these devices. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Don Dugger <donald.d.dugger@intel.com>
-rw-r--r--drivers/pci/quirks.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index f681fb08f5e4..ed2ed867c34c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3423,6 +3423,61 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
3423#endif 3423#endif
3424} 3424}
3425 3425
3426/*
3427 * Many Intel PCH root ports do provide ACS-like features to disable peer
3428 * transactions and validate bus numbers in requests, but do not provide an
3429 * actual PCIe ACS capability. This is the list of device IDs known to fall
3430 * into that category as provided by Intel in Red Hat bugzilla 1037684.
3431 */
3432static const u16 pci_quirk_intel_pch_acs_ids[] = {
3433 /* Ibexpeak PCH */
3434 0x3b42, 0x3b43, 0x3b44, 0x3b45, 0x3b46, 0x3b47, 0x3b48, 0x3b49,
3435 0x3b4a, 0x3b4b, 0x3b4c, 0x3b4d, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51,
3436 /* Cougarpoint PCH */
3437 0x1c10, 0x1c11, 0x1c12, 0x1c13, 0x1c14, 0x1c15, 0x1c16, 0x1c17,
3438 0x1c18, 0x1c19, 0x1c1a, 0x1c1b, 0x1c1c, 0x1c1d, 0x1c1e, 0x1c1f,
3439 /* Pantherpoint PCH */
3440 0x1e10, 0x1e11, 0x1e12, 0x1e13, 0x1e14, 0x1e15, 0x1e16, 0x1e17,
3441 0x1e18, 0x1e19, 0x1e1a, 0x1e1b, 0x1e1c, 0x1e1d, 0x1e1e, 0x1e1f,
3442 /* Lynxpoint-H PCH */
3443 0x8c10, 0x8c11, 0x8c12, 0x8c13, 0x8c14, 0x8c15, 0x8c16, 0x8c17,
3444 0x8c18, 0x8c19, 0x8c1a, 0x8c1b, 0x8c1c, 0x8c1d, 0x8c1e, 0x8c1f,
3445 /* Lynxpoint-LP PCH */
3446 0x9c10, 0x9c11, 0x9c12, 0x9c13, 0x9c14, 0x9c15, 0x9c16, 0x9c17,
3447 0x9c18, 0x9c19, 0x9c1a, 0x9c1b,
3448 /* Wildcat PCH */
3449 0x9c90, 0x9c91, 0x9c92, 0x9c93, 0x9c94, 0x9c95, 0x9c96, 0x9c97,
3450 0x9c98, 0x9c99, 0x9c9a, 0x9c9b,
3451};
3452
3453static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
3454{
3455 int i;
3456
3457 /* Filter out a few obvious non-matches first */
3458 if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
3459 return false;
3460
3461 for (i = 0; i < ARRAY_SIZE(pci_quirk_intel_pch_acs_ids); i++)
3462 if (pci_quirk_intel_pch_acs_ids[i] == dev->device)
3463 return true;
3464
3465 return false;
3466}
3467
3468#define INTEL_PCH_ACS_FLAGS (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV)
3469
3470static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
3471{
3472 u16 flags = dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK ?
3473 INTEL_PCH_ACS_FLAGS : 0;
3474
3475 if (!pci_quirk_intel_pch_acs_match(dev))
3476 return -ENOTTY;
3477
3478 return acs_flags & ~flags ? 0 : 1;
3479}
3480
3426static const struct pci_dev_acs_enabled { 3481static const struct pci_dev_acs_enabled {
3427 u16 vendor; 3482 u16 vendor;
3428 u16 device; 3483 u16 device;
@@ -3434,6 +3489,7 @@ static const struct pci_dev_acs_enabled {
3434 { PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs }, 3489 { PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },
3435 { PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs }, 3490 { PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },
3436 { PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs }, 3491 { PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs },
3492 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
3437 { 0 } 3493 { 0 }
3438}; 3494};
3439 3495
@@ -3462,11 +3518,115 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
3462 return -ENOTTY; 3518 return -ENOTTY;
3463} 3519}
3464 3520
3521/* Config space offset of Root Complex Base Address register */
3522#define INTEL_LPC_RCBA_REG 0xf0
3523/* 31:14 RCBA address */
3524#define INTEL_LPC_RCBA_MASK 0xffffc000
3525/* RCBA Enable */
3526#define INTEL_LPC_RCBA_ENABLE (1 << 0)
3527
3528/* Backbone Scratch Pad Register */
3529#define INTEL_BSPR_REG 0x1104
3530/* Backbone Peer Non-Posted Disable */
3531#define INTEL_BSPR_REG_BPNPD (1 << 8)
3532/* Backbone Peer Posted Disable */
3533#define INTEL_BSPR_REG_BPPD (1 << 9)
3534
3535/* Upstream Peer Decode Configuration Register */
3536#define INTEL_UPDCR_REG 0x1114
3537/* 5:0 Peer Decode Enable bits */
3538#define INTEL_UPDCR_REG_MASK 0x3f
3539
3540static int pci_quirk_enable_intel_lpc_acs(struct pci_dev *dev)
3541{
3542 u32 rcba, bspr, updcr;
3543 void __iomem *rcba_mem;
3544
3545 /*
3546 * Read the RCBA register from the LPC (D31:F0). PCH root ports
3547 * are D28:F* and therefore get probed before LPC, thus we can't
3548 * use pci_get_slot/pci_read_config_dword here.
3549 */
3550 pci_bus_read_config_dword(dev->bus, PCI_DEVFN(31, 0),
3551 INTEL_LPC_RCBA_REG, &rcba);
3552 if (!(rcba & INTEL_LPC_RCBA_ENABLE))
3553 return -EINVAL;
3554
3555 rcba_mem = ioremap_nocache(rcba & INTEL_LPC_RCBA_MASK,
3556 PAGE_ALIGN(INTEL_UPDCR_REG));
3557 if (!rcba_mem)
3558 return -ENOMEM;
3559
3560 /*
3561 * The BSPR can disallow peer cycles, but it's set by soft strap and
3562 * therefore read-only. If both posted and non-posted peer cycles are
3563 * disallowed, we're ok. If either are allowed, then we need to use
3564 * the UPDCR to disable peer decodes for each port. This provides the
3565 * PCIe ACS equivalent of PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF
3566 */
3567 bspr = readl(rcba_mem + INTEL_BSPR_REG);
3568 bspr &= INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD;
3569 if (bspr != (INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD)) {
3570 updcr = readl(rcba_mem + INTEL_UPDCR_REG);
3571 if (updcr & INTEL_UPDCR_REG_MASK) {
3572 dev_info(&dev->dev, "Disabling UPDCR peer decodes\n");
3573 updcr &= ~INTEL_UPDCR_REG_MASK;
3574 writel(updcr, rcba_mem + INTEL_UPDCR_REG);
3575 }
3576 }
3577
3578 iounmap(rcba_mem);
3579 return 0;
3580}
3581
3582/* Miscellaneous Port Configuration register */
3583#define INTEL_MPC_REG 0xd8
3584/* MPC: Invalid Receive Bus Number Check Enable */
3585#define INTEL_MPC_REG_IRBNCE (1 << 26)
3586
3587static void pci_quirk_enable_intel_rp_mpc_acs(struct pci_dev *dev)
3588{
3589 u32 mpc;
3590
3591 /*
3592 * When enabled, the IRBNCE bit of the MPC register enables the
3593 * equivalent of PCI ACS Source Validation (PCI_ACS_SV), which
3594 * ensures that requester IDs fall within the bus number range
3595 * of the bridge. Enable if not already.
3596 */
3597 pci_read_config_dword(dev, INTEL_MPC_REG, &mpc);
3598 if (!(mpc & INTEL_MPC_REG_IRBNCE)) {
3599 dev_info(&dev->dev, "Enabling MPC IRBNCE\n");
3600 mpc |= INTEL_MPC_REG_IRBNCE;
3601 pci_write_config_word(dev, INTEL_MPC_REG, mpc);
3602 }
3603}
3604
3605static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev)
3606{
3607 if (!pci_quirk_intel_pch_acs_match(dev))
3608 return -ENOTTY;
3609
3610 if (pci_quirk_enable_intel_lpc_acs(dev)) {
3611 dev_warn(&dev->dev, "Failed to enable Intel PCH ACS quirk\n");
3612 return 0;
3613 }
3614
3615 pci_quirk_enable_intel_rp_mpc_acs(dev);
3616
3617 dev->dev_flags |= PCI_DEV_FLAGS_ACS_ENABLED_QUIRK;
3618
3619 dev_info(&dev->dev, "Intel PCH root port ACS workaround enabled\n");
3620
3621 return 0;
3622}
3623
3465static const struct pci_dev_enable_acs { 3624static const struct pci_dev_enable_acs {
3466 u16 vendor; 3625 u16 vendor;
3467 u16 device; 3626 u16 device;
3468 int (*enable_acs)(struct pci_dev *dev); 3627 int (*enable_acs)(struct pci_dev *dev);
3469} pci_dev_enable_acs[] = { 3628} pci_dev_enable_acs[] = {
3629 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs },
3470 { 0 } 3630 { 0 }
3471}; 3631};
3472 3632