]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
iommu/arm-smmu: Add configuration implementation hook
authorRobin Murphy <robin.murphy@arm.com>
Thu, 15 Aug 2019 18:37:35 +0000 (19:37 +0100)
committerWill Deacon <will@kernel.org>
Mon, 19 Aug 2019 15:52:48 +0000 (16:52 +0100)
Probing the ID registers and setting up the SMMU configuration is an
area where overrides and workarounds may well be needed. Indeed, the
Cavium workaround detection lives there at the moment, so let's break
that out.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will@kernel.org>
drivers/iommu/arm-smmu-impl.c
drivers/iommu/arm-smmu.c
drivers/iommu/arm-smmu.h

index 0657c85580cb43f3e16ca9879bea227e8ff1bf6e..69641790879324c779e407f8ac91cc3744f22ee3 100644 (file)
@@ -47,8 +47,42 @@ const struct arm_smmu_impl calxeda_impl = {
 };
 
 
+static int cavium_cfg_probe(struct arm_smmu_device *smmu)
+{
+       static atomic_t context_count = ATOMIC_INIT(0);
+       /*
+        * Cavium CN88xx erratum #27704.
+        * Ensure ASID and VMID allocation is unique across all SMMUs in
+        * the system.
+        */
+       smmu->cavium_id_base = atomic_fetch_add(smmu->num_context_banks,
+                                                  &context_count);
+       dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n");
+
+       return 0;
+}
+
+const struct arm_smmu_impl cavium_impl = {
+       .cfg_probe = cavium_cfg_probe,
+};
+
+
 struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
 {
+       /*
+        * We will inevitably have to combine model-specific implementation
+        * quirks with platform-specific integration quirks, but everything
+        * we currently support happens to work out as straightforward
+        * mutually-exclusive assignments.
+        */
+       switch (smmu->model) {
+       case CAVIUM_SMMUV2:
+               smmu->impl = &cavium_impl;
+               break;
+       default:
+               break;
+       }
+
        if (of_property_read_bool(smmu->dev->of_node,
                                  "calxeda,smmu-secure-config-access"))
                smmu->impl = &calxeda_impl;
index 432d781f05f3695c414490bfb40629b5527634d6..362b6b5a28ee518ea6b3fff0cf1a6734b2abc04f 100644 (file)
@@ -155,8 +155,6 @@ struct arm_smmu_domain {
        struct iommu_domain             domain;
 };
 
-static atomic_t cavium_smmu_context_count = ATOMIC_INIT(0);
-
 static bool using_legacy_binding, using_generic_binding;
 
 static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu)
@@ -1804,18 +1802,6 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
        }
        dev_notice(smmu->dev, "\t%u context banks (%u stage-2 only)\n",
                   smmu->num_context_banks, smmu->num_s2_context_banks);
-       /*
-        * Cavium CN88xx erratum #27704.
-        * Ensure ASID and VMID allocation is unique across all SMMUs in
-        * the system.
-        */
-       if (smmu->model == CAVIUM_SMMUV2) {
-               smmu->cavium_id_base =
-                       atomic_add_return(smmu->num_context_banks,
-                                         &cavium_smmu_context_count);
-               smmu->cavium_id_base -= smmu->num_context_banks;
-               dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n");
-       }
        smmu->cbs = devm_kcalloc(smmu->dev, smmu->num_context_banks,
                                 sizeof(*smmu->cbs), GFP_KERNEL);
        if (!smmu->cbs)
@@ -1884,6 +1870,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
                dev_notice(smmu->dev, "\tStage-2: %lu-bit IPA -> %lu-bit PA\n",
                           smmu->ipa_size, smmu->pa_size);
 
+       if (smmu->impl && smmu->impl->cfg_probe)
+               return smmu->impl->cfg_probe(smmu);
+
        return 0;
 }
 
index d4fd29d7070554df377965d76d5996f26c9bc1c0..f4e90f33fce2f000e9f06611f70d1cb34ea29b05 100644 (file)
@@ -287,6 +287,7 @@ struct arm_smmu_impl {
        u64 (*read_reg64)(struct arm_smmu_device *smmu, int page, int offset);
        void (*write_reg64)(struct arm_smmu_device *smmu, int page, int offset,
                            u64 val);
+       int (*cfg_probe)(struct arm_smmu_device *smmu);
 };
 
 static inline void __iomem *arm_smmu_page(struct arm_smmu_device *smmu, int n)