diff options
Diffstat (limited to 'drivers/iommu/amd_iommu_init.c')
| -rw-r--r-- | drivers/iommu/amd_iommu_init.c | 44 | 
1 files changed, 39 insertions, 5 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 81837b0710a9..b6ecddb63cd0 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -975,6 +975,38 @@ static void __init free_iommu_all(void)  }  /* + * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations) + * Workaround: + *     BIOS should disable L2B micellaneous clock gating by setting + *     L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b + */ +static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) +{ +	u32 value; + +	if ((boot_cpu_data.x86 != 0x15) || +	    (boot_cpu_data.x86_model < 0x10) || +	    (boot_cpu_data.x86_model > 0x1f)) +		return; + +	pci_write_config_dword(iommu->dev, 0xf0, 0x90); +	pci_read_config_dword(iommu->dev, 0xf4, &value); + +	if (value & BIT(2)) +		return; + +	/* Select NB indirect register 0x90 and enable writing */ +	pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); + +	pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); +	pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n", +		dev_name(&iommu->dev->dev)); + +	/* Clear the enable writing bit */ +	pci_write_config_dword(iommu->dev, 0xf0, 0x90); +} + +/*   * This function clues the initialization function for one IOMMU   * together and also allocates the command buffer and programs the   * hardware. It does NOT enable the IOMMU. This is done afterwards. @@ -1172,6 +1204,8 @@ static int iommu_init_pci(struct amd_iommu *iommu)  			iommu->stored_l2[i] = iommu_read_l2(iommu, i);  	} +	amd_iommu_erratum_746_workaround(iommu); +  	return pci_enable_device(iommu->dev);  } @@ -1842,11 +1876,6 @@ static int amd_iommu_init_dma(void)  	struct amd_iommu *iommu;  	int ret; -	init_device_table_dma(); - -	for_each_iommu(iommu) -		iommu_flush_all_caches(iommu); -  	if (iommu_pass_through)  		ret = amd_iommu_init_passthrough();  	else @@ -1855,6 +1884,11 @@ static int amd_iommu_init_dma(void)  	if (ret)  		return ret; +	init_device_table_dma(); + +	for_each_iommu(iommu) +		iommu_flush_all_caches(iommu); +  	amd_iommu_init_api();  	amd_iommu_init_notifier();  |