mirror of
https://github.com/torvalds/linux.git
synced 2024-12-12 06:02:38 +00:00
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:
parent
c2a0b538d2
commit
78d8e70461
@ -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;
|
||||||
@ -1020,6 +1045,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
|
|||||||
|
|
||||||
err_unmap:
|
err_unmap:
|
||||||
unmap_iommu(iommu);
|
unmap_iommu(iommu);
|
||||||
|
error_free_seq_id:
|
||||||
|
dmar_free_seq_id(iommu);
|
||||||
error:
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 *),
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user