iommu/vt-d: Don't be too aggressive when clearing one context entry
Previously, we were invalidating context cache and IOTLB globally when clearing one context entry. This is a tad too aggressive. Invalidate the context cache and IOTLB for the interested device only. Signed-off-by: Filippo Sironi <sironi@amazon.de> Cc: David Woodhouse <dwmw@amazon.co.uk> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Joerg Roedel <joro@8bytes.org> Cc: Jacob Pan <jacob.jun.pan@linux.intel.com> Cc: iommu@lists.linux-foundation.org Cc: linux-kernel@vger.kernel.org Acked-by: David Woodhouse <dwmw@amazon.co.uk> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Родитель
11b93ebfa0
Коммит
5082219b6a
|
@ -974,20 +974,6 @@ static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
|
||||
{
|
||||
struct context_entry *context;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
context = iommu_context_addr(iommu, bus, devfn, 0);
|
||||
if (context) {
|
||||
context_clear_entry(context);
|
||||
__iommu_flush_cache(iommu, context, sizeof(*context));
|
||||
}
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
static void free_context_table(struct intel_iommu *iommu)
|
||||
{
|
||||
int i;
|
||||
|
@ -2361,13 +2347,33 @@ static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long i
|
|||
|
||||
static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct context_entry *context;
|
||||
u16 did_old;
|
||||
|
||||
if (!iommu)
|
||||
return;
|
||||
|
||||
clear_context_table(iommu, bus, devfn);
|
||||
iommu->flush.flush_context(iommu, 0, 0, 0,
|
||||
DMA_CCMD_GLOBAL_INVL);
|
||||
iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
context = iommu_context_addr(iommu, bus, devfn, 0);
|
||||
if (!context) {
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
return;
|
||||
}
|
||||
did_old = context_domain_id(context);
|
||||
context_clear_entry(context);
|
||||
__iommu_flush_cache(iommu, context, sizeof(*context));
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
iommu->flush.flush_context(iommu,
|
||||
did_old,
|
||||
(((u16)bus) << 8) | devfn,
|
||||
DMA_CCMD_MASK_NOBIT,
|
||||
DMA_CCMD_DEVICE_INVL);
|
||||
iommu->flush.flush_iotlb(iommu,
|
||||
did_old,
|
||||
0,
|
||||
0,
|
||||
DMA_TLB_DSI_FLUSH);
|
||||
}
|
||||
|
||||
static inline void unlink_domain_info(struct device_domain_info *info)
|
||||
|
|
Загрузка…
Ссылка в новой задаче