iommu/arm-smmu-v3: Document MMU-700 erratum 2812531
authorRobin Murphy <robin.murphy@arm.com>
Wed, 10 May 2023 15:38:44 +0000 (16:38 +0100)
committerWill Deacon <will@kernel.org>
Thu, 8 Jun 2023 20:58:12 +0000 (21:58 +0100)
To work around MMU-700 erratum 2812531 we need to ensure that certain
sequences of commands cannot be issued without an intervening sync. In
practice this falls out of our current command-batching machinery
anyway - each batch only contains a single type of invalidation command,
and ends with a sync. The only exception is when a batch is sufficiently
large to need issuing across multiple command queue slots, wherein the
earlier slots will not contain a sync and thus may in theory interleave
with another batch being issued in parallel to create an affected
sequence across the slot boundary.

Since MMU-700 supports range invalidate commands and thus we will prefer
to use them (which also happens to avoid conditions for other errata),
I'm not entirely sure it's even possible for a single high-level
invalidate call to generate a batch of more than 63 commands, but for
the sake of robustness and documentation, wire up an option to enforce
that a sync is always inserted for every slot issued.

The other aspect is that the relative order of DVM commands cannot be
controlled, so DVM cannot be used. Again that is already the status quo,
but since we have at least defined ARM_SMMU_FEAT_BTM, we can explicitly
disable it for documentation purposes even if it's not wired up anywhere
yet.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Link: https://lore.kernel.org/r/330221cdfd0003cd51b6c04e7ff3566741ad8374.1683731256.git.robin.murphy@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Documentation/arm64/silicon-errata.rst
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

index 951d8d42c24867aae2ebbf97018d3f12c2d818e8..84b58985a0618f12e0b6af8e6f20fea02734e289 100644 (file)
@@ -142,6 +142,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | MMU-600         | #1076982        | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | MMU-700         | #2812531        | N/A                         |
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_845719        |
 +----------------+-----------------+-----------------+-----------------------------+
index 667e7a90706e4a101b99d1cbfb4024063f8066b1..b0ccd735f8bb3f5cb3f30e68faf39200b7bfbbbf 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;
@@ -3431,6 +3437,7 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
 
 #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)
 {
@@ -3451,6 +3458,11 @@ static void arm_smmu_device_iidr_probe(struct arm_smmu_device *smmu)
                        if (variant == 0 && revision <= 2)
                                smmu->features &= ~ARM_SMMU_FEAT_SEV;
                        break;
+               case IIDR_PRODUCTID_ARM_MMU_700:
+                       /* Arm erratum 2812531 */
+                       smmu->features &= ~ARM_SMMU_FEAT_BTM;
+                       smmu->options |= ARM_SMMU_OPT_CMDQ_FORCE_SYNC;
+                       break;
                }
                break;
        }
index 5ce47f2e3402c4c9d58cd97dc125c9b1ff617c8a..1555c82203816636a937bf34688d61b5b386b67c 100644 (file)
@@ -650,6 +650,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_OPT_SKIP_PREFETCH     (1 << 0)
 #define ARM_SMMU_OPT_PAGE0_REGS_ONLY   (1 << 1)
 #define ARM_SMMU_OPT_MSIPOLL           (1 << 2)
+#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC   (1 << 3)
        u32                             options;
 
        struct arm_smmu_cmdq            cmdq;