Skip to content

Commit

Permalink
intel-iommu: iommu init error path bug fixes
Browse files Browse the repository at this point in the history
The kcalloc() failure path in iommu_init_domains() calls
free_dmar_iommu(), which assumes that ->domains, ->domain_ids,
and ->lock have been properly initialized.

Add checks in free_[dmar]_iommu to not use ->domains,->domain_ids
if not alloced. Move the lock init to prior to the kcalloc()'s,
so it is valid in free_context_table() when free_dmar_iommu() invokes
it at the end.

Patch based on iommu-2.6,
commit 1320322

Signed-off-by: Donald Dutile <ddutile@redhat.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
Donald Dutile authored and David Woodhouse committed Aug 24, 2009
1 parent 071e137 commit 94a91b5
Showing 1 changed file with 18 additions and 17 deletions.
35 changes: 18 additions & 17 deletions drivers/pci/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,8 @@ static int iommu_init_domains(struct intel_iommu *iommu)
pr_debug("Number of Domains supportd <%ld>\n", ndomains);
nlongs = BITS_TO_LONGS(ndomains);

spin_lock_init(&iommu->lock);

/* TBD: there might be 64K domains,
* consider other allocation for future chip
*/
Expand All @@ -1170,12 +1172,9 @@ static int iommu_init_domains(struct intel_iommu *iommu)
GFP_KERNEL);
if (!iommu->domains) {
printk(KERN_ERR "Allocating domain array failed\n");
kfree(iommu->domain_ids);
return -ENOMEM;
}

spin_lock_init(&iommu->lock);

/*
* if Caching mode is set, then invalid translations are tagged
* with domainid 0. Hence we need to pre-allocate it.
Expand All @@ -1195,22 +1194,24 @@ void free_dmar_iommu(struct intel_iommu *iommu)
int i;
unsigned long flags;

i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
for (; i < cap_ndoms(iommu->cap); ) {
domain = iommu->domains[i];
clear_bit(i, iommu->domain_ids);
if ((iommu->domains) && (iommu->domain_ids)) {
i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
for (; i < cap_ndoms(iommu->cap); ) {
domain = iommu->domains[i];
clear_bit(i, iommu->domain_ids);

spin_lock_irqsave(&domain->iommu_lock, flags);
if (--domain->iommu_count == 0) {
if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
vm_domain_exit(domain);
else
domain_exit(domain);
}
spin_unlock_irqrestore(&domain->iommu_lock, flags);

spin_lock_irqsave(&domain->iommu_lock, flags);
if (--domain->iommu_count == 0) {
if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
vm_domain_exit(domain);
else
domain_exit(domain);
i = find_next_bit(iommu->domain_ids,
cap_ndoms(iommu->cap), i+1);
}
spin_unlock_irqrestore(&domain->iommu_lock, flags);

i = find_next_bit(iommu->domain_ids,
cap_ndoms(iommu->cap), i+1);
}

if (iommu->gcmd & DMA_GCMD_TE)
Expand Down

0 comments on commit 94a91b5

Please sign in to comment.