diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2013-06-27 18:40:00 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-07-25 14:27:03 -0400 |
commit | 15b100dfd1c9f7558d2fba4e3d13591dab50667f (patch) | |
tree | f6fd4d2c6f37e48649cb606014c758332537d392 /drivers/pci/quirks.c | |
parent | 83db7e0bdb70a9bb93cd000fefc3fbac3394f516 (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.c | 50 |
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 | */ | ||
3318 | static 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 | |||
3298 | static const struct pci_dev_acs_enabled { | 3342 | static 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 | ||