diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2014-11-09 09:47:57 -0500 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2014-11-18 05:18:35 -0500 |
commit | 78d8e7046111425bb688cddc4303d79cb0f0d281 (patch) | |
tree | 5d3be87a35920d72efaf7100406c7058a3295f1e /drivers/iommu/dmar.c | |
parent | c2a0b538d2c778aef7bf2fbe7973229192c9a392 (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.c | 40 |
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); | |||
70 | struct acpi_table_header * __initdata dmar_tbl; | 70 | struct acpi_table_header * __initdata dmar_tbl; |
71 | static acpi_size dmar_tbl_size; | 71 | static acpi_size dmar_tbl_size; |
72 | static int dmar_dev_scope_status = 1; | 72 | static int dmar_dev_scope_status = 1; |
73 | static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)]; | ||
73 | 74 | ||
74 | static int alloc_iommu(struct dmar_drhd_unit *drhd); | 75 | static int alloc_iommu(struct dmar_drhd_unit *drhd); |
75 | static void free_iommu(struct intel_iommu *iommu); | 76 | static void free_iommu(struct intel_iommu *iommu); |
@@ -944,11 +945,32 @@ out: | |||
944 | return err; | 945 | return err; |
945 | } | 946 | } |
946 | 947 | ||
948 | static 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 | |||
962 | static 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 | |||
947 | static int alloc_iommu(struct dmar_drhd_unit *drhd) | 970 | static 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: | 1046 | err_unmap: |
1022 | unmap_iommu(iommu); | 1047 | unmap_iommu(iommu); |
1023 | error: | 1048 | error_free_seq_id: |
1049 | dmar_free_seq_id(iommu); | ||
1050 | error: | ||
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 | ||