diff options
author | Robin Murphy <robin.murphy@arm.com> | 2016-09-12 12:13:53 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2016-09-16 04:34:20 -0400 |
commit | d3097e39302083d58922a3d1032d7d59a63d263d (patch) | |
tree | c38a1ab110a06caac74e655cdb32e13e49397772 | |
parent | d6fc5d977671d16535de66645f83a1bd07e1317d (diff) |
iommu/arm-smmu: Add a stream map entry iterator
We iterate over the SMEs associated with a master config quite a lot in
various places, and are about to do so even more. Let's wrap the idiom
in a handy iterator macro before the repetition gets out of hand.
Tested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | drivers/iommu/arm-smmu.c | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index b6e26dba2dec..f402f9e126a8 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -324,6 +324,8 @@ struct arm_smmu_master_cfg { | |||
324 | s16 smendx[MAX_MASTER_STREAMIDS]; | 324 | s16 smendx[MAX_MASTER_STREAMIDS]; |
325 | }; | 325 | }; |
326 | #define INVALID_SMENDX -1 | 326 | #define INVALID_SMENDX -1 |
327 | #define for_each_cfg_sme(cfg, i, idx) \ | ||
328 | for (i = 0; idx = cfg->smendx[i], i < cfg->num_streamids; ++i) | ||
327 | 329 | ||
328 | struct arm_smmu_device { | 330 | struct arm_smmu_device { |
329 | struct device *dev; | 331 | struct device *dev; |
@@ -1090,8 +1092,8 @@ static int arm_smmu_master_alloc_smes(struct arm_smmu_device *smmu, | |||
1090 | int i, idx; | 1092 | int i, idx; |
1091 | 1093 | ||
1092 | /* Allocate the SMRs on the SMMU */ | 1094 | /* Allocate the SMRs on the SMMU */ |
1093 | for (i = 0; i < cfg->num_streamids; ++i) { | 1095 | for_each_cfg_sme(cfg, i, idx) { |
1094 | if (cfg->smendx[i] != INVALID_SMENDX) | 1096 | if (idx != INVALID_SMENDX) |
1095 | return -EEXIST; | 1097 | return -EEXIST; |
1096 | 1098 | ||
1097 | /* ...except on stream indexing hardware, of course */ | 1099 | /* ...except on stream indexing hardware, of course */ |
@@ -1115,8 +1117,8 @@ static int arm_smmu_master_alloc_smes(struct arm_smmu_device *smmu, | |||
1115 | return 0; | 1117 | return 0; |
1116 | 1118 | ||
1117 | /* It worked! Now, poke the actual hardware */ | 1119 | /* It worked! Now, poke the actual hardware */ |
1118 | for (i = 0; i < cfg->num_streamids; ++i) | 1120 | for_each_cfg_sme(cfg, i, idx) |
1119 | arm_smmu_write_smr(smmu, cfg->smendx[i]); | 1121 | arm_smmu_write_smr(smmu, idx); |
1120 | 1122 | ||
1121 | return 0; | 1123 | return 0; |
1122 | 1124 | ||
@@ -1131,15 +1133,13 @@ err_free_smrs: | |||
1131 | static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg) | 1133 | static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg) |
1132 | { | 1134 | { |
1133 | struct arm_smmu_device *smmu = cfg->smmu; | 1135 | struct arm_smmu_device *smmu = cfg->smmu; |
1134 | int i; | 1136 | int i, idx; |
1135 | 1137 | ||
1136 | /* | 1138 | /* |
1137 | * We *must* clear the S2CR first, because freeing the SMR means | 1139 | * We *must* clear the S2CR first, because freeing the SMR means |
1138 | * that it can be re-allocated immediately. | 1140 | * that it can be re-allocated immediately. |
1139 | */ | 1141 | */ |
1140 | for (i = 0; i < cfg->num_streamids; ++i) { | 1142 | for_each_cfg_sme(cfg, i, idx) { |
1141 | int idx = cfg->smendx[i]; | ||
1142 | |||
1143 | /* An IOMMU group is torn down by the first device to be removed */ | 1143 | /* An IOMMU group is torn down by the first device to be removed */ |
1144 | if (idx == INVALID_SMENDX) | 1144 | if (idx == INVALID_SMENDX) |
1145 | return; | 1145 | return; |
@@ -1151,9 +1151,9 @@ static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg) | |||
1151 | __iowmb(); | 1151 | __iowmb(); |
1152 | 1152 | ||
1153 | /* Invalidate the SMRs before freeing back to the allocator */ | 1153 | /* Invalidate the SMRs before freeing back to the allocator */ |
1154 | for (i = 0; i < cfg->num_streamids; ++i) { | 1154 | for_each_cfg_sme(cfg, i, idx) { |
1155 | if (smmu->smrs) | 1155 | if (smmu->smrs) |
1156 | arm_smmu_free_smr(smmu, cfg->smendx[i]); | 1156 | arm_smmu_free_smr(smmu, idx); |
1157 | 1157 | ||
1158 | cfg->smendx[i] = INVALID_SMENDX; | 1158 | cfg->smendx[i] = INVALID_SMENDX; |
1159 | } | 1159 | } |
@@ -1162,7 +1162,7 @@ static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg) | |||
1162 | static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, | 1162 | static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, |
1163 | struct arm_smmu_master_cfg *cfg) | 1163 | struct arm_smmu_master_cfg *cfg) |
1164 | { | 1164 | { |
1165 | int i, ret = 0; | 1165 | int i, idx, ret = 0; |
1166 | struct arm_smmu_device *smmu = smmu_domain->smmu; | 1166 | struct arm_smmu_device *smmu = smmu_domain->smmu; |
1167 | struct arm_smmu_s2cr *s2cr = smmu->s2crs; | 1167 | struct arm_smmu_s2cr *s2cr = smmu->s2crs; |
1168 | enum arm_smmu_s2cr_type type = S2CR_TYPE_TRANS; | 1168 | enum arm_smmu_s2cr_type type = S2CR_TYPE_TRANS; |
@@ -1182,9 +1182,7 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, | |||
1182 | if (smmu_domain->domain.type == IOMMU_DOMAIN_DMA) | 1182 | if (smmu_domain->domain.type == IOMMU_DOMAIN_DMA) |
1183 | type = S2CR_TYPE_BYPASS; | 1183 | type = S2CR_TYPE_BYPASS; |
1184 | 1184 | ||
1185 | for (i = 0; i < cfg->num_streamids; ++i) { | 1185 | for_each_cfg_sme(cfg, i, idx) { |
1186 | int idx = cfg->smendx[i]; | ||
1187 | |||
1188 | /* Devices in an IOMMU group may already be configured */ | 1186 | /* Devices in an IOMMU group may already be configured */ |
1189 | if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx) | 1187 | if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx) |
1190 | break; | 1188 | break; |