diff options
| author | Suresh Siddha <suresh.b.siddha@intel.com> | 2009-10-02 14:01:24 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-10-05 02:55:33 -0400 |
| commit | 4c923d4714821cf32ff115bb9c91867dff711972 (patch) | |
| tree | deb6220ae172c4512e594682e0c4fca06629abc0 | |
| parent | 824cd75bf30cfc52c4b468f3cabf6932fd012654 (diff) | |
iommu: Allocate dma-remapping structures using numa locality info
Allocate dma-remapping structures using numa locality info. On platforms
having remapping hardware units span different nodes, this enables
optimized dma-remapping transalation structures access by remapping hardware.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
| -rw-r--r-- | drivers/pci/intel-iommu.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index b1e97e682500..c83113646223 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -277,6 +277,7 @@ static int hw_pass_through = 1; | |||
| 277 | 277 | ||
| 278 | struct dmar_domain { | 278 | struct dmar_domain { |
| 279 | int id; /* domain id */ | 279 | int id; /* domain id */ |
| 280 | int nid; /* node id */ | ||
| 280 | unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/ | 281 | unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/ |
| 281 | 282 | ||
| 282 | struct list_head devices; /* all devices' list */ | 283 | struct list_head devices; /* all devices' list */ |
| @@ -400,15 +401,18 @@ static inline void *iommu_kmem_cache_alloc(struct kmem_cache *cachep) | |||
| 400 | } | 401 | } |
| 401 | 402 | ||
| 402 | 403 | ||
| 403 | static inline void *alloc_pgtable_page(void) | 404 | static inline void *alloc_pgtable_page(int node) |
| 404 | { | 405 | { |
| 405 | unsigned int flags; | 406 | unsigned int flags; |
| 406 | void *vaddr; | 407 | struct page *page; |
| 408 | void *vaddr = NULL; | ||
| 407 | 409 | ||
| 408 | /* trying to avoid low memory issues */ | 410 | /* trying to avoid low memory issues */ |
| 409 | flags = current->flags & PF_MEMALLOC; | 411 | flags = current->flags & PF_MEMALLOC; |
| 410 | current->flags |= PF_MEMALLOC; | 412 | current->flags |= PF_MEMALLOC; |
| 411 | vaddr = (void *)get_zeroed_page(GFP_ATOMIC); | 413 | page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0); |
| 414 | if (page) | ||
| 415 | vaddr = page_address(page); | ||
| 412 | current->flags &= (~PF_MEMALLOC | flags); | 416 | current->flags &= (~PF_MEMALLOC | flags); |
| 413 | return vaddr; | 417 | return vaddr; |
| 414 | } | 418 | } |
| @@ -589,7 +593,8 @@ static struct context_entry * device_to_context_entry(struct intel_iommu *iommu, | |||
| 589 | root = &iommu->root_entry[bus]; | 593 | root = &iommu->root_entry[bus]; |
| 590 | context = get_context_addr_from_root(root); | 594 | context = get_context_addr_from_root(root); |
| 591 | if (!context) { | 595 | if (!context) { |
| 592 | context = (struct context_entry *)alloc_pgtable_page(); | 596 | context = (struct context_entry *) |
| 597 | alloc_pgtable_page(iommu->node); | ||
| 593 | if (!context) { | 598 | if (!context) { |
| 594 | spin_unlock_irqrestore(&iommu->lock, flags); | 599 | spin_unlock_irqrestore(&iommu->lock, flags); |
| 595 | return NULL; | 600 | return NULL; |
| @@ -732,7 +737,7 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, | |||
| 732 | if (!dma_pte_present(pte)) { | 737 | if (!dma_pte_present(pte)) { |
| 733 | uint64_t pteval; | 738 | uint64_t pteval; |
| 734 | 739 | ||
| 735 | tmp_page = alloc_pgtable_page(); | 740 | tmp_page = alloc_pgtable_page(domain->nid); |
| 736 | 741 | ||
| 737 | if (!tmp_page) | 742 | if (!tmp_page) |
| 738 | return NULL; | 743 | return NULL; |
| @@ -868,7 +873,7 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu) | |||
| 868 | struct root_entry *root; | 873 | struct root_entry *root; |
| 869 | unsigned long flags; | 874 | unsigned long flags; |
| 870 | 875 | ||
| 871 | root = (struct root_entry *)alloc_pgtable_page(); | 876 | root = (struct root_entry *)alloc_pgtable_page(iommu->node); |
| 872 | if (!root) | 877 | if (!root) |
| 873 | return -ENOMEM; | 878 | return -ENOMEM; |
| 874 | 879 | ||
| @@ -1263,6 +1268,7 @@ static struct dmar_domain *alloc_domain(void) | |||
| 1263 | if (!domain) | 1268 | if (!domain) |
| 1264 | return NULL; | 1269 | return NULL; |
| 1265 | 1270 | ||
| 1271 | domain->nid = -1; | ||
| 1266 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | 1272 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); |
| 1267 | domain->flags = 0; | 1273 | domain->flags = 0; |
| 1268 | 1274 | ||
| @@ -1420,9 +1426,10 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
| 1420 | domain->iommu_snooping = 0; | 1426 | domain->iommu_snooping = 0; |
| 1421 | 1427 | ||
| 1422 | domain->iommu_count = 1; | 1428 | domain->iommu_count = 1; |
| 1429 | domain->nid = iommu->node; | ||
| 1423 | 1430 | ||
| 1424 | /* always allocate the top pgd */ | 1431 | /* always allocate the top pgd */ |
| 1425 | domain->pgd = (struct dma_pte *)alloc_pgtable_page(); | 1432 | domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); |
| 1426 | if (!domain->pgd) | 1433 | if (!domain->pgd) |
| 1427 | return -ENOMEM; | 1434 | return -ENOMEM; |
| 1428 | __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE); | 1435 | __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE); |
| @@ -1577,6 +1584,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, | |||
| 1577 | spin_lock_irqsave(&domain->iommu_lock, flags); | 1584 | spin_lock_irqsave(&domain->iommu_lock, flags); |
| 1578 | if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) { | 1585 | if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) { |
| 1579 | domain->iommu_count++; | 1586 | domain->iommu_count++; |
| 1587 | if (domain->iommu_count == 1) | ||
| 1588 | domain->nid = iommu->node; | ||
| 1580 | domain_update_iommu_cap(domain); | 1589 | domain_update_iommu_cap(domain); |
| 1581 | } | 1590 | } |
| 1582 | spin_unlock_irqrestore(&domain->iommu_lock, flags); | 1591 | spin_unlock_irqrestore(&domain->iommu_lock, flags); |
| @@ -3416,6 +3425,7 @@ static struct dmar_domain *iommu_alloc_vm_domain(void) | |||
| 3416 | return NULL; | 3425 | return NULL; |
| 3417 | 3426 | ||
| 3418 | domain->id = vm_domid++; | 3427 | domain->id = vm_domid++; |
| 3428 | domain->nid = -1; | ||
| 3419 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | 3429 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); |
| 3420 | domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE; | 3430 | domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE; |
| 3421 | 3431 | ||
| @@ -3442,9 +3452,10 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width) | |||
| 3442 | domain->iommu_coherency = 0; | 3452 | domain->iommu_coherency = 0; |
| 3443 | domain->iommu_snooping = 0; | 3453 | domain->iommu_snooping = 0; |
| 3444 | domain->max_addr = 0; | 3454 | domain->max_addr = 0; |
| 3455 | domain->nid = -1; | ||
| 3445 | 3456 | ||
| 3446 | /* always allocate the top pgd */ | 3457 | /* always allocate the top pgd */ |
| 3447 | domain->pgd = (struct dma_pte *)alloc_pgtable_page(); | 3458 | domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid); |
| 3448 | if (!domain->pgd) | 3459 | if (!domain->pgd) |
| 3449 | return -ENOMEM; | 3460 | return -ENOMEM; |
| 3450 | domain_flush_cache(domain, domain->pgd, PAGE_SIZE); | 3461 | domain_flush_cache(domain, domain->pgd, PAGE_SIZE); |
