aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Murphy <Robin.Murphy@arm.com>2015-07-29 19:46:05 +0100
committerAlex Shi <alex.shi@linaro.org>2016-04-18 14:46:05 +0800
commit7d5f529f08a891921f179ad74bc976a5fae44eb1 (patch)
treeb80547a385f284e231697a23ff5e00b7d35832db
parentb608ba0e600ef8c701654e9947882442cec12e02 (diff)
iommu/arm-smmu: Sort out coherency
Currently, we detect whether the SMMU has coherent page table walk capability from the IDR0.CTTW field, and base our cache maintenance decisions on that. In preparation for fixing the bogus DMA API usage, however, we need to ensure that the DMA API agrees about this, which necessitates deferring to the dma-coherent property in the device tree for the final say. As an added bonus, since systems exist where an external CTTW signal has been tied off incorrectly at integration, allowing DT to override it offers a neat workaround for coherency issues with such SMMUs. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> (cherry picked from commit bae2c2d421cdea9dd8d62425eef99e389584cdb3) Signed-off-by: Alex Shi <alex.shi@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/iommu/arm,smmu.txt6
-rw-r--r--drivers/iommu/arm-smmu.c20
2 files changed, 23 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 06760503a819..718074501fcb 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -43,6 +43,12 @@ conditions.
** System MMU optional properties:
+- dma-coherent : Present if page table walks made by the SMMU are
+ cache coherent with the CPU.
+
+ NOTE: this only applies to the SMMU itself, not
+ masters connected upstream of the SMMU.
+
- calxeda,smmu-secure-config-access : Enable proper handling of buggy
implementations that always use secure access to
SMMU configuration registers. In this case non-secure
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 4cd0c29cb585..0583ed2f33c0 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -37,6 +37,7 @@
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
@@ -1532,6 +1533,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
unsigned long size;
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
u32 id;
+ bool cttw_dt, cttw_reg;
dev_notice(smmu->dev, "probing hardware configuration...\n");
dev_notice(smmu->dev, "SMMUv%d with:\n", smmu->version);
@@ -1571,10 +1573,22 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
dev_notice(smmu->dev, "\taddress translation ops\n");
}
- if (id & ID0_CTTW) {
+ /*
+ * In order for DMA API calls to work properly, we must defer to what
+ * the DT says about coherency, regardless of what the hardware claims.
+ * Fortunately, this also opens up a workaround for systems where the
+ * ID register value has ended up configured incorrectly.
+ */
+ cttw_dt = of_dma_is_coherent(smmu->dev->of_node);
+ cttw_reg = !!(id & ID0_CTTW);
+ if (cttw_dt)
smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
- dev_notice(smmu->dev, "\tcoherent table walk\n");
- }
+ if (cttw_dt || cttw_reg)
+ dev_notice(smmu->dev, "\t%scoherent table walk\n",
+ cttw_dt ? "" : "non-");
+ if (cttw_dt != cttw_reg)
+ dev_notice(smmu->dev,
+ "\t(IDR0.CTTW overridden by dma-coherent property)\n");
if (id & ID0_SMS) {
u32 smr, sid, mask;