Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78d8e704 authored by Jiang Liu's avatar Jiang Liu Committed by Joerg Roedel
Browse files

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: default avatarJiang Liu <jiang.liu@linux.intel.com>
Reviewed-by: default avatarYijing Wang <wangyijing@huawei.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent c2a0b538
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ LIST_HEAD(dmar_drhd_units);
struct acpi_table_header * __initdata dmar_tbl;
static acpi_size dmar_tbl_size;
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 void free_iommu(struct intel_iommu *iommu);
@@ -944,11 +945,32 @@ static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
	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)
{
	struct intel_iommu *iommu;
	u32 ver, sts;
	static int iommu_allocated = 0;
	int agaw = 0;
	int msagaw = 0;
	int err;
@@ -962,13 +984,16 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
	if (!iommu)
		return -ENOMEM;

	iommu->seq_id = iommu_allocated++;
	sprintf (iommu->name, "dmar%d", iommu->seq_id);
	if (dmar_alloc_seq_id(iommu) < 0) {
		pr_err("IOMMU: failed to allocate seq_id\n");
		err = -ENOSPC;
		goto error;
	}

	err = map_iommu(iommu, drhd->reg_base_addr);
	if (err) {
		pr_err("IOMMU: failed to map %s\n", iommu->name);
		goto error;
		goto error_free_seq_id;
	}

	err = -EINVAL;
@@ -1020,6 +1045,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)

err_unmap:
	unmap_iommu(iommu);
error_free_seq_id:
	dmar_free_seq_id(iommu);
error:
	kfree(iommu);
	return err;
@@ -1044,6 +1071,7 @@ static void free_iommu(struct intel_iommu *iommu)
	if (iommu->reg)
		unmap_iommu(iommu);

	dmar_free_seq_id(iommu);
	kfree(iommu);
}

+3 −10
Original line number Diff line number Diff line
@@ -330,17 +330,10 @@ static int hw_pass_through = 1;
/* si_domain contains mulitple devices */
#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 {
	int	id;			/* domain 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*/

	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
		 * only
		 */
		if (g_num_of_iommus < IOMMU_UNITS_SUPPORTED) {
		if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
			g_num_of_iommus++;
			continue;
		}
		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 *),
+6 −0
Original line number Diff line number Diff line
@@ -30,6 +30,12 @@

struct acpi_dmar_header;

#ifdef	CONFIG_X86
# define	DMAR_UNITS_SUPPORTED	MAX_IO_APICS
#else
# define	DMAR_UNITS_SUPPORTED	64
#endif

/* DMAR Flags */
#define DMAR_INTR_REMAP		0x1
#define DMAR_X2APIC_OPT_OUT	0x2