From a557aff0c72b62e5ca859eab376f932d24e36cea Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Wed, 15 Jan 2020 13:52:32 +0100 Subject: iommu/arm-smmu-v3: Add context descriptor tables allocators Support for SSID will require allocating context descriptor tables. Move the context descriptor allocation to separate functions. Signed-off-by: Jean-Philippe Brucker Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu-v3.c | 47 ++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 17231374eda6..3f7248d98e72 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -552,11 +552,13 @@ struct arm_smmu_ctx_desc { struct arm_smmu_ctx_desc_cfg { __le64 *cdtab; dma_addr_t cdtab_dma; + unsigned int num_l1_ents; }; struct arm_smmu_s1_cfg { struct arm_smmu_ctx_desc_cfg cdcfg; struct arm_smmu_ctx_desc cd; + u8 s1cdmax; }; struct arm_smmu_s2_cfg { @@ -1475,6 +1477,35 @@ static void arm_smmu_write_ctx_desc(struct arm_smmu_device *smmu, cdptr[3] = cpu_to_le64(cfg->cd.mair); } +static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain) +{ + size_t l1size; + struct arm_smmu_device *smmu = smmu_domain->smmu; + struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; + struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg; + + cdcfg->num_l1_ents = 1UL << cfg->s1cdmax; + l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3); + cdcfg->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cdcfg->cdtab_dma, + GFP_KERNEL); + if (!cdcfg->cdtab) { + dev_warn(smmu->dev, "failed to allocate context descriptor\n"); + return -ENOMEM; + } + return 0; +} + +static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain) +{ + struct arm_smmu_device *smmu = smmu_domain->smmu; + struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg; + size_t l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3); + + dmam_free_coherent(smmu->dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma); + cdcfg->cdtab_dma = 0; + cdcfg->cdtab = NULL; +} + /* Stream table manipulation functions */ static void arm_smmu_write_strtab_l1_desc(__le64 *dst, struct arm_smmu_strtab_l1_desc *desc) @@ -2118,11 +2149,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain) struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; if (cfg->cdcfg.cdtab) { - dmam_free_coherent(smmu_domain->smmu->dev, - CTXDESC_CD_DWORDS << 3, - cfg->cdcfg.cdtab, - cfg->cdcfg.cdtab_dma); - + arm_smmu_free_cd_tables(smmu_domain); arm_smmu_bitmap_free(smmu->asid_map, cfg->cd.asid); } } else { @@ -2147,15 +2174,9 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, if (asid < 0) return asid; - cfg->cdcfg.cdtab = dmam_alloc_coherent(smmu->dev, - CTXDESC_CD_DWORDS << 3, - &cfg->cdcfg.cdtab_dma, - GFP_KERNEL); - if (!cfg->cdcfg.cdtab) { - dev_warn(smmu->dev, "failed to allocate context descriptor\n"); - ret = -ENOMEM; + ret = arm_smmu_alloc_cd_tables(smmu_domain); + if (ret) goto out_free_asid; - } cfg->cd.asid = (u16)asid; cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; -- cgit