aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorRobin Murphy <robin.murphy@arm.com>2016-09-12 12:13:49 -0400
committerWill Deacon <will.deacon@arm.com>2016-09-16 04:34:18 -0400
commit1f3d5ca43019bff1105838712d55be087d93c0da (patch)
tree7bd3fff18cab627ea06571f320518a105dc11b05 /drivers/iommu/arm-smmu.c
parent21174240e4f4439bb8ed6c116cdbdc03eba2126e (diff)
iommu/arm-smmu: Consolidate stream map entry state
In order to consider SMR masking, we really want to be able to validate ID/mask pairs against existing SMR contents to prevent stream match conflicts, which at best would cause transactions to fault unexpectedly, and at worst lead to silent unpredictable behaviour. With our SMMU instance data holding only an allocator bitmap, and the SMR values themselves scattered across master configs hanging off devices which we may have no way of finding, there's essentially no way short of digging everything back out of the hardware. Similarly, the thought of power management ops to support suspend/resume faces the exact same problem. By massaging the software state into a closer shape to the underlying hardware, everything comes together quite nicely; the allocator and the high-level view of the data become a single centralised state which we can easily keep track of, and to which any updates can be validated in full before being synchronised to the hardware itself. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c147
1 files changed, 86 insertions, 61 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index f86d7887f69a..dfe13780ba54 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -28,6 +28,7 @@
28 28
29#define pr_fmt(fmt) "arm-smmu: " fmt 29#define pr_fmt(fmt) "arm-smmu: " fmt
30 30
31#include <linux/atomic.h>
31#include <linux/delay.h> 32#include <linux/delay.h>
32#include <linux/dma-iommu.h> 33#include <linux/dma-iommu.h>
33#include <linux/dma-mapping.h> 34#include <linux/dma-mapping.h>
@@ -55,9 +56,6 @@
55/* Maximum number of context banks per SMMU */ 56/* Maximum number of context banks per SMMU */
56#define ARM_SMMU_MAX_CBS 128 57#define ARM_SMMU_MAX_CBS 128
57 58
58/* Maximum number of mapping groups per SMMU */
59#define ARM_SMMU_MAX_SMRS 128
60
61/* SMMU global address space */ 59/* SMMU global address space */
62#define ARM_SMMU_GR0(smmu) ((smmu)->base) 60#define ARM_SMMU_GR0(smmu) ((smmu)->base)
63#define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift)) 61#define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift))
@@ -295,16 +293,17 @@ enum arm_smmu_implementation {
295}; 293};
296 294
297struct arm_smmu_smr { 295struct arm_smmu_smr {
298 u8 idx;
299 u16 mask; 296 u16 mask;
300 u16 id; 297 u16 id;
298 bool valid;
301}; 299};
302 300
303struct arm_smmu_master_cfg { 301struct arm_smmu_master_cfg {
304 int num_streamids; 302 int num_streamids;
305 u16 streamids[MAX_MASTER_STREAMIDS]; 303 u16 streamids[MAX_MASTER_STREAMIDS];
306 struct arm_smmu_smr *smrs; 304 s16 smendx[MAX_MASTER_STREAMIDS];
307}; 305};
306#define INVALID_SMENDX -1
308 307
309struct arm_smmu_master { 308struct arm_smmu_master {
310 struct device_node *of_node; 309 struct device_node *of_node;
@@ -346,7 +345,7 @@ struct arm_smmu_device {
346 u32 num_mapping_groups; 345 u32 num_mapping_groups;
347 u16 streamid_mask; 346 u16 streamid_mask;
348 u16 smr_mask_mask; 347 u16 smr_mask_mask;
349 DECLARE_BITMAP(smr_map, ARM_SMMU_MAX_SMRS); 348 struct arm_smmu_smr *smrs;
350 349
351 unsigned long va_size; 350 unsigned long va_size;
352 unsigned long ipa_size; 351 unsigned long ipa_size;
@@ -550,6 +549,7 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
550 return -ERANGE; 549 return -ERANGE;
551 } 550 }
552 master->cfg.streamids[i] = streamid; 551 master->cfg.streamids[i] = streamid;
552 master->cfg.smendx[i] = INVALID_SMENDX;
553 } 553 }
554 return insert_smmu_master(smmu, master); 554 return insert_smmu_master(smmu, master);
555} 555}
@@ -1080,79 +1080,91 @@ static void arm_smmu_domain_free(struct iommu_domain *domain)
1080 kfree(smmu_domain); 1080 kfree(smmu_domain);
1081} 1081}
1082 1082
1083static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu, 1083static int arm_smmu_alloc_smr(struct arm_smmu_device *smmu)
1084 struct arm_smmu_master_cfg *cfg)
1085{ 1084{
1086 int i; 1085 int i;
1087 struct arm_smmu_smr *smrs;
1088 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1089 1086
1090 if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH)) 1087 for (i = 0; i < smmu->num_mapping_groups; i++)
1091 return 0; 1088 if (!cmpxchg(&smmu->smrs[i].valid, false, true))
1089 return i;
1092 1090
1093 if (cfg->smrs) 1091 return INVALID_SMENDX;
1094 return -EEXIST; 1092}
1095 1093
1096 smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL); 1094static void arm_smmu_free_smr(struct arm_smmu_device *smmu, int idx)
1097 if (!smrs) { 1095{
1098 dev_err(smmu->dev, "failed to allocate %d SMRs\n", 1096 writel_relaxed(~SMR_VALID, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx));
1099 cfg->num_streamids); 1097 WRITE_ONCE(smmu->smrs[idx].valid, false);
1100 return -ENOMEM; 1098}
1101 } 1099
1100static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
1101{
1102 struct arm_smmu_smr *smr = smmu->smrs + idx;
1103 u32 reg = (smr->id & smmu->streamid_mask) << SMR_ID_SHIFT |
1104 (smr->mask & smmu->smr_mask_mask) << SMR_MASK_SHIFT;
1105
1106 if (smr->valid)
1107 reg |= SMR_VALID;
1108 writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx));
1109}
1110
1111static int arm_smmu_master_alloc_smes(struct arm_smmu_device *smmu,
1112 struct arm_smmu_master_cfg *cfg)
1113{
1114 struct arm_smmu_smr *smrs = smmu->smrs;
1115 int i, idx;
1102 1116
1103 /* Allocate the SMRs on the SMMU */ 1117 /* Allocate the SMRs on the SMMU */
1104 for (i = 0; i < cfg->num_streamids; ++i) { 1118 for (i = 0; i < cfg->num_streamids; ++i) {
1105 int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0, 1119 if (cfg->smendx[i] != INVALID_SMENDX)
1106 smmu->num_mapping_groups); 1120 return -EEXIST;
1121
1122 /* ...except on stream indexing hardware, of course */
1123 if (!smrs) {
1124 cfg->smendx[i] = cfg->streamids[i];
1125 continue;
1126 }
1127
1128 idx = arm_smmu_alloc_smr(smmu);
1107 if (idx < 0) { 1129 if (idx < 0) {
1108 dev_err(smmu->dev, "failed to allocate free SMR\n"); 1130 dev_err(smmu->dev, "failed to allocate free SMR\n");
1109 goto err_free_smrs; 1131 goto err_free_smrs;
1110 } 1132 }
1133 cfg->smendx[i] = idx;
1111 1134
1112 smrs[i] = (struct arm_smmu_smr) { 1135 smrs[idx].id = cfg->streamids[i];
1113 .idx = idx, 1136 smrs[idx].mask = 0; /* We don't currently share SMRs */
1114 .mask = 0, /* We don't currently share SMRs */
1115 .id = cfg->streamids[i],
1116 };
1117 } 1137 }
1118 1138
1139 if (!smrs)
1140 return 0;
1141
1119 /* It worked! Now, poke the actual hardware */ 1142 /* It worked! Now, poke the actual hardware */
1120 for (i = 0; i < cfg->num_streamids; ++i) { 1143 for (i = 0; i < cfg->num_streamids; ++i)
1121 u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT | 1144 arm_smmu_write_smr(smmu, cfg->smendx[i]);
1122 smrs[i].mask << SMR_MASK_SHIFT;
1123 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx));
1124 }
1125 1145
1126 cfg->smrs = smrs;
1127 return 0; 1146 return 0;
1128 1147
1129err_free_smrs: 1148err_free_smrs:
1130 while (--i >= 0) 1149 while (i--) {
1131 __arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx); 1150 arm_smmu_free_smr(smmu, cfg->smendx[i]);
1132 kfree(smrs); 1151 cfg->smendx[i] = INVALID_SMENDX;
1152 }
1133 return -ENOSPC; 1153 return -ENOSPC;
1134} 1154}
1135 1155
1136static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, 1156static void arm_smmu_master_free_smes(struct arm_smmu_device *smmu,
1137 struct arm_smmu_master_cfg *cfg) 1157 struct arm_smmu_master_cfg *cfg)
1138{ 1158{
1139 int i; 1159 int i;
1140 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1141 struct arm_smmu_smr *smrs = cfg->smrs;
1142
1143 if (!smrs)
1144 return;
1145 1160
1146 /* Invalidate the SMRs before freeing back to the allocator */ 1161 /* Invalidate the SMRs before freeing back to the allocator */
1147 for (i = 0; i < cfg->num_streamids; ++i) { 1162 for (i = 0; i < cfg->num_streamids; ++i) {
1148 u8 idx = smrs[i].idx; 1163 if (smmu->smrs)
1164 arm_smmu_free_smr(smmu, cfg->smendx[i]);
1149 1165
1150 writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx)); 1166 cfg->smendx[i] = INVALID_SMENDX;
1151 __arm_smmu_free_bitmap(smmu->smr_map, idx);
1152 } 1167 }
1153
1154 cfg->smrs = NULL;
1155 kfree(smrs);
1156} 1168}
1157 1169
1158static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, 1170static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
@@ -1172,14 +1184,14 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
1172 return 0; 1184 return 0;
1173 1185
1174 /* Devices in an IOMMU group may already be configured */ 1186 /* Devices in an IOMMU group may already be configured */
1175 ret = arm_smmu_master_configure_smrs(smmu, cfg); 1187 ret = arm_smmu_master_alloc_smes(smmu, cfg);
1176 if (ret) 1188 if (ret)
1177 return ret == -EEXIST ? 0 : ret; 1189 return ret == -EEXIST ? 0 : ret;
1178 1190
1179 for (i = 0; i < cfg->num_streamids; ++i) { 1191 for (i = 0; i < cfg->num_streamids; ++i) {
1180 u32 idx, s2cr; 1192 u32 idx, s2cr;
1181 1193
1182 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; 1194 idx = cfg->smendx[i];
1183 s2cr = S2CR_TYPE_TRANS | S2CR_PRIVCFG_UNPRIV | 1195 s2cr = S2CR_TYPE_TRANS | S2CR_PRIVCFG_UNPRIV |
1184 (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT); 1196 (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT);
1185 writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx)); 1197 writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));
@@ -1195,22 +1207,22 @@ static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
1195 struct arm_smmu_device *smmu = smmu_domain->smmu; 1207 struct arm_smmu_device *smmu = smmu_domain->smmu;
1196 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 1208 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1197 1209
1198 /* An IOMMU group is torn down by the first device to be removed */
1199 if ((smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && !cfg->smrs)
1200 return;
1201
1202 /* 1210 /*
1203 * We *must* clear the S2CR first, because freeing the SMR means 1211 * We *must* clear the S2CR first, because freeing the SMR means
1204 * that it can be re-allocated immediately. 1212 * that it can be re-allocated immediately.
1205 */ 1213 */
1206 for (i = 0; i < cfg->num_streamids; ++i) { 1214 for (i = 0; i < cfg->num_streamids; ++i) {
1207 u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; 1215 int idx = cfg->smendx[i];
1208 u32 reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS; 1216 u32 reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS;
1209 1217
1218 /* An IOMMU group is torn down by the first device to be removed */
1219 if (idx == INVALID_SMENDX)
1220 return;
1221
1210 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(idx)); 1222 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(idx));
1211 } 1223 }
1212 1224
1213 arm_smmu_master_free_smrs(smmu, cfg); 1225 arm_smmu_master_free_smes(smmu, cfg);
1214} 1226}
1215 1227
1216static void arm_smmu_detach_dev(struct device *dev, 1228static void arm_smmu_detach_dev(struct device *dev,
@@ -1424,8 +1436,11 @@ static int arm_smmu_init_pci_device(struct pci_dev *pdev,
1424 break; 1436 break;
1425 1437
1426 /* Avoid duplicate SIDs, as this can lead to SMR conflicts */ 1438 /* Avoid duplicate SIDs, as this can lead to SMR conflicts */
1427 if (i == cfg->num_streamids) 1439 if (i == cfg->num_streamids) {
1428 cfg->streamids[cfg->num_streamids++] = sid; 1440 cfg->streamids[i] = sid;
1441 cfg->smendx[i] = INVALID_SMENDX;
1442 cfg->num_streamids++;
1443 }
1429 1444
1430 return 0; 1445 return 0;
1431} 1446}
@@ -1556,17 +1571,21 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
1556{ 1571{
1557 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 1572 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1558 void __iomem *cb_base; 1573 void __iomem *cb_base;
1559 int i = 0; 1574 int i;
1560 u32 reg, major; 1575 u32 reg, major;
1561 1576
1562 /* clear global FSR */ 1577 /* clear global FSR */
1563 reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR); 1578 reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
1564 writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR); 1579 writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR);
1565 1580
1566 /* Mark all SMRn as invalid and all S2CRn as bypass unless overridden */ 1581 /*
1582 * Reset stream mapping groups: Initial values mark all SMRn as
1583 * invalid and all S2CRn as bypass unless overridden.
1584 */
1567 reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS; 1585 reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS;
1568 for (i = 0; i < smmu->num_mapping_groups; ++i) { 1586 for (i = 0; i < smmu->num_mapping_groups; ++i) {
1569 writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i)); 1587 if (smmu->smrs)
1588 arm_smmu_write_smr(smmu, i);
1570 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i)); 1589 writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i));
1571 } 1590 }
1572 1591
@@ -1744,6 +1763,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1744 smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0)); 1763 smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
1745 smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT; 1764 smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
1746 1765
1766 /* Zero-initialised to mark as invalid */
1767 smmu->smrs = devm_kcalloc(smmu->dev, size, sizeof(*smmu->smrs),
1768 GFP_KERNEL);
1769 if (!smmu->smrs)
1770 return -ENOMEM;
1771
1747 dev_notice(smmu->dev, 1772 dev_notice(smmu->dev,
1748 "\tstream matching with %lu register groups, mask 0x%x", 1773 "\tstream matching with %lu register groups, mask 0x%x",
1749 size, smmu->smr_mask_mask); 1774 size, smmu->smr_mask_mask);