aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/intel-iommu.c
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2008-07-10 14:16:35 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-12 02:44:46 -0400
commite61d98d8dad0048619bb138b0ff996422ffae53b (patch)
treef31fe1610a082e0e12605db879ff56546ad971e5 /drivers/pci/intel-iommu.c
parent1ba89386db0a3f39590b90b5dd20d7149ae52de0 (diff)
x64, x2apic/intr-remap: Intel vt-d, IOMMU code reorganization
code reorganization of the generic Intel vt-d parsing related routines and linux iommu routines specific to Intel vt-d. drivers/pci/dmar.c now contains the generic vt-d parsing related routines drivers/pci/intel_iommu.c contains the iommu routines specific to vt-d Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: akpm@linux-foundation.org Cc: arjan@linux.intel.com Cc: andi@firstfloor.org Cc: ebiederm@xmission.com Cc: jbarnes@virtuousgeek.org Cc: steiner@sgi.com Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/pci/intel-iommu.c')
-rw-r--r--drivers/pci/intel-iommu.c92
1 files changed, 8 insertions, 84 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index bb0642318a95..1c0270d3e2e5 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -990,6 +990,8 @@ static int iommu_init_domains(struct intel_iommu *iommu)
990 return -ENOMEM; 990 return -ENOMEM;
991 } 991 }
992 992
993 spin_lock_init(&iommu->lock);
994
993 /* 995 /*
994 * if Caching mode is set, then invalid translations are tagged 996 * if Caching mode is set, then invalid translations are tagged
995 * with domainid 0. Hence we need to pre-allocate it. 997 * with domainid 0. Hence we need to pre-allocate it.
@@ -998,62 +1000,15 @@ static int iommu_init_domains(struct intel_iommu *iommu)
998 set_bit(0, iommu->domain_ids); 1000 set_bit(0, iommu->domain_ids);
999 return 0; 1001 return 0;
1000} 1002}
1001static struct intel_iommu *alloc_iommu(struct intel_iommu *iommu,
1002 struct dmar_drhd_unit *drhd)
1003{
1004 int ret;
1005 int map_size;
1006 u32 ver;
1007
1008 iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K);
1009 if (!iommu->reg) {
1010 printk(KERN_ERR "IOMMU: can't map the region\n");
1011 goto error;
1012 }
1013 iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
1014 iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
1015
1016 /* the registers might be more than one page */
1017 map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
1018 cap_max_fault_reg_offset(iommu->cap));
1019 map_size = PAGE_ALIGN_4K(map_size);
1020 if (map_size > PAGE_SIZE_4K) {
1021 iounmap(iommu->reg);
1022 iommu->reg = ioremap(drhd->reg_base_addr, map_size);
1023 if (!iommu->reg) {
1024 printk(KERN_ERR "IOMMU: can't map the region\n");
1025 goto error;
1026 }
1027 }
1028 1003
1029 ver = readl(iommu->reg + DMAR_VER_REG);
1030 pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n",
1031 drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver),
1032 iommu->cap, iommu->ecap);
1033 ret = iommu_init_domains(iommu);
1034 if (ret)
1035 goto error_unmap;
1036 spin_lock_init(&iommu->lock);
1037 spin_lock_init(&iommu->register_lock);
1038
1039 drhd->iommu = iommu;
1040 return iommu;
1041error_unmap:
1042 iounmap(iommu->reg);
1043error:
1044 kfree(iommu);
1045 return NULL;
1046}
1047 1004
1048static void domain_exit(struct dmar_domain *domain); 1005static void domain_exit(struct dmar_domain *domain);
1049static void free_iommu(struct intel_iommu *iommu) 1006
1007void free_dmar_iommu(struct intel_iommu *iommu)
1050{ 1008{
1051 struct dmar_domain *domain; 1009 struct dmar_domain *domain;
1052 int i; 1010 int i;
1053 1011
1054 if (!iommu)
1055 return;
1056
1057 i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); 1012 i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
1058 for (; i < cap_ndoms(iommu->cap); ) { 1013 for (; i < cap_ndoms(iommu->cap); ) {
1059 domain = iommu->domains[i]; 1014 domain = iommu->domains[i];
@@ -1078,10 +1033,6 @@ static void free_iommu(struct intel_iommu *iommu)
1078 1033
1079 /* free context mapping */ 1034 /* free context mapping */
1080 free_context_table(iommu); 1035 free_context_table(iommu);
1081
1082 if (iommu->reg)
1083 iounmap(iommu->reg);
1084 kfree(iommu);
1085} 1036}
1086 1037
1087static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu) 1038static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
@@ -1426,37 +1377,6 @@ find_domain(struct pci_dev *pdev)
1426 return NULL; 1377 return NULL;
1427} 1378}
1428 1379
1429static int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
1430 struct pci_dev *dev)
1431{
1432 int index;
1433
1434 while (dev) {
1435 for (index = 0; index < cnt; index++)
1436 if (dev == devices[index])
1437 return 1;
1438
1439 /* Check our parent */
1440 dev = dev->bus->self;
1441 }
1442
1443 return 0;
1444}
1445
1446static struct dmar_drhd_unit *
1447dmar_find_matched_drhd_unit(struct pci_dev *dev)
1448{
1449 struct dmar_drhd_unit *drhd = NULL;
1450
1451 list_for_each_entry(drhd, &dmar_drhd_units, list) {
1452 if (drhd->include_all || dmar_pci_device_match(drhd->devices,
1453 drhd->devices_cnt, dev))
1454 return drhd;
1455 }
1456
1457 return NULL;
1458}
1459
1460/* domain is initialized */ 1380/* domain is initialized */
1461static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) 1381static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
1462{ 1382{
@@ -1764,6 +1684,10 @@ int __init init_dmars(void)
1764 goto error; 1684 goto error;
1765 } 1685 }
1766 1686
1687 ret = iommu_init_domains(iommu);
1688 if (ret)
1689 goto error;
1690
1767 /* 1691 /*
1768 * TBD: 1692 * TBD:
1769 * we could share the same root & context tables 1693 * we could share the same root & context tables