diff options
Diffstat (limited to 'arch/x86/kernel/amd_iommu_init.c')
| -rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 24 | 
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index b4b61d462dc..c20001e4f55 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -240,7 +240,7 @@ static void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)  	writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);  } -static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit) +static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)  {  	u32 ctrl; @@ -519,6 +519,26 @@ 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)  { @@ -547,6 +567,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);  }  |