Loading drivers/iommu/arm-smmu.c +49 −1 Original line number Diff line number Diff line Loading @@ -511,6 +511,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_has_secure_vmid(struct arm_smmu_domain *smmu_domain); static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain); static void parse_driver_options(struct arm_smmu_device *smmu) { int i = 0; Loading Loading @@ -1486,7 +1488,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, /* SCTLR */ 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) reg |= SCTLR_M; if (stage1) Loading Loading @@ -2908,6 +2911,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, ret = 0; break; } case DOMAIN_ATTR_EARLY_MAP: *((int *)data) = !!(smmu_domain->attributes & (1 << DOMAIN_ATTR_EARLY_MAP)); ret = 0; break; default: ret = -ENODEV; break; Loading Loading @@ -3036,6 +3044,24 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain, smmu_domain->attributes |= 1 << DOMAIN_ATTR_FAST; ret = 0; 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: ret = -ENODEV; break; Loading @@ -3046,6 +3072,28 @@ out_unlock: 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, struct device *dev, u64 mask) { Loading drivers/iommu/iommu-debug.c +2 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,8 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr) return "DOMAIN_ATTR_S1_BYPASS"; case DOMAIN_ATTR_FAST: return "DOMAIN_ATTR_FAST"; case DOMAIN_ATTR_EARLY_MAP: return "DOMAIN_ATTR_EARLY_MAP"; default: return "Unknown attr!"; } Loading include/linux/iommu.h +1 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ enum iommu_attr { DOMAIN_ATTR_S1_BYPASS, DOMAIN_ATTR_FAST, DOMAIN_ATTR_PGTBL_INFO, DOMAIN_ATTR_EARLY_MAP, DOMAIN_ATTR_MAX, }; Loading Loading
drivers/iommu/arm-smmu.c +49 −1 Original line number Diff line number Diff line Loading @@ -511,6 +511,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_has_secure_vmid(struct arm_smmu_domain *smmu_domain); static int arm_smmu_enable_s1_translations(struct arm_smmu_domain *smmu_domain); static void parse_driver_options(struct arm_smmu_device *smmu) { int i = 0; Loading Loading @@ -1486,7 +1488,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, /* SCTLR */ 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) reg |= SCTLR_M; if (stage1) Loading Loading @@ -2908,6 +2911,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain, ret = 0; break; } case DOMAIN_ATTR_EARLY_MAP: *((int *)data) = !!(smmu_domain->attributes & (1 << DOMAIN_ATTR_EARLY_MAP)); ret = 0; break; default: ret = -ENODEV; break; Loading Loading @@ -3036,6 +3044,24 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain, smmu_domain->attributes |= 1 << DOMAIN_ATTR_FAST; ret = 0; 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: ret = -ENODEV; break; Loading @@ -3046,6 +3072,28 @@ out_unlock: 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, struct device *dev, u64 mask) { Loading
drivers/iommu/iommu-debug.c +2 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,8 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr) return "DOMAIN_ATTR_S1_BYPASS"; case DOMAIN_ATTR_FAST: return "DOMAIN_ATTR_FAST"; case DOMAIN_ATTR_EARLY_MAP: return "DOMAIN_ATTR_EARLY_MAP"; default: return "Unknown attr!"; } Loading
include/linux/iommu.h +1 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ enum iommu_attr { DOMAIN_ATTR_S1_BYPASS, DOMAIN_ATTR_FAST, DOMAIN_ATTR_PGTBL_INFO, DOMAIN_ATTR_EARLY_MAP, DOMAIN_ATTR_MAX, }; Loading