lkml.org 
[lkml]   [2022]   [Aug]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3/5] iommu/arm-smmu-qcom: Add private interface to tlbinv by ASID
    Date
    From: Rob Clark <robdclark@chromium.org>

    This will let the drm driver use different ASID values for each set of
    pgtables to avoid over-invalidation on unmap.

    Signed-off-by: Rob Clark <robdclark@chromium.org>
    ---
    drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 1 +
    drivers/iommu/arm/arm-smmu/arm-smmu.c | 43 ++++++++++++++++++++--
    drivers/iommu/arm/arm-smmu/arm-smmu.h | 1 +
    include/linux/adreno-smmu-priv.h | 2 +
    4 files changed, 43 insertions(+), 4 deletions(-)

    diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
    index 59b460c1c9a5..3230348729ab 100644
    --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
    +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
    @@ -229,6 +229,7 @@ static int qcom_adreno_smmu_init_context(struct arm_smmu_domain *smmu_domain,
    priv->get_fault_info = qcom_adreno_smmu_get_fault_info;
    priv->set_stall = qcom_adreno_smmu_set_stall;
    priv->resume_translation = qcom_adreno_smmu_resume_translation;
    + priv->tlb_inv_by_id = arm_smmu_tlb_inv_by_id;

    return 0;
    }
    diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
    index 2ed3594f384e..624359bb2092 100644
    --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
    +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
    @@ -252,7 +252,7 @@ static void arm_smmu_tlb_sync_context(struct arm_smmu_domain *smmu_domain)
    spin_unlock_irqrestore(&smmu_domain->cb_lock, flags);
    }

    -static void arm_smmu_tlb_inv_context_s1(void *cookie)
    +static void arm_smmu_tlb_inv_context_s1_asid(void *cookie, u16 asid)
    {
    struct arm_smmu_domain *smmu_domain = cookie;
    /*
    @@ -261,21 +261,56 @@ static void arm_smmu_tlb_inv_context_s1(void *cookie)
    */
    wmb();
    arm_smmu_cb_write(smmu_domain->smmu, smmu_domain->cfg.cbndx,
    - ARM_SMMU_CB_S1_TLBIASID, smmu_domain->cfg.asid);
    + ARM_SMMU_CB_S1_TLBIASID, asid);
    arm_smmu_tlb_sync_context(smmu_domain);
    }

    -static void arm_smmu_tlb_inv_context_s2(void *cookie)
    +static void arm_smmu_tlb_inv_context_s1(void *cookie)
    +{
    + struct arm_smmu_domain *smmu_domain = cookie;
    +
    + arm_smmu_tlb_inv_context_s1_asid(cookie, smmu_domain->cfg.asid);
    +}
    +
    +static void arm_smmu_tlb_inv_context_s2_vmid(void *cookie, u16 vmid)
    {
    struct arm_smmu_domain *smmu_domain = cookie;
    struct arm_smmu_device *smmu = smmu_domain->smmu;

    /* See above */
    wmb();
    - arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_TLBIVMID, smmu_domain->cfg.vmid);
    + arm_smmu_gr0_write(smmu, ARM_SMMU_GR0_TLBIVMID, vmid);
    arm_smmu_tlb_sync_global(smmu);
    }

    +static void arm_smmu_tlb_inv_context_s2(void *cookie)
    +{
    + struct arm_smmu_domain *smmu_domain = cookie;
    +
    + arm_smmu_tlb_inv_context_s2_vmid(cookie, smmu_domain->cfg.vmid);
    +}
    +
    +void arm_smmu_tlb_inv_by_id(const void *cookie, u16 id)
    +{
    + struct arm_smmu_domain *smmu_domain = (void *)cookie;
    + struct arm_smmu_device *smmu = smmu_domain->smmu;
    +
    + arm_smmu_rpm_get(smmu);
    + switch (smmu_domain->stage) {
    + case ARM_SMMU_DOMAIN_S1:
    + arm_smmu_tlb_inv_context_s1_asid(smmu_domain, id);
    + break;
    + case ARM_SMMU_DOMAIN_S2:
    + case ARM_SMMU_DOMAIN_NESTED:
    + arm_smmu_tlb_inv_context_s2_vmid(smmu_domain, id);
    + break;
    + case ARM_SMMU_DOMAIN_BYPASS:
    + break;
    + }
    +
    + arm_smmu_rpm_put(smmu);
    +}
    +
    static void arm_smmu_tlb_inv_range_s1(unsigned long iova, size_t size,
    size_t granule, void *cookie, int reg)
    {
    diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
    index 2b9b42fb6f30..f6fb52d6f841 100644
    --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
    +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
    @@ -527,6 +527,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_tlb_inv_by_id(const void *cookie, u16 id);
    void arm_smmu_write_context_bank(struct arm_smmu_device *smmu, int idx);
    int arm_mmu500_reset(struct arm_smmu_device *smmu);

    diff --git a/include/linux/adreno-smmu-priv.h b/include/linux/adreno-smmu-priv.h
    index 4ad90541a095..c44fc68d4de8 100644
    --- a/include/linux/adreno-smmu-priv.h
    +++ b/include/linux/adreno-smmu-priv.h
    @@ -50,6 +50,7 @@ struct adreno_smmu_fault_info {
    * before set_ttbr0_cfg(). If stalling on fault is enabled,
    * the GPU driver must call resume_translation()
    * @resume_translation: Resume translation after a fault
    + * @tlb_inv_by_id: Flush TLB by ASID/VMID
    *
    *
    * The GPU driver (drm/msm) and adreno-smmu work together for controlling
    @@ -69,6 +70,7 @@ struct adreno_smmu_priv {
    void (*get_fault_info)(const void *cookie, struct adreno_smmu_fault_info *info);
    void (*set_stall)(const void *cookie, bool enabled);
    void (*resume_translation)(const void *cookie, bool terminate);
    + void (*tlb_inv_by_id)(const void *cookie, u16 id);
    };

    #endif /* __ADRENO_SMMU_PRIV_H */
    --
    2.37.2
    \
     
     \ /
      Last update: 2022-08-21 20:19    [W:3.519 / U:0.164 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site