diff options
| author | Jiang Liu <jiang.liu@linux.intel.com> | 2014-07-11 02:19:37 -0400 |
|---|---|---|
| committer | Joerg Roedel <jroedel@suse.de> | 2014-07-23 10:04:47 -0400 |
| commit | 161f693460772ef269ab35cbd145b6431e935eac (patch) | |
| tree | 47ed588294459adf8521a6af63129a5130bf737b /drivers | |
| parent | a156ef99e874f3701367cc192aa604bcf8c0a236 (diff) | |
iommu/vt-d: Fix issue in computing domain's iommu_snooping flag
IOMMU units may dynamically attached to/detached from domains,
so we should scan all active IOMMU units when computing iommu_snooping
flag for a domain instead of only scanning IOMMU units associated
with the domain.
Also check snooping and superpage capabilities when hot-adding DMAR units.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/iommu/intel-iommu.c | 42 |
1 files changed, 24 insertions, 18 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index cd1ba24c766a..58cc2b75d7ae 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -633,50 +633,56 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) | |||
| 633 | rcu_read_unlock(); | 633 | rcu_read_unlock(); |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | static void domain_update_iommu_snooping(struct dmar_domain *domain) | 636 | static int domain_update_iommu_snooping(struct intel_iommu *skip) |
| 637 | { | 637 | { |
| 638 | int i; | 638 | struct dmar_drhd_unit *drhd; |
| 639 | 639 | struct intel_iommu *iommu; | |
| 640 | domain->iommu_snooping = 1; | 640 | int ret = 1; |
| 641 | 641 | ||
| 642 | for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { | 642 | rcu_read_lock(); |
| 643 | if (!ecap_sc_support(g_iommus[i]->ecap)) { | 643 | for_each_active_iommu(iommu, drhd) { |
| 644 | domain->iommu_snooping = 0; | 644 | if (iommu != skip) { |
| 645 | break; | 645 | if (!ecap_sc_support(iommu->ecap)) { |
| 646 | ret = 0; | ||
| 647 | break; | ||
| 648 | } | ||
| 646 | } | 649 | } |
| 647 | } | 650 | } |
| 651 | rcu_read_unlock(); | ||
| 652 | |||
| 653 | return ret; | ||
| 648 | } | 654 | } |
| 649 | 655 | ||
| 650 | static void domain_update_iommu_superpage(struct dmar_domain *domain) | 656 | static int domain_update_iommu_superpage(struct intel_iommu *skip) |
| 651 | { | 657 | { |
| 652 | struct dmar_drhd_unit *drhd; | 658 | struct dmar_drhd_unit *drhd; |
| 653 | struct intel_iommu *iommu = NULL; | 659 | struct intel_iommu *iommu; |
| 654 | int mask = 0xf; | 660 | int mask = 0xf; |
| 655 | 661 | ||
| 656 | if (!intel_iommu_superpage) { | 662 | if (!intel_iommu_superpage) { |
| 657 | domain->iommu_superpage = 0; | 663 | return 0; |
| 658 | return; | ||
| 659 | } | 664 | } |
| 660 | 665 | ||
| 661 | /* set iommu_superpage to the smallest common denominator */ | 666 | /* set iommu_superpage to the smallest common denominator */ |
| 662 | rcu_read_lock(); | 667 | rcu_read_lock(); |
| 663 | for_each_active_iommu(iommu, drhd) { | 668 | for_each_active_iommu(iommu, drhd) { |
| 664 | mask &= cap_super_page_val(iommu->cap); | 669 | if (iommu != skip) { |
| 665 | if (!mask) { | 670 | mask &= cap_super_page_val(iommu->cap); |
| 666 | break; | 671 | if (!mask) |
| 672 | break; | ||
| 667 | } | 673 | } |
| 668 | } | 674 | } |
| 669 | rcu_read_unlock(); | 675 | rcu_read_unlock(); |
| 670 | 676 | ||
| 671 | domain->iommu_superpage = fls(mask); | 677 | return fls(mask); |
| 672 | } | 678 | } |
| 673 | 679 | ||
| 674 | /* Some capabilities may be different across iommus */ | 680 | /* Some capabilities may be different across iommus */ |
| 675 | static void domain_update_iommu_cap(struct dmar_domain *domain) | 681 | static void domain_update_iommu_cap(struct dmar_domain *domain) |
| 676 | { | 682 | { |
| 677 | domain_update_iommu_coherency(domain); | 683 | domain_update_iommu_coherency(domain); |
| 678 | domain_update_iommu_snooping(domain); | 684 | domain->iommu_snooping = domain_update_iommu_snooping(NULL); |
| 679 | domain_update_iommu_superpage(domain); | 685 | domain->iommu_superpage = domain_update_iommu_superpage(NULL); |
| 680 | } | 686 | } |
| 681 | 687 | ||
| 682 | static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn) | 688 | static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn) |
