diff options
author | Donald Dutile <ddutile@redhat.com> | 2009-08-20 16:51:34 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-08-24 03:56:26 -0400 |
commit | 94a91b5051a77d8a71d4f11a3240f0d9c51b6cf2 (patch) | |
tree | 04d81ea79520cbd662024ee23cd3f834dd950ed0 /drivers/pci/intel-iommu.c | |
parent | 071e13746f9ebb259987c71ea77f11e7656769a2 (diff) |
intel-iommu: iommu init error path bug fixes
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 132032274a594ee9ffb6b9c9e2e9698149a09ea9
Signed-off-by: Donald Dutile <ddutile@redhat.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r-- | drivers/pci/intel-iommu.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index e67335ba24a3..beb5ccfd89bd 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1158,6 +1158,8 @@ static int iommu_init_domains(struct intel_iommu *iommu) | |||
1158 | pr_debug("Number of Domains supportd <%ld>\n", ndomains); | 1158 | pr_debug("Number of Domains supportd <%ld>\n", ndomains); |
1159 | nlongs = BITS_TO_LONGS(ndomains); | 1159 | nlongs = BITS_TO_LONGS(ndomains); |
1160 | 1160 | ||
1161 | spin_lock_init(&iommu->lock); | ||
1162 | |||
1161 | /* TBD: there might be 64K domains, | 1163 | /* TBD: there might be 64K domains, |
1162 | * consider other allocation for future chip | 1164 | * consider other allocation for future chip |
1163 | */ | 1165 | */ |
@@ -1170,12 +1172,9 @@ static int iommu_init_domains(struct intel_iommu *iommu) | |||
1170 | GFP_KERNEL); | 1172 | GFP_KERNEL); |
1171 | if (!iommu->domains) { | 1173 | if (!iommu->domains) { |
1172 | printk(KERN_ERR "Allocating domain array failed\n"); | 1174 | printk(KERN_ERR "Allocating domain array failed\n"); |
1173 | kfree(iommu->domain_ids); | ||
1174 | return -ENOMEM; | 1175 | return -ENOMEM; |
1175 | } | 1176 | } |
1176 | 1177 | ||
1177 | spin_lock_init(&iommu->lock); | ||
1178 | |||
1179 | /* | 1178 | /* |
1180 | * if Caching mode is set, then invalid translations are tagged | 1179 | * if Caching mode is set, then invalid translations are tagged |
1181 | * with domainid 0. Hence we need to pre-allocate it. | 1180 | * with domainid 0. Hence we need to pre-allocate it. |
@@ -1195,22 +1194,24 @@ void free_dmar_iommu(struct intel_iommu *iommu) | |||
1195 | int i; | 1194 | int i; |
1196 | unsigned long flags; | 1195 | unsigned long flags; |
1197 | 1196 | ||
1198 | i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); | 1197 | if ((iommu->domains) && (iommu->domain_ids)) { |
1199 | for (; i < cap_ndoms(iommu->cap); ) { | 1198 | i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); |
1200 | domain = iommu->domains[i]; | 1199 | for (; i < cap_ndoms(iommu->cap); ) { |
1201 | clear_bit(i, iommu->domain_ids); | 1200 | domain = iommu->domains[i]; |
1201 | clear_bit(i, iommu->domain_ids); | ||
1202 | |||
1203 | spin_lock_irqsave(&domain->iommu_lock, flags); | ||
1204 | if (--domain->iommu_count == 0) { | ||
1205 | if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) | ||
1206 | vm_domain_exit(domain); | ||
1207 | else | ||
1208 | domain_exit(domain); | ||
1209 | } | ||
1210 | spin_unlock_irqrestore(&domain->iommu_lock, flags); | ||
1202 | 1211 | ||
1203 | spin_lock_irqsave(&domain->iommu_lock, flags); | 1212 | i = find_next_bit(iommu->domain_ids, |
1204 | if (--domain->iommu_count == 0) { | 1213 | cap_ndoms(iommu->cap), i+1); |
1205 | if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) | ||
1206 | vm_domain_exit(domain); | ||
1207 | else | ||
1208 | domain_exit(domain); | ||
1209 | } | 1214 | } |
1210 | spin_unlock_irqrestore(&domain->iommu_lock, flags); | ||
1211 | |||
1212 | i = find_next_bit(iommu->domain_ids, | ||
1213 | cap_ndoms(iommu->cap), i+1); | ||
1214 | } | 1215 | } |
1215 | 1216 | ||
1216 | if (iommu->gcmd & DMA_GCMD_TE) | 1217 | if (iommu->gcmd & DMA_GCMD_TE) |