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

Commit 1b573683 authored by Weidong Han's avatar Weidong Han Committed by Joerg Roedel
Browse files

calculate agaw for each iommu



"SAGAW" capability may be different across iommus. Use a default agaw, but if default agaw is not supported in some iommus, choose a less supported agaw.

Signed-off-by: default avatarWeidong Han <weidong.han@intel.com>
Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent 8c11e798
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -491,6 +491,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
	int map_size;
	u32 ver;
	static int iommu_allocated = 0;
	int agaw;

	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
	if (!iommu)
@@ -506,6 +507,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
	iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
	iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);

	agaw = iommu_calculate_agaw(iommu);
	if (agaw < 0) {
		printk(KERN_ERR
			"Cannot get a valid agaw for iommu (seq_id = %d)\n",
			iommu->seq_id);
		goto error;
	}
	iommu->agaw = agaw;

	/* the registers might be more than one page */
	map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
		cap_max_fault_reg_offset(iommu->cap));
+22 −0
Original line number Diff line number Diff line
@@ -362,6 +362,28 @@ void free_iova_mem(struct iova *iova)
	kmem_cache_free(iommu_iova_cache, iova);
}


static inline int width_to_agaw(int width);

/* calculate agaw for each iommu.
 * "SAGAW" may be different across iommus, use a default agaw, and
 * get a supported less agaw for iommus that don't support the default agaw.
 */
int iommu_calculate_agaw(struct intel_iommu *iommu)
{
	unsigned long sagaw;
	int agaw = -1;

	sagaw = cap_sagaw(iommu->cap);
	for (agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
	     agaw >= 0; agaw--) {
		if (test_bit(agaw, &sagaw))
			break;
	}

	return agaw;
}

/* in native case, each domain is related to only one iommu */
static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
{
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ struct dmar_domain;
struct root_entry;

extern void free_dmar_iommu(struct intel_iommu *iommu);
extern int iommu_calculate_agaw(struct intel_iommu *iommu);

extern int dmar_disabled;

+1 −0
Original line number Diff line number Diff line
@@ -290,6 +290,7 @@ struct intel_iommu {
	u32		gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
	spinlock_t	register_lock; /* protect register handling */
	int		seq_id;	/* sequence id of the iommu */
	int		agaw; /* agaw of this iommu */

#ifdef CONFIG_DMAR
	unsigned long 	*domain_ids; /* bitmap of domains */