Commit 51d20e1096a711f8cfa9d98a3ac2dd2c7c0fc20c
Committed by
Greg Kroah-Hartman
1 parent
f10acdb935
Exists in
ti-linux-3.14.y
and in
2 other branches
iommu/vt-d: Fix missing IOTLB flush in intel_iommu_unmap()
Based on commit ea8ea460c9ace60bbb5ac6e5521d637d5c15293d upstream This missing IOTLB flush was added as a minor, inconsequential bug-fix in commit ea8ea460c ("iommu/vt-d: Clean up and fix page table clear/free behaviour") in 3.15. It wasn't originally intended for -stable but a couple of users have reported issues which turn out to be fixed by adding the missing flush. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Showing 1 changed file with 17 additions and 1 deletions Side-by-side Diff
drivers/iommu/intel-iommu.c
... | ... | @@ -4075,13 +4075,29 @@ |
4075 | 4075 | unsigned long iova, size_t size) |
4076 | 4076 | { |
4077 | 4077 | struct dmar_domain *dmar_domain = domain->priv; |
4078 | - int order; | |
4078 | + int order, iommu_id; | |
4079 | 4079 | |
4080 | 4080 | order = dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
4081 | 4081 | (iova + size - 1) >> VTD_PAGE_SHIFT); |
4082 | 4082 | |
4083 | 4083 | if (dmar_domain->max_addr == iova + size) |
4084 | 4084 | dmar_domain->max_addr = iova; |
4085 | + | |
4086 | + for_each_set_bit(iommu_id, dmar_domain->iommu_bmp, g_num_of_iommus) { | |
4087 | + struct intel_iommu *iommu = g_iommus[iommu_id]; | |
4088 | + int num, ndomains; | |
4089 | + | |
4090 | + /* | |
4091 | + * find bit position of dmar_domain | |
4092 | + */ | |
4093 | + ndomains = cap_ndoms(iommu->cap); | |
4094 | + for_each_set_bit(num, iommu->domain_ids, ndomains) { | |
4095 | + if (iommu->domains[num] == dmar_domain) | |
4096 | + iommu_flush_iotlb_psi(iommu, num, | |
4097 | + iova >> VTD_PAGE_SHIFT, | |
4098 | + 1 << order, 0); | |
4099 | + } | |
4100 | + } | |
4085 | 4101 | |
4086 | 4102 | return PAGE_SIZE << order; |
4087 | 4103 | } |