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>
This commit is contained in:
parent
83db7e0bdb
commit
15b100dfd1
1 changed files with 50 additions and 0 deletions
|
@ -3295,11 +3295,61 @@ struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
|
|||
return pci_dev_get(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* AMD has indicated that the devices below do not support peer-to-peer
|
||||
* in any system where they are found in the southbridge with an AMD
|
||||
* IOMMU in the system. Multifunction devices that do not support
|
||||
* peer-to-peer between functions can claim to support a subset of ACS.
|
||||
* Such devices effectively enable request redirect (RR) and completion
|
||||
* redirect (CR) since all transactions are redirected to the upstream
|
||||
* root complex.
|
||||
*
|
||||
* http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94086
|
||||
* http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94102
|
||||
* http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/99402
|
||||
*
|
||||
* 1002:4385 SBx00 SMBus Controller
|
||||
* 1002:439c SB7x0/SB8x0/SB9x0 IDE Controller
|
||||
* 1002:4383 SBx00 Azalia (Intel HDA)
|
||||
* 1002:439d SB7x0/SB8x0/SB9x0 LPC host controller
|
||||
* 1002:4384 SBx00 PCI to PCI Bridge
|
||||
* 1002:4399 SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
|
||||
*/
|
||||
static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
struct acpi_table_header *header = NULL;
|
||||
acpi_status status;
|
||||
|
||||
/* Targeting multifunction devices on the SB (appears on root bus) */
|
||||
if (!dev->multifunction || !pci_is_root_bus(dev->bus))
|
||||
return -ENODEV;
|
||||
|
||||
/* The IVRS table describes the AMD IOMMU */
|
||||
status = acpi_get_table("IVRS", 0, &header);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
/* Filter out flags not applicable to multifunction */
|
||||
acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT);
|
||||
|
||||
return acs_flags & ~(PCI_ACS_RR | PCI_ACS_CR) ? 0 : 1;
|
||||
#else
|
||||
return -ENODEV;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct pci_dev_acs_enabled {
|
||||
u16 vendor;
|
||||
u16 device;
|
||||
int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags);
|
||||
} pci_dev_acs_enabled[] = {
|
||||
{ PCI_VENDOR_ID_ATI, 0x4385, pci_quirk_amd_sb_acs },
|
||||
{ PCI_VENDOR_ID_ATI, 0x439c, pci_quirk_amd_sb_acs },
|
||||
{ PCI_VENDOR_ID_ATI, 0x4383, pci_quirk_amd_sb_acs },
|
||||
{ PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },
|
||||
{ PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },
|
||||
{ PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue