aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/iommu/dmar.c40
-rw-r--r--drivers/iommu/intel-iommu.c13
-rw-r--r--include/linux/dmar.h6
3 files changed, 43 insertions, 16 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
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index b9cc9c2b03fc..2779354321f5 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -330,17 +330,10 @@ static int hw_pass_through = 1;
330/* si_domain contains mulitple devices */ 330/* si_domain contains mulitple devices */
331#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1) 331#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
332 332
333/* define the limit of IOMMUs supported in each domain */
334#ifdef CONFIG_X86
335# define IOMMU_UNITS_SUPPORTED MAX_IO_APICS
336#else
337# define IOMMU_UNITS_SUPPORTED 64
338#endif
339
340struct dmar_domain { 333struct dmar_domain {
341 int id; /* domain id */ 334 int id; /* domain id */
342 int nid; /* node id */ 335 int nid; /* node id */
343 DECLARE_BITMAP(iommu_bmp, IOMMU_UNITS_SUPPORTED); 336 DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED);
344 /* bitmap of iommus this domain uses*/ 337 /* bitmap of iommus this domain uses*/
345 338
346 struct list_head devices; /* all devices' list */ 339 struct list_head devices; /* all devices' list */
@@ -2730,12 +2723,12 @@ static int __init init_dmars(void)
2730 * threaded kernel __init code path all other access are read 2723 * threaded kernel __init code path all other access are read
2731 * only 2724 * only
2732 */ 2725 */
2733 if (g_num_of_iommus < IOMMU_UNITS_SUPPORTED) { 2726 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
2734 g_num_of_iommus++; 2727 g_num_of_iommus++;
2735 continue; 2728 continue;
2736 } 2729 }
2737 printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n", 2730 printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n",
2738 IOMMU_UNITS_SUPPORTED); 2731 DMAR_UNITS_SUPPORTED);
2739 } 2732 }
2740 2733
2741 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), 2734 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 495df5e48f80..725204fc433e 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -30,6 +30,12 @@
30 30
31struct acpi_dmar_header; 31struct acpi_dmar_header;
32 32
33#ifdef CONFIG_X86
34# define DMAR_UNITS_SUPPORTED MAX_IO_APICS
35#else
36# define DMAR_UNITS_SUPPORTED 64
37#endif
38
33/* DMAR Flags */ 39/* DMAR Flags */
34#define DMAR_INTR_REMAP 0x1 40#define DMAR_INTR_REMAP 0x1
35#define DMAR_X2APIC_OPT_OUT 0x2 41#define DMAR_X2APIC_OPT_OUT 0x2