diff options
Diffstat (limited to 'arch/x86/kernel/amd_iommu_init.c')
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 246d727b65b7..9179c21120a8 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -137,6 +137,7 @@ int amd_iommus_present; | |||
137 | 137 | ||
138 | /* IOMMUs have a non-present cache? */ | 138 | /* IOMMUs have a non-present cache? */ |
139 | bool amd_iommu_np_cache __read_mostly; | 139 | bool amd_iommu_np_cache __read_mostly; |
140 | bool amd_iommu_iotlb_sup __read_mostly = true; | ||
140 | 141 | ||
141 | /* | 142 | /* |
142 | * The ACPI table parsing functions set this variable on an error | 143 | * The ACPI table parsing functions set this variable on an error |
@@ -180,6 +181,12 @@ static u32 dev_table_size; /* size of the device table */ | |||
180 | static u32 alias_table_size; /* size of the alias table */ | 181 | static u32 alias_table_size; /* size of the alias table */ |
181 | static u32 rlookup_table_size; /* size if the rlookup table */ | 182 | static u32 rlookup_table_size; /* size if the rlookup table */ |
182 | 183 | ||
184 | /* | ||
185 | * This function flushes all internal caches of | ||
186 | * the IOMMU used by this driver. | ||
187 | */ | ||
188 | extern void iommu_flush_all_caches(struct amd_iommu *iommu); | ||
189 | |||
183 | static inline void update_last_devid(u16 devid) | 190 | static inline void update_last_devid(u16 devid) |
184 | { | 191 | { |
185 | if (devid > amd_iommu_last_bdf) | 192 | if (devid > amd_iommu_last_bdf) |
@@ -293,9 +300,23 @@ static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit) | |||
293 | /* Function to enable the hardware */ | 300 | /* Function to enable the hardware */ |
294 | static void iommu_enable(struct amd_iommu *iommu) | 301 | static void iommu_enable(struct amd_iommu *iommu) |
295 | { | 302 | { |
296 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx\n", | 303 | static const char * const feat_str[] = { |
304 | "PreF", "PPR", "X2APIC", "NX", "GT", "[5]", | ||
305 | "IA", "GA", "HE", "PC", NULL | ||
306 | }; | ||
307 | int i; | ||
308 | |||
309 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx", | ||
297 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | 310 | dev_name(&iommu->dev->dev), iommu->cap_ptr); |
298 | 311 | ||
312 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { | ||
313 | printk(KERN_CONT " extended features: "); | ||
314 | for (i = 0; feat_str[i]; ++i) | ||
315 | if (iommu_feature(iommu, (1ULL << i))) | ||
316 | printk(KERN_CONT " %s", feat_str[i]); | ||
317 | } | ||
318 | printk(KERN_CONT "\n"); | ||
319 | |||
299 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); | 320 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); |
300 | } | 321 | } |
301 | 322 | ||
@@ -651,7 +672,7 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) | |||
651 | static void __init init_iommu_from_pci(struct amd_iommu *iommu) | 672 | static void __init init_iommu_from_pci(struct amd_iommu *iommu) |
652 | { | 673 | { |
653 | int cap_ptr = iommu->cap_ptr; | 674 | int cap_ptr = iommu->cap_ptr; |
654 | u32 range, misc; | 675 | u32 range, misc, low, high; |
655 | int i, j; | 676 | int i, j; |
656 | 677 | ||
657 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, | 678 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, |
@@ -667,6 +688,15 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu) | |||
667 | MMIO_GET_LD(range)); | 688 | MMIO_GET_LD(range)); |
668 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); | 689 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); |
669 | 690 | ||
691 | if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB))) | ||
692 | amd_iommu_iotlb_sup = false; | ||
693 | |||
694 | /* read extended feature bits */ | ||
695 | low = readl(iommu->mmio_base + MMIO_EXT_FEATURES); | ||
696 | high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4); | ||
697 | |||
698 | iommu->features = ((u64)high << 32) | low; | ||
699 | |||
670 | if (!is_rd890_iommu(iommu->dev)) | 700 | if (!is_rd890_iommu(iommu->dev)) |
671 | return; | 701 | return; |
672 | 702 | ||
@@ -1004,10 +1034,11 @@ static int iommu_setup_msi(struct amd_iommu *iommu) | |||
1004 | if (pci_enable_msi(iommu->dev)) | 1034 | if (pci_enable_msi(iommu->dev)) |
1005 | return 1; | 1035 | return 1; |
1006 | 1036 | ||
1007 | r = request_irq(iommu->dev->irq, amd_iommu_int_handler, | 1037 | r = request_threaded_irq(iommu->dev->irq, |
1008 | IRQF_SAMPLE_RANDOM, | 1038 | amd_iommu_int_handler, |
1009 | "AMD-Vi", | 1039 | amd_iommu_int_thread, |
1010 | NULL); | 1040 | 0, "AMD-Vi", |
1041 | iommu->dev); | ||
1011 | 1042 | ||
1012 | if (r) { | 1043 | if (r) { |
1013 | pci_disable_msi(iommu->dev); | 1044 | pci_disable_msi(iommu->dev); |
@@ -1244,6 +1275,7 @@ static void enable_iommus(void) | |||
1244 | iommu_set_exclusion_range(iommu); | 1275 | iommu_set_exclusion_range(iommu); |
1245 | iommu_init_msi(iommu); | 1276 | iommu_init_msi(iommu); |
1246 | iommu_enable(iommu); | 1277 | iommu_enable(iommu); |
1278 | iommu_flush_all_caches(iommu); | ||
1247 | } | 1279 | } |
1248 | } | 1280 | } |
1249 | 1281 | ||
@@ -1274,8 +1306,8 @@ static void amd_iommu_resume(void) | |||
1274 | * we have to flush after the IOMMUs are enabled because a | 1306 | * we have to flush after the IOMMUs are enabled because a |
1275 | * disabled IOMMU will never execute the commands we send | 1307 | * disabled IOMMU will never execute the commands we send |
1276 | */ | 1308 | */ |
1277 | amd_iommu_flush_all_devices(); | 1309 | for_each_iommu(iommu) |
1278 | amd_iommu_flush_all_domains(); | 1310 | iommu_flush_all_caches(iommu); |
1279 | } | 1311 | } |
1280 | 1312 | ||
1281 | static int amd_iommu_suspend(void) | 1313 | static int amd_iommu_suspend(void) |