Message ID | 20191001220205.6423-5-kholk11@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add support for QCOM IOMMU v2 and 500 | expand |
On 01/10/2019 23:02, kholk11@gmail.com wrote: > From: AngeloGioacchino Del Regno <kholk11@gmail.com> > > To avoid context faults reset the context entirely on detach and > to ensure a fresh clean start also do a complete reset before > programming the context for domain initialization. > > Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com> > --- > drivers/iommu/qcom_iommu.c | 23 +++++++++++++++++++++-- > 1 file changed, 21 insertions(+), 2 deletions(-) > > diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c > index c8957ec83b92..b4a38ef129e3 100644 > --- a/drivers/iommu/qcom_iommu.c > +++ b/drivers/iommu/qcom_iommu.c > @@ -220,6 +220,23 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev) > return IRQ_HANDLED; > } > > +static void qcom_iommu_reset_ctx(struct qcom_iommu_ctx *ctx) > +{ > + iommu_writel(ctx, ARM_SMMU_CB_FAR, 0); > + iommu_writel(ctx, ARM_SMMU_CB_FSR, 0); > + iommu_writel(ctx, ARM_SMMU_CB_S1_MAIR1, 0); > + iommu_writel(ctx, ARM_SMMU_CB_PAR, 0); > + iommu_writel(ctx, ARM_SMMU_CB_S1_MAIR0, 0); > + iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0); > + iommu_writel(ctx, ARM_SMMU_CB_TCR2, 0); > + iommu_writel(ctx, ARM_SMMU_CB_TCR, 0); > + iommu_writeq(ctx, ARM_SMMU_CB_TTBR0, 0); > + iommu_writeq(ctx, ARM_SMMU_CB_TTBR1, 0); > + > + /* Should we issue a TLBSYNC there instead? */ Unless there are outstanding TLB invalidations, it wouldn't achieve much. That said, doing a TBLIALL as part of the reset sequence *would* generally be a good idea. Also, since the write to SCTLR affects the overall enable state of the context bank, it would be best to do that before touching anything else. Robin. > + mb(); > +} > + > static int qcom_iommu_init_domain(struct iommu_domain *domain, > struct qcom_iommu_dev *qcom_iommu, > struct iommu_fwspec *fwspec) > @@ -267,6 +284,8 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, > ctx->secure_init = true; > } > > + qcom_iommu_reset_ctx(ctx); > + > /* TCR */ > iommu_writel(ctx, ARM_SMMU_CB_TCR2, > (pgtbl_cfg.arm_lpae_s1_cfg.tcr >> 32) | > @@ -412,8 +431,8 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de > for (i = 0; i < fwspec->num_ids; i++) { > struct qcom_iommu_ctx *ctx = to_ctx(fwspec, fwspec->ids[i]); > > - /* Disable the context bank: */ > - iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0); > + /* Disable and reset the context bank */ > + qcom_iommu_reset_ctx(ctx); > > ctx->domain = NULL; > } >
diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index c8957ec83b92..b4a38ef129e3 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -220,6 +220,23 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev) return IRQ_HANDLED; } +static void qcom_iommu_reset_ctx(struct qcom_iommu_ctx *ctx) +{ + iommu_writel(ctx, ARM_SMMU_CB_FAR, 0); + iommu_writel(ctx, ARM_SMMU_CB_FSR, 0); + iommu_writel(ctx, ARM_SMMU_CB_S1_MAIR1, 0); + iommu_writel(ctx, ARM_SMMU_CB_PAR, 0); + iommu_writel(ctx, ARM_SMMU_CB_S1_MAIR0, 0); + iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0); + iommu_writel(ctx, ARM_SMMU_CB_TCR2, 0); + iommu_writel(ctx, ARM_SMMU_CB_TCR, 0); + iommu_writeq(ctx, ARM_SMMU_CB_TTBR0, 0); + iommu_writeq(ctx, ARM_SMMU_CB_TTBR1, 0); + + /* Should we issue a TLBSYNC there instead? */ + mb(); +} + static int qcom_iommu_init_domain(struct iommu_domain *domain, struct qcom_iommu_dev *qcom_iommu, struct iommu_fwspec *fwspec) @@ -267,6 +284,8 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, ctx->secure_init = true; } + qcom_iommu_reset_ctx(ctx); + /* TCR */ iommu_writel(ctx, ARM_SMMU_CB_TCR2, (pgtbl_cfg.arm_lpae_s1_cfg.tcr >> 32) | @@ -412,8 +431,8 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de for (i = 0; i < fwspec->num_ids; i++) { struct qcom_iommu_ctx *ctx = to_ctx(fwspec, fwspec->ids[i]); - /* Disable the context bank: */ - iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0); + /* Disable and reset the context bank */ + qcom_iommu_reset_ctx(ctx); ctx->domain = NULL; }