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 /drivers/pci/intel-iommu.c | |
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>
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-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); |