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: Weidong Han <weidong.han@intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
parent
8c11e798ee
commit
1b5736839a
|
@ -491,6 +491,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
|
||||||
int map_size;
|
int map_size;
|
||||||
u32 ver;
|
u32 ver;
|
||||||
static int iommu_allocated = 0;
|
static int iommu_allocated = 0;
|
||||||
|
int agaw;
|
||||||
|
|
||||||
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
|
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
|
||||||
if (!iommu)
|
if (!iommu)
|
||||||
|
@ -506,6 +507,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
|
||||||
iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
|
iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
|
||||||
iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_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 */
|
/* the registers might be more than one page */
|
||||||
map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
|
map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
|
||||||
cap_max_fault_reg_offset(iommu->cap));
|
cap_max_fault_reg_offset(iommu->cap));
|
||||||
|
|
|
@ -362,6 +362,28 @@ void free_iova_mem(struct iova *iova)
|
||||||
kmem_cache_free(iommu_iova_cache, 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 */
|
/* in native case, each domain is related to only one iommu */
|
||||||
static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
|
static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,7 @@ struct dmar_domain;
|
||||||
struct root_entry;
|
struct root_entry;
|
||||||
|
|
||||||
extern void free_dmar_iommu(struct intel_iommu *iommu);
|
extern void free_dmar_iommu(struct intel_iommu *iommu);
|
||||||
|
extern int iommu_calculate_agaw(struct intel_iommu *iommu);
|
||||||
|
|
||||||
extern int dmar_disabled;
|
extern int dmar_disabled;
|
||||||
|
|
||||||
|
|
|
@ -290,6 +290,7 @@ struct intel_iommu {
|
||||||
u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
|
u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
|
||||||
spinlock_t register_lock; /* protect register handling */
|
spinlock_t register_lock; /* protect register handling */
|
||||||
int seq_id; /* sequence id of the iommu */
|
int seq_id; /* sequence id of the iommu */
|
||||||
|
int agaw; /* agaw of this iommu */
|
||||||
|
|
||||||
#ifdef CONFIG_DMAR
|
#ifdef CONFIG_DMAR
|
||||||
unsigned long *domain_ids; /* bitmap of domains */
|
unsigned long *domain_ids; /* bitmap of domains */
|
||||||
|
|
Loading…
Reference in New Issue