summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2016-09-12 12:13:44 -0400
committerWill Deacon <will.deacon@arm.com>2016-09-16 04:34:16 -0400
commitdc87a98db751a98577fc6a89b4f26180fc020d24 (patch)
treec94bb65411214bab89e874394434119877badf2e /drivers
parentb9bc88118029d20f25f9e457a147de65ada00f7c (diff)
iommu/arm-smmu: Fall back to global bypass
Unlike SMMUv2, SMMUv3 has no easy way to bypass unknown stream IDs, other than allocating and filling in the entire stream table with bypass entries, which for some configurations would waste *gigabytes* of RAM. Otherwise, all transactions on unknown stream IDs will simply be aborted with a C_BAD_STREAMID event. Rather than render the system unusable in the case of an invalid DT, avoid enabling the SMMU altogether such that everything bypasses (though letting the explicit disable_bypass option take precedence). Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iommu/arm-smmu-v3.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 5db6931c715c..d7fef5f99bfc 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -123,6 +123,10 @@
123#define CR2_RECINVSID (1 << 1) 123#define CR2_RECINVSID (1 << 1)
124#define CR2_E2H (1 << 0) 124#define CR2_E2H (1 << 0)
125 125
126#define ARM_SMMU_GBPA 0x44
127#define GBPA_ABORT (1 << 20)
128#define GBPA_UPDATE (1 << 31)
129
126#define ARM_SMMU_IRQ_CTRL 0x50 130#define ARM_SMMU_IRQ_CTRL 0x50
127#define IRQ_CTRL_EVTQ_IRQEN (1 << 2) 131#define IRQ_CTRL_EVTQ_IRQEN (1 << 2)
128#define IRQ_CTRL_PRIQ_IRQEN (1 << 1) 132#define IRQ_CTRL_PRIQ_IRQEN (1 << 1)
@@ -2124,6 +2128,24 @@ static int arm_smmu_write_reg_sync(struct arm_smmu_device *smmu, u32 val,
2124 1, ARM_SMMU_POLL_TIMEOUT_US); 2128 1, ARM_SMMU_POLL_TIMEOUT_US);
2125} 2129}
2126 2130
2131/* GBPA is "special" */
2132static int arm_smmu_update_gbpa(struct arm_smmu_device *smmu, u32 set, u32 clr)
2133{
2134 int ret;
2135 u32 reg, __iomem *gbpa = smmu->base + ARM_SMMU_GBPA;
2136
2137 ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
2138 1, ARM_SMMU_POLL_TIMEOUT_US);
2139 if (ret)
2140 return ret;
2141
2142 reg &= ~clr;
2143 reg |= set;
2144 writel_relaxed(reg | GBPA_UPDATE, gbpa);
2145 return readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
2146 1, ARM_SMMU_POLL_TIMEOUT_US);
2147}
2148
2127static void arm_smmu_free_msis(void *data) 2149static void arm_smmu_free_msis(void *data)
2128{ 2150{
2129 struct device *dev = data; 2151 struct device *dev = data;
@@ -2269,7 +2291,7 @@ static int arm_smmu_device_disable(struct arm_smmu_device *smmu)
2269 return ret; 2291 return ret;
2270} 2292}
2271 2293
2272static int arm_smmu_device_reset(struct arm_smmu_device *smmu) 2294static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
2273{ 2295{
2274 int ret; 2296 int ret;
2275 u32 reg, enables; 2297 u32 reg, enables;
@@ -2370,8 +2392,17 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu)
2370 return ret; 2392 return ret;
2371 } 2393 }
2372 2394
2373 /* Enable the SMMU interface */ 2395
2374 enables |= CR0_SMMUEN; 2396 /* Enable the SMMU interface, or ensure bypass */
2397 if (!bypass || disable_bypass) {
2398 enables |= CR0_SMMUEN;
2399 } else {
2400 ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
2401 if (ret) {
2402 dev_err(smmu->dev, "GBPA not responding to update\n");
2403 return ret;
2404 }
2405 }
2375 ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, 2406 ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
2376 ARM_SMMU_CR0ACK); 2407 ARM_SMMU_CR0ACK);
2377 if (ret) { 2408 if (ret) {
@@ -2570,6 +2601,15 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
2570 struct resource *res; 2601 struct resource *res;
2571 struct arm_smmu_device *smmu; 2602 struct arm_smmu_device *smmu;
2572 struct device *dev = &pdev->dev; 2603 struct device *dev = &pdev->dev;
2604 bool bypass = true;
2605 u32 cells;
2606
2607 if (of_property_read_u32(dev->of_node, "#iommu-cells", &cells))
2608 dev_err(dev, "missing #iommu-cells property\n");
2609 else if (cells != 1)
2610 dev_err(dev, "invalid #iommu-cells value (%d)\n", cells);
2611 else
2612 bypass = false;
2573 2613
2574 smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); 2614 smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
2575 if (!smmu) { 2615 if (!smmu) {
@@ -2622,7 +2662,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
2622 platform_set_drvdata(pdev, smmu); 2662 platform_set_drvdata(pdev, smmu);
2623 2663
2624 /* Reset the device */ 2664 /* Reset the device */
2625 return arm_smmu_device_reset(smmu); 2665 return arm_smmu_device_reset(smmu, bypass);
2626} 2666}
2627 2667
2628static int arm_smmu_device_remove(struct platform_device *pdev) 2668static int arm_smmu_device_remove(struct platform_device *pdev)