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>
This commit is contained in:
Jiang Liu 2014-11-09 22:47:57 +08:00 committed by Joerg Roedel
parent c2a0b538d2
commit 78d8e70461
3 changed files with 43 additions and 16 deletions

View File

@ -70,6 +70,7 @@ LIST_HEAD(dmar_drhd_units);
struct acpi_table_header * __initdata dmar_tbl; struct acpi_table_header * __initdata dmar_tbl;
static acpi_size dmar_tbl_size; static acpi_size dmar_tbl_size;
static int dmar_dev_scope_status = 1; static int dmar_dev_scope_status = 1;
static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)];
static int alloc_iommu(struct dmar_drhd_unit *drhd); static int alloc_iommu(struct dmar_drhd_unit *drhd);
static void free_iommu(struct intel_iommu *iommu); static void free_iommu(struct intel_iommu *iommu);
@ -944,11 +945,32 @@ out:
return err; return err;
} }
static int dmar_alloc_seq_id(struct intel_iommu *iommu)
{
iommu->seq_id = find_first_zero_bit(dmar_seq_ids,
DMAR_UNITS_SUPPORTED);
if (iommu->seq_id >= DMAR_UNITS_SUPPORTED) {
iommu->seq_id = -1;
} else {
set_bit(iommu->seq_id, dmar_seq_ids);
sprintf(iommu->name, "dmar%d", iommu->seq_id);
}
return iommu->seq_id;
}
static void dmar_free_seq_id(struct intel_iommu *iommu)
{
if (iommu->seq_id >= 0) {
clear_bit(iommu->seq_id, dmar_seq_ids);
iommu->seq_id = -1;
}
}
static int alloc_iommu(struct dmar_drhd_unit *drhd) static int alloc_iommu(struct dmar_drhd_unit *drhd)
{ {
struct intel_iommu *iommu; struct intel_iommu *iommu;
u32 ver, sts; u32 ver, sts;
static int iommu_allocated = 0;
int agaw = 0; int agaw = 0;
int msagaw = 0; int msagaw = 0;
int err; int err;
@ -962,13 +984,16 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
if (!iommu) if (!iommu)
return -ENOMEM; return -ENOMEM;
iommu->seq_id = iommu_allocated++; if (dmar_alloc_seq_id(iommu) < 0) {
sprintf (iommu->name, "dmar%d", iommu->seq_id); pr_err("IOMMU: failed to allocate seq_id\n");
err = -ENOSPC;
goto error;
}
err = map_iommu(iommu, drhd->reg_base_addr); err = map_iommu(iommu, drhd->reg_base_addr);
if (err) { if (err) {
pr_err("IOMMU: failed to map %s\n", iommu->name); pr_err("IOMMU: failed to map %s\n", iommu->name);
goto error; goto error_free_seq_id;
} }
err = -EINVAL; err = -EINVAL;
@ -1018,9 +1043,11 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
return 0; return 0;
err_unmap: err_unmap:
unmap_iommu(iommu); unmap_iommu(iommu);
error: error_free_seq_id:
dmar_free_seq_id(iommu);
error:
kfree(iommu); kfree(iommu);
return err; return err;
} }
@ -1044,6 +1071,7 @@ static void free_iommu(struct intel_iommu *iommu)
if (iommu->reg) if (iommu->reg)
unmap_iommu(iommu); unmap_iommu(iommu);
dmar_free_seq_id(iommu);
kfree(iommu); kfree(iommu);
} }

View File

@ -330,17 +330,10 @@ static int hw_pass_through = 1;
/* si_domain contains mulitple devices */ /* si_domain contains mulitple devices */
#define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1) #define DOMAIN_FLAG_STATIC_IDENTITY (1 << 1)
/* define the limit of IOMMUs supported in each domain */
#ifdef CONFIG_X86
# define IOMMU_UNITS_SUPPORTED MAX_IO_APICS
#else
# define IOMMU_UNITS_SUPPORTED 64
#endif
struct dmar_domain { struct dmar_domain {
int id; /* domain id */ int id; /* domain id */
int nid; /* node id */ int nid; /* node id */
DECLARE_BITMAP(iommu_bmp, IOMMU_UNITS_SUPPORTED); DECLARE_BITMAP(iommu_bmp, DMAR_UNITS_SUPPORTED);
/* bitmap of iommus this domain uses*/ /* bitmap of iommus this domain uses*/
struct list_head devices; /* all devices' list */ struct list_head devices; /* all devices' list */
@ -2730,12 +2723,12 @@ static int __init init_dmars(void)
* threaded kernel __init code path all other access are read * threaded kernel __init code path all other access are read
* only * only
*/ */
if (g_num_of_iommus < IOMMU_UNITS_SUPPORTED) { if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
g_num_of_iommus++; g_num_of_iommus++;
continue; continue;
} }
printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n", printk_once(KERN_ERR "intel-iommu: exceeded %d IOMMUs\n",
IOMMU_UNITS_SUPPORTED); DMAR_UNITS_SUPPORTED);
} }
g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),

View File

@ -30,6 +30,12 @@
struct acpi_dmar_header; struct acpi_dmar_header;
#ifdef CONFIG_X86
# define DMAR_UNITS_SUPPORTED MAX_IO_APICS
#else
# define DMAR_UNITS_SUPPORTED 64
#endif
/* DMAR Flags */ /* DMAR Flags */
#define DMAR_INTR_REMAP 0x1 #define DMAR_INTR_REMAP 0x1
#define DMAR_X2APIC_OPT_OUT 0x2 #define DMAR_X2APIC_OPT_OUT 0x2