iommu/vt-d: Establish domain<->iommu link in dmar_insert_one_dev_info

This makes domain attachment more synchronous with domain
deattachment. The domain<->iommu link is released in
dmar_remove_one_dev_info.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Joerg Roedel 2015-07-22 13:11:53 +02:00
parent dc534b25d1
commit c6c2cebd66

View file

@ -1919,14 +1919,16 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
struct intel_iommu *iommu, struct intel_iommu *iommu,
u8 bus, u8 devfn) u8 bus, u8 devfn)
{ {
u16 did = domain->iommu_did[iommu->seq_id];
int translation = CONTEXT_TT_MULTI_LEVEL; int translation = CONTEXT_TT_MULTI_LEVEL;
struct device_domain_info *info = NULL; struct device_domain_info *info = NULL;
struct context_entry *context; struct context_entry *context;
unsigned long flags; unsigned long flags;
struct dma_pte *pgd; struct dma_pte *pgd;
int id;
int agaw; int agaw;
WARN_ON(did == 0);
if (hw_pass_through && domain_type_is_si(domain)) if (hw_pass_through && domain_type_is_si(domain))
translation = CONTEXT_TT_PASS_THROUGH; translation = CONTEXT_TT_PASS_THROUGH;
@ -1948,15 +1950,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
pgd = domain->pgd; pgd = domain->pgd;
id = __iommu_attach_domain(domain, iommu);
if (id < 0) {
spin_unlock_irqrestore(&iommu->lock, flags);
pr_err("%s: No free domain ids\n", iommu->name);
return -EFAULT;
}
context_clear_entry(context); context_clear_entry(context);
context_set_domain_id(context, id); context_set_domain_id(context, did);
/* /*
* Skip top levels of page tables for iommu which has less agaw * Skip top levels of page tables for iommu which has less agaw
@ -2002,15 +1997,13 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
(((u16)bus) << 8) | devfn, (((u16)bus) << 8) | devfn,
DMA_CCMD_MASK_NOBIT, DMA_CCMD_MASK_NOBIT,
DMA_CCMD_DEVICE_INVL); DMA_CCMD_DEVICE_INVL);
iommu->flush.flush_iotlb(iommu, id, 0, 0, DMA_TLB_DSI_FLUSH); iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
} else { } else {
iommu_flush_write_buffer(iommu); iommu_flush_write_buffer(iommu);
} }
iommu_enable_dev_iotlb(info); iommu_enable_dev_iotlb(info);
spin_unlock_irqrestore(&iommu->lock, flags); spin_unlock_irqrestore(&iommu->lock, flags);
domain_attach_iommu(domain, iommu);
return 0; return 0;
} }
@ -2320,6 +2313,12 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
return found; return found;
} }
if (iommu_attach_domain(domain, iommu) < 0) {
spin_unlock_irqrestore(&device_domain_lock, flags);
return NULL;
}
domain_attach_iommu(domain, iommu);
list_add(&info->link, &domain->devices); list_add(&info->link, &domain->devices);
list_add(&info->global, &device_domain_list); list_add(&info->global, &device_domain_list);
if (dev) if (dev)
@ -2383,11 +2382,6 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw)
domain = alloc_domain(0); domain = alloc_domain(0);
if (!domain) if (!domain)
return NULL; return NULL;
if (iommu_attach_domain(domain, iommu) < 0) {
free_domain_mem(domain);
return NULL;
}
domain_attach_iommu(domain, iommu);
if (domain_init(domain, iommu, gaw)) { if (domain_init(domain, iommu, gaw)) {
domain_exit(domain); domain_exit(domain);
return NULL; return NULL;