On Tue 01 Sep 11:46 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse <jcro...@codeaurora.org>
> 
> Do a bit of prep work to add the upcoming adreno-smmu implementation.
> 
> Add an hook to allow the implementation to choose which context banks
> to allocate.
> 
> Move some of the common structs to arm-smmu.h in anticipation of them
> being used by the implementations and update some of the existing hooks
> to pass more information that the implementation will need.
> 
> These modifications will be used by the upcoming Adreno SMMU
> implementation to identify the GPU device and properly configure it
> for pagetable switching.
> 
> Co-developed-by: Rob Clark <robdcl...@chromium.org>
> Signed-off-by: Jordan Crouse <jcro...@codeaurora.org>
> Signed-off-by: Rob Clark <robdcl...@chromium.org>

As I built the handoff support on top of this patch I ended up
reworking the alloc_context_bank() prototype to something I found a
little bit cleaner.

So perhaps you would be interested in squashing
https://lore.kernel.org/linux-arm-msm/20200904155513.282067-2-bjorn.anders...@linaro.org/
into this patch?

Otherwise, feel free to add my:

Reviewed-by: Bjorn Andersson <bjorn.anders...@linaro.org>

Regards,
Bjorn

> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-impl.c |  2 +-
>  drivers/iommu/arm/arm-smmu/arm-smmu.c      | 69 ++++++----------------
>  drivers/iommu/arm/arm-smmu/arm-smmu.h      | 51 +++++++++++++++-
>  3 files changed, 68 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> index a9861dcd0884..88f17cc33023 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> @@ -69,7 +69,7 @@ static int cavium_cfg_probe(struct arm_smmu_device *smmu)
>  }
>  
>  static int cavium_init_context(struct arm_smmu_domain *smmu_domain,
> -             struct io_pgtable_cfg *pgtbl_cfg)
> +             struct io_pgtable_cfg *pgtbl_cfg, struct device *dev)
>  {
>       struct cavium_smmu *cs = container_of(smmu_domain->smmu,
>                                             struct cavium_smmu, smmu);
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 8e884e58f208..68b7b9e6140e 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -65,41 +65,10 @@ module_param(disable_bypass, bool, S_IRUGO);
>  MODULE_PARM_DESC(disable_bypass,
>       "Disable bypass streams such that incoming transactions from devices 
> that are not attached to an iommu domain will report an abort back to the 
> device and will not be allowed to pass through the SMMU.");
>  
> -struct arm_smmu_s2cr {
> -     struct iommu_group              *group;
> -     int                             count;
> -     enum arm_smmu_s2cr_type         type;
> -     enum arm_smmu_s2cr_privcfg      privcfg;
> -     u8                              cbndx;
> -};
> -
>  #define s2cr_init_val (struct arm_smmu_s2cr){                                
> \
>       .type = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS,    \
>  }
>  
> -struct arm_smmu_smr {
> -     u16                             mask;
> -     u16                             id;
> -     bool                            valid;
> -};
> -
> -struct arm_smmu_cb {
> -     u64                             ttbr[2];
> -     u32                             tcr[2];
> -     u32                             mair[2];
> -     struct arm_smmu_cfg             *cfg;
> -};
> -
> -struct arm_smmu_master_cfg {
> -     struct arm_smmu_device          *smmu;
> -     s16                             smendx[];
> -};
> -#define INVALID_SMENDX                       -1
> -#define cfg_smendx(cfg, fw, i) \
> -     (i >= fw->num_ids ? INVALID_SMENDX : cfg->smendx[i])
> -#define for_each_cfg_sme(cfg, fw, i, idx) \
> -     for (i = 0; idx = cfg_smendx(cfg, fw, i), i < fw->num_ids; ++i)
> -
>  static bool using_legacy_binding, using_generic_binding;
>  
>  static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu)
> @@ -234,19 +203,6 @@ static int arm_smmu_register_legacy_master(struct device 
> *dev,
>  }
>  #endif /* CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS */
>  
> -static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end)
> -{
> -     int idx;
> -
> -     do {
> -             idx = find_next_zero_bit(map, end, start);
> -             if (idx == end)
> -                     return -ENOSPC;
> -     } while (test_and_set_bit(idx, map));
> -
> -     return idx;
> -}
> -
>  static void __arm_smmu_free_bitmap(unsigned long *map, int idx)
>  {
>       clear_bit(idx, map);
> @@ -578,7 +534,7 @@ static void arm_smmu_init_context_bank(struct 
> arm_smmu_domain *smmu_domain,
>       }
>  }
>  
> -static void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int 
> idx)
> +void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx)
>  {
>       u32 reg;
>       bool stage1;
> @@ -665,7 +621,8 @@ static void arm_smmu_write_context_bank(struct 
> arm_smmu_device *smmu, int idx)
>  }
>  
>  static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> -                                     struct arm_smmu_device *smmu)
> +                                     struct arm_smmu_device *smmu,
> +                                     struct device *dev)
>  {
>       int irq, start, ret = 0;
>       unsigned long ias, oas;
> @@ -780,10 +737,20 @@ static int arm_smmu_init_domain_context(struct 
> iommu_domain *domain,
>               ret = -EINVAL;
>               goto out_unlock;
>       }
> -     ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
> +
> +     smmu_domain->smmu = smmu;
> +
> +     if (smmu->impl && smmu->impl->alloc_context_bank)
> +             ret = smmu->impl->alloc_context_bank(smmu_domain, dev,
> +                             start, smmu->num_context_banks);
> +     else
> +             ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
>                                     smmu->num_context_banks);
> -     if (ret < 0)
> +
> +     if (ret < 0) {
> +             smmu_domain->smmu = NULL;
>               goto out_unlock;
> +     }
>  
>       cfg->cbndx = ret;
>       if (smmu->version < ARM_SMMU_V2) {
> @@ -798,8 +765,6 @@ static int arm_smmu_init_domain_context(struct 
> iommu_domain *domain,
>       else
>               cfg->asid = cfg->cbndx;
>  
> -     smmu_domain->smmu = smmu;
> -
>       pgtbl_cfg = (struct io_pgtable_cfg) {
>               .pgsize_bitmap  = smmu->pgsize_bitmap,
>               .ias            = ias,
> @@ -810,7 +775,7 @@ static int arm_smmu_init_domain_context(struct 
> iommu_domain *domain,
>       };
>  
>       if (smmu->impl && smmu->impl->init_context) {
> -             ret = smmu->impl->init_context(smmu_domain, &pgtbl_cfg);
> +             ret = smmu->impl->init_context(smmu_domain, &pgtbl_cfg, dev);
>               if (ret)
>                       goto out_clear_smmu;
>       }
> @@ -1194,7 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain 
> *domain, struct device *dev)
>               return ret;
>  
>       /* Ensure that the domain is finalised */
> -     ret = arm_smmu_init_domain_context(domain, smmu);
> +     ret = arm_smmu_init_domain_context(domain, smmu, dev);
>       if (ret < 0)
>               goto rpm_put;
>  
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index f3e456893f28..59ff3fc5c6c8 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -256,6 +256,21 @@ enum arm_smmu_implementation {
>       QCOM_SMMUV2,
>  };
>  
> +struct arm_smmu_s2cr {
> +     struct iommu_group              *group;
> +     int                             count;
> +     enum arm_smmu_s2cr_type         type;
> +     enum arm_smmu_s2cr_privcfg      privcfg;
> +     u8                              cbndx;
> +};
> +
> +struct arm_smmu_smr {
> +     u16                             mask;
> +     u16                             id;
> +     bool                            valid;
> +     bool                            pinned;
> +};
> +
>  struct arm_smmu_device {
>       struct device                   *dev;
>  
> @@ -331,6 +346,13 @@ struct arm_smmu_cfg {
>  };
>  #define ARM_SMMU_INVALID_IRPTNDX     0xff
>  
> +struct arm_smmu_cb {
> +     u64                             ttbr[2];
> +     u32                             tcr[2];
> +     u32                             mair[2];
> +     struct arm_smmu_cfg             *cfg;
> +};
> +
>  enum arm_smmu_domain_stage {
>       ARM_SMMU_DOMAIN_S1 = 0,
>       ARM_SMMU_DOMAIN_S2,
> @@ -350,6 +372,11 @@ struct arm_smmu_domain {
>       struct iommu_domain             domain;
>  };
>  
> +struct arm_smmu_master_cfg {
> +     struct arm_smmu_device          *smmu;
> +     s16                             smendx[];
> +};
> +
>  static inline u32 arm_smmu_lpae_tcr(struct io_pgtable_cfg *cfg)
>  {
>       u32 tcr = FIELD_PREP(ARM_SMMU_TCR_TG0, cfg->arm_lpae_s1_cfg.tcr.tg) |
> @@ -400,14 +427,35 @@ struct arm_smmu_impl {
>       int (*cfg_probe)(struct arm_smmu_device *smmu);
>       int (*reset)(struct arm_smmu_device *smmu);
>       int (*init_context)(struct arm_smmu_domain *smmu_domain,
> -                     struct io_pgtable_cfg *cfg);
> +                     struct io_pgtable_cfg *cfg, struct device *dev);
>       void (*tlb_sync)(struct arm_smmu_device *smmu, int page, int sync,
>                        int status);
>       int (*def_domain_type)(struct device *dev);
>       irqreturn_t (*global_fault)(int irq, void *dev);
>       irqreturn_t (*context_fault)(int irq, void *dev);
> +     int (*alloc_context_bank)(struct arm_smmu_domain *smmu_domain,
> +                     struct device *dev, int start, int max);
>  };
>  
> +#define INVALID_SMENDX                       -1
> +#define cfg_smendx(cfg, fw, i) \
> +     (i >= fw->num_ids ? INVALID_SMENDX : cfg->smendx[i])
> +#define for_each_cfg_sme(cfg, fw, i, idx) \
> +     for (i = 0; idx = cfg_smendx(cfg, fw, i), i < fw->num_ids; ++i)
> +
> +static inline int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int 
> end)
> +{
> +     int idx;
> +
> +     do {
> +             idx = find_next_zero_bit(map, end, start);
> +             if (idx == end)
> +                     return -ENOSPC;
> +     } while (test_and_set_bit(idx, map));
> +
> +     return idx;
> +}
> +
>  static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int 
> n)
>  {
>       return smmu->base + (n << smmu->pgshift);
> @@ -472,6 +520,7 @@ struct arm_smmu_device *arm_smmu_impl_init(struct 
> arm_smmu_device *smmu);
>  struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu);
>  struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu);
>  
> +void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx);
>  int arm_mmu500_reset(struct arm_smmu_device *smmu);
>  
>  #endif /* _ARM_SMMU_H */
> -- 
> 2.26.2
> 

Reply via email to