x86/amd-iommu: Workaround for erratum 63
authorJoerg Roedel <joerg.roedel@amd.com>
Fri, 6 Nov 2009 10:50:26 +0000 (11:50 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 10 Nov 2009 00:52:48 +0000 (16:52 -0800)
commit c5cca146aa03e1f60fb179df65f0dbaf17bc64ed upstream.

There is an erratum for IOMMU hardware which documents
undefined behavior when forwarding SMI requests from
peripherals and the DTE of that peripheral has a sysmgt
value of 01b. This problem caused weird IO_PAGE_FAULTS in my
case.
This patch implements the suggested workaround for that
erratum into the AMD IOMMU driver.  The erratum is
documented with number 63.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
arch/x86/kernel/amd_iommu_init.c

index 3b06a9c..7d58f32 100644 (file)
@@ -430,6 +430,27 @@ static void set_dev_entry_bit(u16 devid, u8 bit)
        amd_iommu_dev_table[devid].data[i] |= (1 << _bit);
 }
 
+static int get_dev_entry_bit(u16 devid, u8 bit)
+{
+       int i = (bit >> 5) & 0x07;
+       int _bit = bit & 0x1f;
+
+       return (amd_iommu_dev_table[devid].data[i] & (1 << _bit)) >> _bit;
+}
+
+
+void amd_iommu_apply_erratum_63(u16 devid)
+{
+       int sysmgt;
+
+       sysmgt = get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT1) |
+               (get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT2) << 1);
+
+       if (sysmgt == 0x01)
+               set_dev_entry_bit(devid, DEV_ENTRY_IW);
+}
+
+
 /* Writes the specific IOMMU for a device into the rlookup table */
 static void __init set_iommu_for_device(struct amd_iommu *iommu, u16 devid)
 {
@@ -458,6 +479,8 @@ static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
        if (flags & ACPI_DEVFLAG_LINT1)
                set_dev_entry_bit(devid, DEV_ENTRY_LINT1_PASS);
 
+       amd_iommu_apply_erratum_63(devid);
+
        set_iommu_for_device(iommu, devid);
 }