diff options
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 | ||