Merge "iommu/arm-smmu: support mapping before enabling S1 translations"
This commit is contained in:
commit
24eb8e0963
3 changed files with 52 additions and 1 deletions
|
@ -528,6 +528,8 @@ static bool arm_smmu_is_static_cb(struct arm_smmu_device *smmu);
|
||||||
static bool arm_smmu_is_slave_side_secure(struct arm_smmu_domain *smmu_domain);
|
static bool arm_smmu_is_slave_side_secure(struct arm_smmu_domain *smmu_domain);
|
||||||
static bool arm_smmu_has_secure_vmid(struct arm_smmu_domain *smmu_domain);
|
static bool arm_smmu_has_secure_vmid(struct arm_smmu_domain *smmu_domain);
|
||||||
|
|
||||||
|
static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain);
|
||||||
|
|
||||||
static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
|
static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
|
||||||
{
|
{
|
||||||
return container_of(dom, struct arm_smmu_domain, domain);
|
return container_of(dom, struct arm_smmu_domain, domain);
|
||||||
|
@ -1604,7 +1606,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
|
||||||
/* SCTLR */
|
/* SCTLR */
|
||||||
reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_EAE_SBOP;
|
reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_EAE_SBOP;
|
||||||
|
|
||||||
if (!(smmu_domain->attributes & (1 << DOMAIN_ATTR_S1_BYPASS)) ||
|
if ((!(smmu_domain->attributes & (1 << DOMAIN_ATTR_S1_BYPASS)) &&
|
||||||
|
!(smmu_domain->attributes & (1 << DOMAIN_ATTR_EARLY_MAP))) ||
|
||||||
!stage1)
|
!stage1)
|
||||||
reg |= SCTLR_M;
|
reg |= SCTLR_M;
|
||||||
if (stage1)
|
if (stage1)
|
||||||
|
@ -3043,6 +3046,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DOMAIN_ATTR_EARLY_MAP:
|
||||||
|
*((int *)data) = !!(smmu_domain->attributes
|
||||||
|
& (1 << DOMAIN_ATTR_EARLY_MAP));
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
break;
|
break;
|
||||||
|
@ -3148,6 +3156,24 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
|
||||||
smmu_domain->attributes |= 1 << DOMAIN_ATTR_FAST;
|
smmu_domain->attributes |= 1 << DOMAIN_ATTR_FAST;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
case DOMAIN_ATTR_EARLY_MAP: {
|
||||||
|
int early_map = *((int *)data);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if (early_map) {
|
||||||
|
smmu_domain->attributes |=
|
||||||
|
1 << DOMAIN_ATTR_EARLY_MAP;
|
||||||
|
} else {
|
||||||
|
if (smmu_domain->smmu)
|
||||||
|
ret = arm_smmu_enable_s1_translations(
|
||||||
|
smmu_domain);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
smmu_domain->attributes &=
|
||||||
|
~(1 << DOMAIN_ATTR_EARLY_MAP);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
break;
|
break;
|
||||||
|
@ -3158,6 +3184,28 @@ out_unlock:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain)
|
||||||
|
{
|
||||||
|
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
|
||||||
|
struct arm_smmu_device *smmu = smmu_domain->smmu;
|
||||||
|
void __iomem *cb_base;
|
||||||
|
u32 reg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
|
||||||
|
ret = arm_smmu_enable_clocks(smmu);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
reg = readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR);
|
||||||
|
reg |= SCTLR_M;
|
||||||
|
|
||||||
|
writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR);
|
||||||
|
arm_smmu_disable_clocks(smmu);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int arm_smmu_dma_supported(struct iommu_domain *domain,
|
static int arm_smmu_dma_supported(struct iommu_domain *domain,
|
||||||
struct device *dev, u64 mask)
|
struct device *dev, u64 mask)
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,6 +70,8 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr)
|
||||||
return "DOMAIN_ATTR_S1_BYPASS";
|
return "DOMAIN_ATTR_S1_BYPASS";
|
||||||
case DOMAIN_ATTR_FAST:
|
case DOMAIN_ATTR_FAST:
|
||||||
return "DOMAIN_ATTR_FAST";
|
return "DOMAIN_ATTR_FAST";
|
||||||
|
case DOMAIN_ATTR_EARLY_MAP:
|
||||||
|
return "DOMAIN_ATTR_EARLY_MAP";
|
||||||
default:
|
default:
|
||||||
return "Unknown attr!";
|
return "Unknown attr!";
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,7 @@ enum iommu_attr {
|
||||||
DOMAIN_ATTR_S1_BYPASS,
|
DOMAIN_ATTR_S1_BYPASS,
|
||||||
DOMAIN_ATTR_FAST,
|
DOMAIN_ATTR_FAST,
|
||||||
DOMAIN_ATTR_PGTBL_INFO,
|
DOMAIN_ATTR_PGTBL_INFO,
|
||||||
|
DOMAIN_ATTR_EARLY_MAP,
|
||||||
DOMAIN_ATTR_MAX,
|
DOMAIN_ATTR_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue