aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/dmar.c
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-11-09 09:47:57 -0500
committerJoerg Roedel <jroedel@suse.de>2014-11-18 05:18:35 -0500
commit78d8e7046111425bb688cddc4303d79cb0f0d281 (patch)
tree5d3be87a35920d72efaf7100406c7058a3295f1e /drivers/iommu/dmar.c
parentc2a0b538d2c778aef7bf2fbe7973229192c9a392 (diff)
iommu/vt-d: Dynamically allocate and free seq_id for DMAR units
Introduce functions to support dynamic IOMMU seq_id allocating and releasing, which will be used to support DMAR hotplug. Also rename IOMMU_UNITS_SUPPORTED as DMAR_UNITS_SUPPORTED. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Reviewed-by: Yijing Wang <wangyijing@huawei.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/dmar.c')
-rw-r--r--drivers/iommu/dmar.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 586dd2aa2ca2..78aa1b2af113 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -70,6 +70,7 @@ LIST_HEAD(dmar_drhd_units);
70struct acpi_table_header * __initdata dmar_tbl; 70struct acpi_table_header * __initdata dmar_tbl;
71static acpi_size dmar_tbl_size; 71static acpi_size dmar_tbl_size;
72static int dmar_dev_scope_status = 1; 72static int dmar_dev_scope_status = 1;
73static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)];
73 74
74static int alloc_iommu(struct dmar_drhd_unit *drhd); 75static int alloc_iommu(struct dmar_drhd_unit *drhd);
75static void free_iommu(struct intel_iommu *iommu); 76static void free_iommu(struct intel_iommu *iommu);
@@ -944,11 +945,32 @@ out:
944 return err; 945 return err;
945} 946}
946 947
948static int dmar_alloc_seq_id(struct intel_iommu *iommu)
949{
950 iommu->seq_id = find_first_zero_bit(dmar_seq_ids,
951 DMAR_UNITS_SUPPORTED);
952 if (iommu->seq_id >= DMAR_UNITS_SUPPORTED) {
953 iommu->seq_id = -1;
954 } else {
955 set_bit(iommu->seq_id, dmar_seq_ids);
956 sprintf(iommu->name, "dmar%d", iommu->seq_id);
957 }
958
959 return iommu->seq_id;
960}
961
962static void dmar_free_seq_id(struct intel_iommu *iommu)
963{
964 if (iommu->seq_id >= 0) {
965 clear_bit(iommu->seq_id, dmar_seq_ids);
966 iommu->seq_id = -1;
967 }
968}
969
947static int alloc_iommu(struct dmar_drhd_unit *drhd) 970static int alloc_iommu(struct dmar_drhd_unit *drhd)
948{ 971{
949 struct intel_iommu *iommu; 972 struct intel_iommu *iommu;
950 u32 ver, sts; 973 u32 ver, sts;
951 static int iommu_allocated = 0;
952 int agaw = 0; 974 int agaw = 0;
953 int msagaw = 0; 975 int msagaw = 0;
954 int err; 976 int err;
@@ -962,13 +984,16 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
962 if (!iommu) 984 if (!iommu)
963 return -ENOMEM; 985 return -ENOMEM;
964 986
965 iommu->seq_id = iommu_allocated++; 987 if (dmar_alloc_seq_id(iommu) < 0) {
966 sprintf (iommu->name, "dmar%d", iommu->seq_id); 988 pr_err("IOMMU: failed to allocate seq_id\n");
989 err = -ENOSPC;
990 goto error;
991 }
967 992
968 err = map_iommu(iommu, drhd->reg_base_addr); 993 err = map_iommu(iommu, drhd->reg_base_addr);
969 if (err) { 994 if (err) {
970 pr_err("IOMMU: failed to map %s\n", iommu->name); 995 pr_err("IOMMU: failed to map %s\n", iommu->name);
971 goto error; 996 goto error_free_seq_id;
972 } 997 }
973 998
974 err = -EINVAL; 999 err = -EINVAL;
@@ -1018,9 +1043,11 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
1018 1043
1019 return 0; 1044 return 0;
1020 1045
1021 err_unmap: 1046err_unmap:
1022 unmap_iommu(iommu); 1047 unmap_iommu(iommu);
1023 error: 1048error_free_seq_id:
1049 dmar_free_seq_id(iommu);
1050error:
1024 kfree(iommu); 1051 kfree(iommu);
1025 return err; 1052 return err;
1026} 1053}
@@ -1044,6 +1071,7 @@ static void free_iommu(struct intel_iommu *iommu)
1044 if (iommu->reg) 1071 if (iommu->reg)
1045 unmap_iommu(iommu); 1072 unmap_iommu(iommu);
1046 1073
1074 dmar_free_seq_id(iommu);
1047 kfree(iommu); 1075 kfree(iommu);
1048} 1076}
1049 1077