aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-06-27 18:40:00 -0400
committerBjorn Helgaas <bhelgaas@google.com>2013-07-25 14:27:03 -0400
commit15b100dfd1c9f7558d2fba4e3d13591dab50667f (patch)
treef6fd4d2c6f37e48649cb606014c758332537d392 /drivers/pci/quirks.c
parent83db7e0bdb70a9bb93cd000fefc3fbac3394f516 (diff)
PCI: Claim ACS support for AMD southbridge devices
AMD confirmed that peer-to-peer between these devices is not possible. We can therefore claim that they support a subset of ACS. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Donald Dutile <ddutile@redhat.com>
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e85d23044ae0..2e2ea2208f2e 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3295,11 +3295,61 @@ struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
3295 return pci_dev_get(dev); 3295 return pci_dev_get(dev);
3296} 3296}
3297 3297
3298/*
3299 * AMD has indicated that the devices below do not support peer-to-peer
3300 * in any system where they are found in the southbridge with an AMD
3301 * IOMMU in the system. Multifunction devices that do not support
3302 * peer-to-peer between functions can claim to support a subset of ACS.
3303 * Such devices effectively enable request redirect (RR) and completion
3304 * redirect (CR) since all transactions are redirected to the upstream
3305 * root complex.
3306 *
3307 * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94086
3308 * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94102
3309 * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/99402
3310 *
3311 * 1002:4385 SBx00 SMBus Controller
3312 * 1002:439c SB7x0/SB8x0/SB9x0 IDE Controller
3313 * 1002:4383 SBx00 Azalia (Intel HDA)
3314 * 1002:439d SB7x0/SB8x0/SB9x0 LPC host controller
3315 * 1002:4384 SBx00 PCI to PCI Bridge
3316 * 1002:4399 SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
3317 */
3318static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
3319{
3320#ifdef CONFIG_ACPI
3321 struct acpi_table_header *header = NULL;
3322 acpi_status status;
3323
3324 /* Targeting multifunction devices on the SB (appears on root bus) */
3325 if (!dev->multifunction || !pci_is_root_bus(dev->bus))
3326 return -ENODEV;
3327
3328 /* The IVRS table describes the AMD IOMMU */
3329 status = acpi_get_table("IVRS", 0, &header);
3330 if (ACPI_FAILURE(status))
3331 return -ENODEV;
3332
3333 /* Filter out flags not applicable to multifunction */
3334 acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT);
3335
3336 return acs_flags & ~(PCI_ACS_RR | PCI_ACS_CR) ? 0 : 1;
3337#else
3338 return -ENODEV;
3339#endif
3340}
3341
3298static const struct pci_dev_acs_enabled { 3342static const struct pci_dev_acs_enabled {
3299 u16 vendor; 3343 u16 vendor;
3300 u16 device; 3344 u16 device;
3301 int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags); 3345 int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags);
3302} pci_dev_acs_enabled[] = { 3346} pci_dev_acs_enabled[] = {
3347 { PCI_VENDOR_ID_ATI, 0x4385, pci_quirk_amd_sb_acs },
3348 { PCI_VENDOR_ID_ATI, 0x439c, pci_quirk_amd_sb_acs },
3349 { PCI_VENDOR_ID_ATI, 0x4383, pci_quirk_amd_sb_acs },
3350 { PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },
3351 { PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },
3352 { PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs },
3303 { 0 } 3353 { 0 }
3304}; 3354};
3305 3355