diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-28 14:52:56 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-28 14:52:56 -0500 |
| commit | ae2c3d95faa4f75005f52051734464d4e8991612 (patch) | |
| tree | bdfaaf82527a23753db2ab5ce43c1b20aa5e568f | |
| parent | 325a86b65c01408dc77690fac1a7a45c844a613b (diff) | |
| parent | 318fe782539c4150d1b8e4e6c9dc3a896512cb8a (diff) | |
Merge tag 'iommu-fixes-v3.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU fix from Joerg Roedel:
"One fix for the AMD IOMMU driver to work around broken BIOSes found in
the field. Some BIOSes forget to enable a workaround for a hardware
problem which might cause the IOMMU to stop working under high load
conditions. The fix makes sure this workaround is enabled."
* tag 'iommu-fixes-v3.8-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
IOMMU, AMD Family15h Model10-1Fh erratum 746 Workaround
| -rw-r--r-- | drivers/iommu/amd_iommu_init.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 81837b0710a9..faf10ba1ed9a 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) | |||
| 975 | } | 975 | } |
| 976 | 976 | ||
| 977 | /* | 977 | /* |
| 978 | * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations) | ||
| 979 | * Workaround: | ||
| 980 | * BIOS should disable L2B micellaneous clock gating by setting | ||
| 981 | * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b | ||
| 982 | */ | ||
| 983 | static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) | ||
| 984 | { | ||
| 985 | u32 value; | ||
| 986 | |||
| 987 | if ((boot_cpu_data.x86 != 0x15) || | ||
| 988 | (boot_cpu_data.x86_model < 0x10) || | ||
| 989 | (boot_cpu_data.x86_model > 0x1f)) | ||
| 990 | return; | ||
| 991 | |||
| 992 | pci_write_config_dword(iommu->dev, 0xf0, 0x90); | ||
| 993 | pci_read_config_dword(iommu->dev, 0xf4, &value); | ||
| 994 | |||
| 995 | if (value & BIT(2)) | ||
| 996 | return; | ||
| 997 | |||
| 998 | /* Select NB indirect register 0x90 and enable writing */ | ||
| 999 | pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); | ||
| 1000 | |||
| 1001 | pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); | ||
| 1002 | pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n", | ||
| 1003 | dev_name(&iommu->dev->dev)); | ||
| 1004 | |||
| 1005 | /* Clear the enable writing bit */ | ||
| 1006 | pci_write_config_dword(iommu->dev, 0xf0, 0x90); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | /* | ||
| 978 | * This function clues the initialization function for one IOMMU | 1010 | * This function clues the initialization function for one IOMMU |
| 979 | * together and also allocates the command buffer and programs the | 1011 | * together and also allocates the command buffer and programs the |
| 980 | * hardware. It does NOT enable the IOMMU. This is done afterwards. | 1012 | * hardware. It does NOT enable the IOMMU. This is done afterwards. |
| @@ -1172,6 +1204,8 @@ static int iommu_init_pci(struct amd_iommu *iommu) | |||
| 1172 | iommu->stored_l2[i] = iommu_read_l2(iommu, i); | 1204 | iommu->stored_l2[i] = iommu_read_l2(iommu, i); |
| 1173 | } | 1205 | } |
| 1174 | 1206 | ||
| 1207 | amd_iommu_erratum_746_workaround(iommu); | ||
| 1208 | |||
| 1175 | return pci_enable_device(iommu->dev); | 1209 | return pci_enable_device(iommu->dev); |
| 1176 | } | 1210 | } |
| 1177 | 1211 | ||
