diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2009-11-26 05:13:32 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2009-11-27 08:20:34 -0500 |
commit | 7c392cbe984d904f7c89a6a75b2ac245254e8da5 (patch) | |
tree | 48b5d1f73cd3814de15d32a0e82a963dd4237f9c | |
parent | 241000556f751dacd332df6ab2e903a23746e51e (diff) |
x86/amd-iommu: Keep devices per domain in a list
This patch introduces a list to each protection domain which
keeps all devices associated with the domain. This can be
used later to optimize certain functions and to completly
remove the amd_iommu_pd_table.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r-- | arch/x86/include/asm/amd_iommu_types.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 11 |
2 files changed, 13 insertions, 0 deletions
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 434e90ed89c5..93953d1922c4 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h | |||
@@ -235,6 +235,7 @@ extern bool amd_iommu_np_cache; | |||
235 | */ | 235 | */ |
236 | struct protection_domain { | 236 | struct protection_domain { |
237 | struct list_head list; /* for list of all protection domains */ | 237 | struct list_head list; /* for list of all protection domains */ |
238 | struct list_head dev_list; /* List of all devices in this domain */ | ||
238 | spinlock_t lock; /* mostly used to lock the page table*/ | 239 | spinlock_t lock; /* mostly used to lock the page table*/ |
239 | u16 id; /* the domain id written to the device table */ | 240 | u16 id; /* the domain id written to the device table */ |
240 | int mode; /* paging mode (0-6 levels) */ | 241 | int mode; /* paging mode (0-6 levels) */ |
@@ -251,6 +252,7 @@ struct protection_domain { | |||
251 | * This struct contains device specific data for the IOMMU | 252 | * This struct contains device specific data for the IOMMU |
252 | */ | 253 | */ |
253 | struct iommu_dev_data { | 254 | struct iommu_dev_data { |
255 | struct list_head list; /* For domain->dev_list */ | ||
254 | struct device *alias; /* The Alias Device */ | 256 | struct device *alias; /* The Alias Device */ |
255 | struct protection_domain *domain; /* Domain the device is bound to */ | 257 | struct protection_domain *domain; /* Domain the device is bound to */ |
256 | atomic_t bind; /* Domain attach reverent count */ | 258 | atomic_t bind; /* Domain attach reverent count */ |
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index f5db7d5e444e..530d6080940f 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -1286,6 +1286,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void) | |||
1286 | dma_dom->domain.id = domain_id_alloc(); | 1286 | dma_dom->domain.id = domain_id_alloc(); |
1287 | if (dma_dom->domain.id == 0) | 1287 | if (dma_dom->domain.id == 0) |
1288 | goto free_dma_dom; | 1288 | goto free_dma_dom; |
1289 | INIT_LIST_HEAD(&dma_dom->domain.dev_list); | ||
1289 | dma_dom->domain.mode = PAGE_MODE_2_LEVEL; | 1290 | dma_dom->domain.mode = PAGE_MODE_2_LEVEL; |
1290 | dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL); | 1291 | dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL); |
1291 | dma_dom->domain.flags = PD_DMA_OPS_MASK; | 1292 | dma_dom->domain.flags = PD_DMA_OPS_MASK; |
@@ -1408,6 +1409,7 @@ static int __attach_device(struct device *dev, | |||
1408 | if (alias != devid) { | 1409 | if (alias != devid) { |
1409 | if (alias_data->domain == NULL) { | 1410 | if (alias_data->domain == NULL) { |
1410 | alias_data->domain = domain; | 1411 | alias_data->domain = domain; |
1412 | list_add(&alias_data->list, &domain->dev_list); | ||
1411 | set_dte_entry(alias, domain); | 1413 | set_dte_entry(alias, domain); |
1412 | } | 1414 | } |
1413 | 1415 | ||
@@ -1416,6 +1418,7 @@ static int __attach_device(struct device *dev, | |||
1416 | 1418 | ||
1417 | if (dev_data->domain == NULL) { | 1419 | if (dev_data->domain == NULL) { |
1418 | dev_data->domain = domain; | 1420 | dev_data->domain = domain; |
1421 | list_add(&dev_data->list, &domain->dev_list); | ||
1419 | set_dte_entry(devid, domain); | 1422 | set_dte_entry(devid, domain); |
1420 | } | 1423 | } |
1421 | 1424 | ||
@@ -1460,6 +1463,7 @@ static void __detach_device(struct device *dev) | |||
1460 | struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; | 1463 | struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; |
1461 | struct iommu_dev_data *dev_data = get_dev_data(dev); | 1464 | struct iommu_dev_data *dev_data = get_dev_data(dev); |
1462 | struct iommu_dev_data *alias_data; | 1465 | struct iommu_dev_data *alias_data; |
1466 | unsigned long flags; | ||
1463 | 1467 | ||
1464 | BUG_ON(!iommu); | 1468 | BUG_ON(!iommu); |
1465 | 1469 | ||
@@ -1469,13 +1473,19 @@ static void __detach_device(struct device *dev) | |||
1469 | if (devid != alias) { | 1473 | if (devid != alias) { |
1470 | alias_data = get_dev_data(dev_data->alias); | 1474 | alias_data = get_dev_data(dev_data->alias); |
1471 | if (atomic_dec_and_test(&alias_data->bind)) { | 1475 | if (atomic_dec_and_test(&alias_data->bind)) { |
1476 | spin_lock_irqsave(&alias_data->domain->lock, flags); | ||
1472 | clear_dte_entry(alias); | 1477 | clear_dte_entry(alias); |
1478 | list_del(&alias_data->list); | ||
1479 | spin_unlock_irqrestore(&alias_data->domain->lock, flags); | ||
1473 | alias_data->domain = NULL; | 1480 | alias_data->domain = NULL; |
1474 | } | 1481 | } |
1475 | } | 1482 | } |
1476 | 1483 | ||
1477 | if (atomic_dec_and_test(&dev_data->bind)) { | 1484 | if (atomic_dec_and_test(&dev_data->bind)) { |
1485 | spin_lock_irqsave(&dev_data->domain->lock, flags); | ||
1478 | clear_dte_entry(devid); | 1486 | clear_dte_entry(devid); |
1487 | list_del(&dev_data->list); | ||
1488 | spin_unlock_irqrestore(&dev_data->domain->lock, flags); | ||
1479 | dev_data->domain = NULL; | 1489 | dev_data->domain = NULL; |
1480 | } | 1490 | } |
1481 | 1491 | ||
@@ -2294,6 +2304,7 @@ static struct protection_domain *protection_domain_alloc(void) | |||
2294 | domain->id = domain_id_alloc(); | 2304 | domain->id = domain_id_alloc(); |
2295 | if (!domain->id) | 2305 | if (!domain->id) |
2296 | goto out_err; | 2306 | goto out_err; |
2307 | INIT_LIST_HEAD(&domain->dev_list); | ||
2297 | 2308 | ||
2298 | add_domain_to_list(domain); | 2309 | add_domain_to_list(domain); |
2299 | 2310 | ||