aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/intel-iommu.c
diff options
context:
space:
mode:
authorDonald Dutile <ddutile@redhat.com>2009-08-20 16:51:34 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-08-24 03:56:26 -0400
commit94a91b5051a77d8a71d4f11a3240f0d9c51b6cf2 (patch)
tree04d81ea79520cbd662024ee23cd3f834dd950ed0 /drivers/pci/intel-iommu.c
parent071e13746f9ebb259987c71ea77f11e7656769a2 (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.c35
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)