Merge tag '6.6-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
[sfrench/cifs-2.6.git] / drivers / iommu / arm / arm-smmu-v3 / arm-smmu-v3.c
index 3fd83fb75722713eaed891db9226ab76061eb898..e82bf1c449a35dd300738f9b6b457dc9d3e3bca8 100644 (file)
@@ -894,6 +894,12 @@ static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
 {
        int index;
 
+       if (cmds->num == CMDQ_BATCH_ENTRIES - 1 &&
+           (smmu->options & ARM_SMMU_OPT_CMDQ_FORCE_SYNC)) {
+               arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, true);
+               cmds->num = 0;
+       }
+
        if (cmds->num == CMDQ_BATCH_ENTRIES) {
                arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, false);
                cmds->num = 0;
@@ -1053,7 +1059,7 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
        /*
         * This function handles the following cases:
         *
-        * (1) Install primary CD, for normal DMA traffic (SSID = 0).
+        * (1) Install primary CD, for normal DMA traffic (SSID = IOMMU_NO_PASID = 0).
         * (2) Install a secondary CD, for SID+SSID traffic.
         * (3) Update ASID of a CD. Atomically write the first 64 bits of the
         *     CD, then invalidate the old entry and mappings.
@@ -1601,7 +1607,7 @@ static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
 
        sid = FIELD_GET(PRIQ_0_SID, evt[0]);
        ssv = FIELD_GET(PRIQ_0_SSID_V, evt[0]);
-       ssid = ssv ? FIELD_GET(PRIQ_0_SSID, evt[0]) : 0;
+       ssid = ssv ? FIELD_GET(PRIQ_0_SSID, evt[0]) : IOMMU_NO_PASID;
        last = FIELD_GET(PRIQ_0_PRG_LAST, evt[0]);
        grpid = FIELD_GET(PRIQ_1_PRG_IDX, evt[1]);
 
@@ -1742,7 +1748,7 @@ arm_smmu_atc_inv_to_cmd(int ssid, unsigned long iova, size_t size,
         */
        *cmd = (struct arm_smmu_cmdq_ent) {
                .opcode                 = CMDQ_OP_ATC_INV,
-               .substream_valid        = !!ssid,
+               .substream_valid        = (ssid != IOMMU_NO_PASID),
                .atc.ssid               = ssid,
        };
 
@@ -1789,7 +1795,7 @@ static int arm_smmu_atc_inv_master(struct arm_smmu_master *master)
        struct arm_smmu_cmdq_ent cmd;
        struct arm_smmu_cmdq_batch cmds;
 
-       arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd);
+       arm_smmu_atc_inv_to_cmd(IOMMU_NO_PASID, 0, 0, &cmd);
 
        cmds.num = 0;
        for (i = 0; i < master->num_streams; i++) {
@@ -1869,7 +1875,7 @@ static void arm_smmu_tlb_inv_context(void *cookie)
                cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
                arm_smmu_cmdq_issue_cmd_with_sync(smmu, &cmd);
        }
-       arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
+       arm_smmu_atc_inv_domain(smmu_domain, IOMMU_NO_PASID, 0, 0);
 }
 
 static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
@@ -1892,8 +1898,13 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
                /* Convert page size of 12,14,16 (log2) to 1,2,3 */
                cmd->tlbi.tg = (tg - 10) / 2;
 
-               /* Determine what level the granule is at */
-               cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
+               /*
+                * Determine what level the granule is at. For non-leaf, io-pgtable
+                * assumes .tlb_flush_walk can invalidate multiple levels at once,
+                * so ignore the nominal last-level granule and leave TTL=0.
+                */
+               if (cmd->tlbi.leaf)
+                       cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
 
                num_pages = size >> tg;
        }
@@ -1957,7 +1968,7 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size,
         * Unfortunately, this can't be leaf-only since we may have
         * zapped an entire table.
         */
-       arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size);
+       arm_smmu_atc_inv_domain(smmu_domain, IOMMU_NO_PASID, iova, size);
 }
 
 void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid,
@@ -2008,6 +2019,7 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
                /* Assume that a coherent TCU implies coherent TBUs */
                return master->smmu->features & ARM_SMMU_FEAT_COHERENCY;
        case IOMMU_CAP_NOEXEC:
+       case IOMMU_CAP_DEFERRED_FLUSH:
                return true;
        default:
                return false;
@@ -2023,7 +2035,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 
        if (type != IOMMU_DOMAIN_UNMANAGED &&
            type != IOMMU_DOMAIN_DMA &&
-           type != IOMMU_DOMAIN_DMA_FQ &&
            type != IOMMU_DOMAIN_IDENTITY)
                return NULL;
 
@@ -2044,24 +2055,6 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
        return &smmu_domain->domain;
 }
 
-static int arm_smmu_bitmap_alloc(unsigned long *map, int span)
-{
-       int idx, size = 1 << span;
-
-       do {
-               idx = find_first_zero_bit(map, size);
-               if (idx == size)
-                       return -ENOSPC;
-       } while (test_and_set_bit(idx, map));
-
-       return idx;
-}
-
-static void arm_smmu_bitmap_free(unsigned long *map, int idx)
-{
-       clear_bit(idx, map);
-}
-
 static void arm_smmu_domain_free(struct iommu_domain *domain)
 {
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
@@ -2082,7 +2075,7 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
        } else {
                struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
                if (cfg->vmid)
-                       arm_smmu_bitmap_free(smmu->vmid_map, cfg->vmid);
+                       ida_free(&smmu->vmid_map, cfg->vmid);
        }
 
        kfree(smmu_domain);
@@ -2131,7 +2124,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
         * the master has been added to the devices list for this domain.
         * This isn't an issue because the STE hasn't been installed yet.
         */
-       ret = arm_smmu_write_ctx_desc(smmu_domain, 0, &cfg->cd);
+       ret = arm_smmu_write_ctx_desc(smmu_domain, IOMMU_NO_PASID, &cfg->cd);
        if (ret)
                goto out_free_cd_tables;
 
@@ -2156,7 +2149,9 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
        struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
        typeof(&pgtbl_cfg->arm_lpae_s2_cfg.vtcr) vtcr;
 
-       vmid = arm_smmu_bitmap_alloc(smmu->vmid_map, smmu->vmid_bits);
+       /* Reserve VMID 0 for stage-2 bypass STEs */
+       vmid = ida_alloc_range(&smmu->vmid_map, 1, (1 << smmu->vmid_bits) - 1,
+                              GFP_KERNEL);
        if (vmid < 0)
                return vmid;
 
@@ -2317,7 +2312,7 @@ static void arm_smmu_enable_ats(struct arm_smmu_master *master)
        pdev = to_pci_dev(master->dev);
 
        atomic_inc(&smmu_domain->nr_ats_masters);
-       arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
+       arm_smmu_atc_inv_domain(smmu_domain, IOMMU_NO_PASID, 0, 0);
        if (pci_enable_ats(pdev, stu))
                dev_err(master->dev, "Failed to enable ATS (STU %zu)\n", stu);
 }
@@ -3087,8 +3082,8 @@ static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
        reg |= STRTAB_BASE_RA;
        smmu->strtab_cfg.strtab_base = reg;
 
-       /* Allocate the first VMID for stage-2 bypass STEs */
-       set_bit(0, smmu->vmid_map);
+       ida_init(&smmu->vmid_map);
+
        return 0;
 }
 
@@ -3429,6 +3424,44 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
        return 0;
 }
 
+#define IIDR_IMPLEMENTER_ARM           0x43b
+#define IIDR_PRODUCTID_ARM_MMU_600     0x483
+#define IIDR_PRODUCTID_ARM_MMU_700     0x487
+
+static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu)
+{
+       u32 reg;
+       unsigned int implementer, productid, variant, revision;
+
+       reg = readl_relaxed(smmu->base + ARM_SMMU_IIDR);
+       implementer = FIELD_GET(IIDR_IMPLEMENTER, reg);
+       productid = FIELD_GET(IIDR_PRODUCTID, reg);
+       variant = FIELD_GET(IIDR_VARIANT, reg);
+       revision = FIELD_GET(IIDR_REVISION, reg);
+
+       switch (implementer) {
+       case IIDR_IMPLEMENTER_ARM:
+               switch (productid) {
+               case IIDR_PRODUCTID_ARM_MMU_600:
+                       /* Arm erratum 1076982 */
+                       if (variant == 0 && revision <= 2)
+                               smmu->features &= ~ARM_SMMU_FEAT_SEV;
+                       /* Arm erratum 1209401 */
+                       if (variant < 2)
+                               smmu->features &= ~ARM_SMMU_FEAT_NESTING;
+                       break;
+               case IIDR_PRODUCTID_ARM_MMU_700:
+                       /* Arm erratum 2812531 */
+                       smmu->features &= ~ARM_SMMU_FEAT_BTM;
+                       smmu->options |= ARM_SMMU_OPT_CMDQ_FORCE_SYNC;
+                       /* Arm errata 2268618, 2812531 */
+                       smmu->features &= ~ARM_SMMU_FEAT_NESTING;
+                       break;
+               }
+               break;
+       }
+}
+
 static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 {
        u32 reg;
@@ -3635,6 +3668,12 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 
        smmu->ias = max(smmu->ias, smmu->oas);
 
+       if ((smmu->features & ARM_SMMU_FEAT_TRANS_S1) &&
+           (smmu->features & ARM_SMMU_FEAT_TRANS_S2))
+               smmu->features |= ARM_SMMU_FEAT_NESTING;
+
+       arm_smmu_device_iidr_probe(smmu);
+
        if (arm_smmu_sva_supported(smmu))
                smmu->features |= ARM_SMMU_FEAT_SVA;
 
@@ -3868,6 +3907,7 @@ static void arm_smmu_device_remove(struct platform_device *pdev)
        iommu_device_sysfs_remove(&smmu->iommu);
        arm_smmu_device_disable(smmu);
        iopf_queue_free(smmu->evtq.iopf);
+       ida_destroy(&smmu->vmid_map);
 }
 
 static void arm_smmu_device_shutdown(struct platform_device *pdev)