diff options
author | Sheng Yang <sheng@linux.intel.com> | 2009-03-18 03:33:05 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-03-24 05:42:43 -0400 |
commit | 58c610bd1a3f50820e45a7c09ec0e44d2cda15dd (patch) | |
tree | 696539e1e17fd7600222865fa331e9144737a58b /drivers/pci | |
parent | a1e4ee22863d41a6fbb24310d7951836cb6dafe7 (diff) |
intel-iommu: Snooping control support
Snooping control enabled IOMMU to guarantee DMA cache coherency and thus reduce
software effort (VMM) in maintaining effective memory type.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/intel-iommu.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index f3f686581a90..be999ff025af 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -231,6 +231,7 @@ struct dmar_domain { | |||
231 | int flags; /* flags to find out type of domain */ | 231 | int flags; /* flags to find out type of domain */ |
232 | 232 | ||
233 | int iommu_coherency;/* indicate coherency of iommu access */ | 233 | int iommu_coherency;/* indicate coherency of iommu access */ |
234 | int iommu_snooping; /* indicate snooping control feature*/ | ||
234 | int iommu_count; /* reference count of iommu */ | 235 | int iommu_count; /* reference count of iommu */ |
235 | spinlock_t iommu_lock; /* protect iommu set in domain */ | 236 | spinlock_t iommu_lock; /* protect iommu set in domain */ |
236 | u64 max_addr; /* maximum mapped address */ | 237 | u64 max_addr; /* maximum mapped address */ |
@@ -421,7 +422,6 @@ static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) | |||
421 | return g_iommus[iommu_id]; | 422 | return g_iommus[iommu_id]; |
422 | } | 423 | } |
423 | 424 | ||
424 | /* "Coherency" capability may be different across iommus */ | ||
425 | static void domain_update_iommu_coherency(struct dmar_domain *domain) | 425 | static void domain_update_iommu_coherency(struct dmar_domain *domain) |
426 | { | 426 | { |
427 | int i; | 427 | int i; |
@@ -438,6 +438,29 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) | |||
438 | } | 438 | } |
439 | } | 439 | } |
440 | 440 | ||
441 | static void domain_update_iommu_snooping(struct dmar_domain *domain) | ||
442 | { | ||
443 | int i; | ||
444 | |||
445 | domain->iommu_snooping = 1; | ||
446 | |||
447 | i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); | ||
448 | for (; i < g_num_of_iommus; ) { | ||
449 | if (!ecap_sc_support(g_iommus[i]->ecap)) { | ||
450 | domain->iommu_snooping = 0; | ||
451 | break; | ||
452 | } | ||
453 | i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1); | ||
454 | } | ||
455 | } | ||
456 | |||
457 | /* Some capabilities may be different across iommus */ | ||
458 | static void domain_update_iommu_cap(struct dmar_domain *domain) | ||
459 | { | ||
460 | domain_update_iommu_coherency(domain); | ||
461 | domain_update_iommu_snooping(domain); | ||
462 | } | ||
463 | |||
441 | static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn) | 464 | static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn) |
442 | { | 465 | { |
443 | struct dmar_drhd_unit *drhd = NULL; | 466 | struct dmar_drhd_unit *drhd = NULL; |
@@ -1429,6 +1452,11 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
1429 | else | 1452 | else |
1430 | domain->iommu_coherency = 0; | 1453 | domain->iommu_coherency = 0; |
1431 | 1454 | ||
1455 | if (ecap_sc_support(iommu->ecap)) | ||
1456 | domain->iommu_snooping = 1; | ||
1457 | else | ||
1458 | domain->iommu_snooping = 0; | ||
1459 | |||
1432 | domain->iommu_count = 1; | 1460 | domain->iommu_count = 1; |
1433 | 1461 | ||
1434 | /* always allocate the top pgd */ | 1462 | /* always allocate the top pgd */ |
@@ -1557,7 +1585,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
1557 | spin_lock_irqsave(&domain->iommu_lock, flags); | 1585 | spin_lock_irqsave(&domain->iommu_lock, flags); |
1558 | if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) { | 1586 | if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) { |
1559 | domain->iommu_count++; | 1587 | domain->iommu_count++; |
1560 | domain_update_iommu_coherency(domain); | 1588 | domain_update_iommu_cap(domain); |
1561 | } | 1589 | } |
1562 | spin_unlock_irqrestore(&domain->iommu_lock, flags); | 1590 | spin_unlock_irqrestore(&domain->iommu_lock, flags); |
1563 | return 0; | 1591 | return 0; |
@@ -2820,7 +2848,7 @@ static void vm_domain_remove_one_dev_info(struct dmar_domain *domain, | |||
2820 | spin_lock_irqsave(&domain->iommu_lock, tmp_flags); | 2848 | spin_lock_irqsave(&domain->iommu_lock, tmp_flags); |
2821 | clear_bit(iommu->seq_id, &domain->iommu_bmp); | 2849 | clear_bit(iommu->seq_id, &domain->iommu_bmp); |
2822 | domain->iommu_count--; | 2850 | domain->iommu_count--; |
2823 | domain_update_iommu_coherency(domain); | 2851 | domain_update_iommu_cap(domain); |
2824 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); | 2852 | spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags); |
2825 | } | 2853 | } |
2826 | 2854 | ||
@@ -2848,13 +2876,13 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain) | |||
2848 | iommu_detach_dev(iommu, info->bus, info->devfn); | 2876 | iommu_detach_dev(iommu, info->bus, info->devfn); |
2849 | 2877 | ||
2850 | /* clear this iommu in iommu_bmp, update iommu count | 2878 | /* clear this iommu in iommu_bmp, update iommu count |
2851 | * and coherency | 2879 | * and capabilities |
2852 | */ | 2880 | */ |
2853 | spin_lock_irqsave(&domain->iommu_lock, flags2); | 2881 | spin_lock_irqsave(&domain->iommu_lock, flags2); |
2854 | if (test_and_clear_bit(iommu->seq_id, | 2882 | if (test_and_clear_bit(iommu->seq_id, |
2855 | &domain->iommu_bmp)) { | 2883 | &domain->iommu_bmp)) { |
2856 | domain->iommu_count--; | 2884 | domain->iommu_count--; |
2857 | domain_update_iommu_coherency(domain); | 2885 | domain_update_iommu_cap(domain); |
2858 | } | 2886 | } |
2859 | spin_unlock_irqrestore(&domain->iommu_lock, flags2); | 2887 | spin_unlock_irqrestore(&domain->iommu_lock, flags2); |
2860 | 2888 | ||