iommu/arm-smmu-v3: Make BTM optional for SVA
authorJean-Philippe Brucker <jean-philippe@linaro.org>
Fri, 22 Jan 2021 15:10:55 +0000 (16:10 +0100)
committerWill Deacon <will@kernel.org>
Fri, 22 Jan 2021 15:44:32 +0000 (15:44 +0000)
When BTM isn't supported by the SMMU, send invalidations on the
command queue.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Link: https://lore.kernel.org/r/20210122151054.2833521-3-jean-philippe@linaro.org
Signed-off-by: Will Deacon <will@kernel.org>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

index e13b092e60049b683159bb7e2e530b5558c69d56..bb251cab61f332597268fbef4e9f859cc39bfaa3 100644 (file)
@@ -182,9 +182,13 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn,
                                         unsigned long start, unsigned long end)
 {
        struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn);
+       struct arm_smmu_domain *smmu_domain = smmu_mn->domain;
+       size_t size = end - start + 1;
 
-       arm_smmu_atc_inv_domain(smmu_mn->domain, mm->pasid, start,
-                               end - start + 1);
+       if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM))
+               arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid,
+                                           PAGE_SIZE, false, smmu_domain);
+       arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size);
 }
 
 static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
@@ -391,7 +395,7 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
        unsigned long reg, fld;
        unsigned long oas;
        unsigned long asid_bits;
-       u32 feat_mask = ARM_SMMU_FEAT_BTM | ARM_SMMU_FEAT_COHERENCY;
+       u32 feat_mask = ARM_SMMU_FEAT_COHERENCY;
 
        if (vabits_actual == 52)
                feat_mask |= ARM_SMMU_FEAT_VAX;
index 86cbac77c941676d6a2ace974f65dedf13bc2082..111467888e88d90069d7d7776ebad2307838d2fb 100644 (file)
@@ -1743,6 +1743,21 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size,
        arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size);
 }
 
+void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid,
+                                size_t granule, bool leaf,
+                                struct arm_smmu_domain *smmu_domain)
+{
+       struct arm_smmu_cmdq_ent cmd = {
+               .opcode = CMDQ_OP_TLBI_NH_VA,
+               .tlbi = {
+                       .asid   = asid,
+                       .leaf   = leaf,
+               },
+       };
+
+       __arm_smmu_tlb_inv_range(&cmd, iova, size, granule, smmu_domain);
+}
+
 static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather,
                                         unsigned long iova, size_t granule,
                                         void *cookie)
index da525f46dab4fc1d0e46f6bc34caa6ff4db7229f..56bc0c3d4f4ae58e104767d794d2ab8adb85e6ed 100644 (file)
@@ -694,6 +694,9 @@ extern struct arm_smmu_ctx_desc quiet_cd;
 int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
                            struct arm_smmu_ctx_desc *cd);
 void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
+void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid,
+                                size_t granule, bool leaf,
+                                struct arm_smmu_domain *smmu_domain);
 bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
 int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
                            unsigned long iova, size_t size);