diff options
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r-- | drivers/iommu/intel-iommu.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 8aa580dc3033..a08a53448b72 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -354,10 +354,18 @@ static int hw_pass_through = 1; | |||
354 | /* si_domain contains mulitple devices */ | 354 | /* si_domain contains mulitple devices */ |
355 | #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2) | 355 | #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 2) |
356 | 356 | ||
357 | /* define the limit of IOMMUs supported in each domain */ | ||
358 | #ifdef CONFIG_X86 | ||
359 | # define IOMMU_UNITS_SUPPORTED MAX_IO_APICS | ||
360 | #else | ||
361 | # define IOMMU_UNITS_SUPPORTED 64 | ||
362 | #endif | ||
363 | |||
357 | struct dmar_domain { | 364 | struct dmar_domain { |
358 | int id; /* domain id */ | 365 | int id; /* domain id */ |
359 | int nid; /* node id */ | 366 | int nid; /* node id */ |
360 | unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/ | 367 | DECLARE_BITMAP(iommu_bmp, IOMMU_UNITS_SUPPORTED); |
368 | /* bitmap of iommus this domain uses*/ | ||
361 | 369 | ||
362 | struct list_head devices; /* all devices' list */ | 370 | struct list_head devices; /* all devices' list */ |
363 | struct iova_domain iovad; /* iova's that belong to this domain */ | 371 | struct iova_domain iovad; /* iova's that belong to this domain */ |
@@ -569,7 +577,7 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) | |||
569 | BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE); | 577 | BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE); |
570 | BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY); | 578 | BUG_ON(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY); |
571 | 579 | ||
572 | iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); | 580 | iommu_id = find_first_bit(domain->iommu_bmp, g_num_of_iommus); |
573 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) | 581 | if (iommu_id < 0 || iommu_id >= g_num_of_iommus) |
574 | return NULL; | 582 | return NULL; |
575 | 583 | ||
@@ -582,7 +590,7 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) | |||
582 | 590 | ||
583 | domain->iommu_coherency = 1; | 591 | domain->iommu_coherency = 1; |
584 | 592 | ||
585 | for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { | 593 | for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { |
586 | if (!ecap_coherent(g_iommus[i]->ecap)) { | 594 | if (!ecap_coherent(g_iommus[i]->ecap)) { |
587 | domain->iommu_coherency = 0; | 595 | domain->iommu_coherency = 0; |
588 | break; | 596 | break; |
@@ -596,7 +604,7 @@ static void domain_update_iommu_snooping(struct dmar_domain *domain) | |||
596 | 604 | ||
597 | domain->iommu_snooping = 1; | 605 | domain->iommu_snooping = 1; |
598 | 606 | ||
599 | for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { | 607 | for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { |
600 | if (!ecap_sc_support(g_iommus[i]->ecap)) { | 608 | if (!ecap_sc_support(g_iommus[i]->ecap)) { |
601 | domain->iommu_snooping = 0; | 609 | domain->iommu_snooping = 0; |
602 | break; | 610 | break; |
@@ -1332,7 +1340,7 @@ static struct dmar_domain *alloc_domain(void) | |||
1332 | return NULL; | 1340 | return NULL; |
1333 | 1341 | ||
1334 | domain->nid = -1; | 1342 | domain->nid = -1; |
1335 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | 1343 | memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp)); |
1336 | domain->flags = 0; | 1344 | domain->flags = 0; |
1337 | 1345 | ||
1338 | return domain; | 1346 | return domain; |
@@ -1358,7 +1366,7 @@ static int iommu_attach_domain(struct dmar_domain *domain, | |||
1358 | 1366 | ||
1359 | domain->id = num; | 1367 | domain->id = num; |
1360 | set_bit(num, iommu->domain_ids); | 1368 | set_bit(num, iommu->domain_ids); |
1361 | set_bit(iommu->seq_id, &domain->iommu_bmp); | 1369 | set_bit(iommu->seq_id, domain->iommu_bmp); |
1362 | iommu->domains[num] = domain; | 1370 | iommu->domains[num] = domain; |
1363 | spin_unlock_irqrestore(&iommu->lock, flags); | 1371 | spin_unlock_irqrestore(&iommu->lock, flags); |
1364 | 1372 | ||
@@ -1383,7 +1391,7 @@ static void iommu_detach_domain(struct dmar_domain *domain, | |||
1383 | 1391 | ||
1384 | if (found) { | 1392 | if (found) { |
1385 | clear_bit(num, iommu->domain_ids); | 1393 | clear_bit(num, iommu->domain_ids); |
1386 | clear_bit(iommu->seq_id, &domain->iommu_bmp); | 1394 | clear_bit(iommu->seq_id, domain->iommu_bmp); |
1387 | iommu->domains[num] = NULL; | 1395 | iommu->domains[num] = NULL; |
1388 | } | 1396 | } |
1389 | spin_unlock_irqrestore(&iommu->lock, flags); | 1397 | spin_unlock_irqrestore(&iommu->lock, flags); |
@@ -1525,7 +1533,7 @@ static void domain_exit(struct dmar_domain *domain) | |||
1525 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); | 1533 | dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw)); |
1526 | 1534 | ||
1527 | for_each_active_iommu(iommu, drhd) | 1535 | for_each_active_iommu(iommu, drhd) |
1528 | if (test_bit(iommu->seq_id, &domain->iommu_bmp)) | 1536 | if (test_bit(iommu->seq_id, domain->iommu_bmp)) |
1529 | iommu_detach_domain(domain, iommu); | 1537 | iommu_detach_domain(domain, iommu); |
1530 | 1538 | ||
1531 | free_domain_mem(domain); | 1539 | free_domain_mem(domain); |
@@ -1651,7 +1659,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, | |||
1651 | spin_unlock_irqrestore(&iommu->lock, flags); | 1659 | spin_unlock_irqrestore(&iommu->lock, flags); |
1652 | 1660 | ||
1653 | spin_lock_irqsave(&domain->iommu_lock, flags); | 1661 | spin_lock_irqsave(&domain->iommu_lock, flags); |
1654 | if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) { | 1662 | if (!test_and_set_bit(iommu->seq_id, domain->iommu_bmp)) { |
1655 | domain->iommu_count++; | 1663 | domain->iommu_count++; |
1656 | if (domain->iommu_count == 1) | 1664 | if (domain->iommu_count == 1) |
1657 | domain->nid = iommu->node; | 1665 | domain->nid = iommu->node; |
@@ -2400,12 +2408,17 @@ static int __init init_dmars(void) | |||
2400 | * endfor | 2408 | * endfor |
2401 | */ | 2409 | */ |
2402 | for_each_drhd_unit(drhd) { | 2410 | for_each_drhd_unit(drhd) { |
2403 | g_num_of_iommus++; | ||
2404 | /* | 2411 | /* |
2405 | * lock not needed as this is only incremented in the single | 2412 | * lock not needed as this is only incremented in the single |
2406 | * threaded kernel __init code path all other access are read | 2413 | * threaded kernel __init code path all other access are read |
2407 | * only | 2414 | * only |
2408 | */ | 2415 | */ |
2416 | if (g_num_of_iommus < IOMMU_UNITS_SUPPORTED) { | ||
2417 | g_num_of_iommus++; | ||
2418 | continue; | ||
2419 | } | ||
2420 | printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n", | ||
2421 | IOMMU_UNITS_SUPPORTED); | ||
2409 | } | 2422 | } |
2410 | 2423 | ||
2411 | g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), | 2424 | g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), |
@@ -3746,7 +3759,7 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain, | |||
3746 | if (found == 0) { | 3759 | if (found == 0) { |
3747 | unsigned long tmp_flags; | 3760 | unsigned long tmp_flags; |
3748 | spin_lock_irqsave(&domain->iommu_lock, tmp_flags); | 3761 | spin_lock_irqsave(&domain->iommu_lock, tmp_flags); |
3749 | clear_bit(iommu->seq_id, &domain->iommu_bmp); | 3762 | clear_bit(iommu->seq_id, domain->iommu_bmp); |
3750 | domain->iommu_count--; | 3763 | domain->iommu_count--; |
3751 | domain_update_iommu_cap(domain); | 3764 | domain_update_iommu_cap(domain); |
3752 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); | 3765 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); |
@@ -3788,7 +3801,7 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain) | |||
3788 | */ | 3801 | */ |
3789 | spin_lock_irqsave(&domain->iommu_lock, flags2); | 3802 | spin_lock_irqsave(&domain->iommu_lock, flags2); |
3790 | if (test_and_clear_bit(iommu->seq_id, | 3803 | if (test_and_clear_bit(iommu->seq_id, |
3791 | &domain->iommu_bmp)) { | 3804 | domain->iommu_bmp)) { |
3792 | domain->iommu_count--; | 3805 | domain->iommu_count--; |
3793 | domain_update_iommu_cap(domain); | 3806 | domain_update_iommu_cap(domain); |
3794 | } | 3807 | } |
@@ -3813,7 +3826,7 @@ static struct dmar_domain *iommu_alloc_vm_domain(void) | |||
3813 | 3826 | ||
3814 | domain->id = vm_domid++; | 3827 | domain->id = vm_domid++; |
3815 | domain->nid = -1; | 3828 | domain->nid = -1; |
3816 | memset(&domain->iommu_bmp, 0, sizeof(unsigned long)); | 3829 | memset(domain->iommu_bmp, 0, sizeof(domain->iommu_bmp)); |
3817 | domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE; | 3830 | domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE; |
3818 | 3831 | ||
3819 | return domain; | 3832 | return domain; |