diff options
-rw-r--r-- | drivers/pci/intel-iommu.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1880ee06d701..9ce79b1bae83 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -2647,15 +2647,24 @@ static void flush_unmaps(void) | |||
2647 | if (!deferred_flush[i].next) | 2647 | if (!deferred_flush[i].next) |
2648 | continue; | 2648 | continue; |
2649 | 2649 | ||
2650 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, | 2650 | /* In caching mode, global flushes turn emulation expensive */ |
2651 | if (!cap_caching_mode(iommu->cap)) | ||
2652 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, | ||
2651 | DMA_TLB_GLOBAL_FLUSH); | 2653 | DMA_TLB_GLOBAL_FLUSH); |
2652 | for (j = 0; j < deferred_flush[i].next; j++) { | 2654 | for (j = 0; j < deferred_flush[i].next; j++) { |
2653 | unsigned long mask; | 2655 | unsigned long mask; |
2654 | struct iova *iova = deferred_flush[i].iova[j]; | 2656 | struct iova *iova = deferred_flush[i].iova[j]; |
2655 | 2657 | struct dmar_domain *domain = deferred_flush[i].domain[j]; | |
2656 | mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1)); | 2658 | |
2657 | iommu_flush_dev_iotlb(deferred_flush[i].domain[j], | 2659 | /* On real hardware multiple invalidations are expensive */ |
2658 | (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); | 2660 | if (cap_caching_mode(iommu->cap)) |
2661 | iommu_flush_iotlb_psi(iommu, domain->id, | ||
2662 | iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1, 0); | ||
2663 | else { | ||
2664 | mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1)); | ||
2665 | iommu_flush_dev_iotlb(deferred_flush[i].domain[j], | ||
2666 | (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); | ||
2667 | } | ||
2659 | __free_iova(&deferred_flush[i].domain[j]->iovad, iova); | 2668 | __free_iova(&deferred_flush[i].domain[j]->iovad, iova); |
2660 | } | 2669 | } |
2661 | deferred_flush[i].next = 0; | 2670 | deferred_flush[i].next = 0; |