aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-12-02 11:49:42 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2009-01-03 08:11:54 -0500
commit5b28df6f43ac9878f310ad0cb7f11ddb262a7ac6 (patch)
tree9045d718c721886b90e7de98b572881f2482cdc1 /arch
parent9fdb19d64c0247f23343b51fc85f438f8e7a2f3c (diff)
AMD IOMMU: add checks for dma_ops domain to dma_ops functions
Impact: detect when a driver uses a device assigned otherwise Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/amd_iommu.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index bb28e2cda711..5c465c91150e 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -792,6 +792,15 @@ free_dma_dom:
792} 792}
793 793
794/* 794/*
795 * little helper function to check whether a given protection domain is a
796 * dma_ops domain
797 */
798static bool dma_ops_domain(struct protection_domain *domain)
799{
800 return domain->flags & PD_DMA_OPS_MASK;
801}
802
803/*
795 * Find out the protection domain structure for a given PCI device. This 804 * Find out the protection domain structure for a given PCI device. This
796 * will give us the pointer to the page table root for example. 805 * will give us the pointer to the page table root for example.
797 */ 806 */
@@ -1096,6 +1105,9 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
1096 /* device not handled by any AMD IOMMU */ 1105 /* device not handled by any AMD IOMMU */
1097 return (dma_addr_t)paddr; 1106 return (dma_addr_t)paddr;
1098 1107
1108 if (!dma_ops_domain(domain))
1109 return bad_dma_address;
1110
1099 spin_lock_irqsave(&domain->lock, flags); 1111 spin_lock_irqsave(&domain->lock, flags);
1100 addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false, 1112 addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false,
1101 dma_mask); 1113 dma_mask);
@@ -1126,6 +1138,9 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr,
1126 /* device not handled by any AMD IOMMU */ 1138 /* device not handled by any AMD IOMMU */
1127 return; 1139 return;
1128 1140
1141 if (!dma_ops_domain(domain))
1142 return;
1143
1129 spin_lock_irqsave(&domain->lock, flags); 1144 spin_lock_irqsave(&domain->lock, flags);
1130 1145
1131 __unmap_single(iommu, domain->priv, dma_addr, size, dir); 1146 __unmap_single(iommu, domain->priv, dma_addr, size, dir);
@@ -1180,6 +1195,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
1180 if (!iommu || !domain) 1195 if (!iommu || !domain)
1181 return map_sg_no_iommu(dev, sglist, nelems, dir); 1196 return map_sg_no_iommu(dev, sglist, nelems, dir);
1182 1197
1198 if (!dma_ops_domain(domain))
1199 return 0;
1200
1183 spin_lock_irqsave(&domain->lock, flags); 1201 spin_lock_irqsave(&domain->lock, flags);
1184 1202
1185 for_each_sg(sglist, s, nelems, i) { 1203 for_each_sg(sglist, s, nelems, i) {
@@ -1233,6 +1251,9 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
1233 !get_device_resources(dev, &iommu, &domain, &devid)) 1251 !get_device_resources(dev, &iommu, &domain, &devid))
1234 return; 1252 return;
1235 1253
1254 if (!dma_ops_domain(domain))
1255 return;
1256
1236 spin_lock_irqsave(&domain->lock, flags); 1257 spin_lock_irqsave(&domain->lock, flags);
1237 1258
1238 for_each_sg(sglist, s, nelems, i) { 1259 for_each_sg(sglist, s, nelems, i) {
@@ -1278,6 +1299,9 @@ static void *alloc_coherent(struct device *dev, size_t size,
1278 return virt_addr; 1299 return virt_addr;
1279 } 1300 }
1280 1301
1302 if (!dma_ops_domain(domain))
1303 goto out_free;
1304
1281 if (!dma_mask) 1305 if (!dma_mask)
1282 dma_mask = *dev->dma_mask; 1306 dma_mask = *dev->dma_mask;
1283 1307
@@ -1286,18 +1310,20 @@ static void *alloc_coherent(struct device *dev, size_t size,
1286 *dma_addr = __map_single(dev, iommu, domain->priv, paddr, 1310 *dma_addr = __map_single(dev, iommu, domain->priv, paddr,
1287 size, DMA_BIDIRECTIONAL, true, dma_mask); 1311 size, DMA_BIDIRECTIONAL, true, dma_mask);
1288 1312
1289 if (*dma_addr == bad_dma_address) { 1313 if (*dma_addr == bad_dma_address)
1290 free_pages((unsigned long)virt_addr, get_order(size)); 1314 goto out_free;
1291 virt_addr = NULL;
1292 goto out;
1293 }
1294 1315
1295 iommu_completion_wait(iommu); 1316 iommu_completion_wait(iommu);
1296 1317
1297out:
1298 spin_unlock_irqrestore(&domain->lock, flags); 1318 spin_unlock_irqrestore(&domain->lock, flags);
1299 1319
1300 return virt_addr; 1320 return virt_addr;
1321
1322out_free:
1323
1324 free_pages((unsigned long)virt_addr, get_order(size));
1325
1326 return NULL;
1301} 1327}
1302 1328
1303/* 1329/*
@@ -1319,6 +1345,9 @@ static void free_coherent(struct device *dev, size_t size,
1319 if (!iommu || !domain) 1345 if (!iommu || !domain)
1320 goto free_mem; 1346 goto free_mem;
1321 1347
1348 if (!dma_ops_domain(domain))
1349 goto free_mem;
1350
1322 spin_lock_irqsave(&domain->lock, flags); 1351 spin_lock_irqsave(&domain->lock, flags);
1323 1352
1324 __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); 1353 __unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);