aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2009-03-18 03:33:05 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-03-24 05:42:43 -0400
commit58c610bd1a3f50820e45a7c09ec0e44d2cda15dd (patch)
tree696539e1e17fd7600222865fa331e9144737a58b /drivers/pci
parenta1e4ee22863d41a6fbb24310d7951836cb6dafe7 (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.c38
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 */
425static void domain_update_iommu_coherency(struct dmar_domain *domain) 425static 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
441static 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 */
458static void domain_update_iommu_cap(struct dmar_domain *domain)
459{
460 domain_update_iommu_coherency(domain);
461 domain_update_iommu_snooping(domain);
462}
463
441static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn) 464static 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