diff options
| author | Jean-Philippe Brucker <jean-philippe.brucker@arm.com> | 2019-04-17 14:24:45 -0400 |
|---|---|---|
| committer | Will Deacon <will.deacon@arm.com> | 2019-04-23 07:23:12 -0400 |
| commit | 8be39a1a04c1491a6a408c1549dfd4e191f3a287 (patch) | |
| tree | 874cf25a725b9176c8de2450d991e7442d683479 /drivers | |
| parent | bcecaee434733d98a9e7a45834f7439b64142eb3 (diff) | |
iommu/arm-smmu-v3: Add a master->domain pointer
As we're going to track domain-master links more closely for ATS and CD
invalidation, add pointer to the attached domain in struct
arm_smmu_master. As a result, arm_smmu_strtab_ent is redundant and can be
removed.
Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 92 |
1 files changed, 45 insertions, 47 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 25ba546cae7f..7b425483f4b6 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c | |||
| @@ -505,19 +505,6 @@ struct arm_smmu_s2_cfg { | |||
| 505 | u64 vtcr; | 505 | u64 vtcr; |
| 506 | }; | 506 | }; |
| 507 | 507 | ||
| 508 | struct arm_smmu_strtab_ent { | ||
| 509 | /* | ||
| 510 | * An STE is "assigned" if the master emitting the corresponding SID | ||
| 511 | * is attached to a domain. The behaviour of an unassigned STE is | ||
| 512 | * determined by the disable_bypass parameter, whereas an assigned | ||
| 513 | * STE behaves according to s1_cfg/s2_cfg, which themselves are | ||
| 514 | * configured according to the domain type. | ||
| 515 | */ | ||
| 516 | bool assigned; | ||
| 517 | struct arm_smmu_s1_cfg *s1_cfg; | ||
| 518 | struct arm_smmu_s2_cfg *s2_cfg; | ||
| 519 | }; | ||
| 520 | |||
| 521 | struct arm_smmu_strtab_cfg { | 508 | struct arm_smmu_strtab_cfg { |
| 522 | __le64 *strtab; | 509 | __le64 *strtab; |
| 523 | dma_addr_t strtab_dma; | 510 | dma_addr_t strtab_dma; |
| @@ -593,7 +580,7 @@ struct arm_smmu_device { | |||
| 593 | /* SMMU private data for each master */ | 580 | /* SMMU private data for each master */ |
| 594 | struct arm_smmu_master { | 581 | struct arm_smmu_master { |
| 595 | struct arm_smmu_device *smmu; | 582 | struct arm_smmu_device *smmu; |
| 596 | struct arm_smmu_strtab_ent ste; | 583 | struct arm_smmu_domain *domain; |
| 597 | u32 *sids; | 584 | u32 *sids; |
| 598 | unsigned int num_sids; | 585 | unsigned int num_sids; |
| 599 | }; | 586 | }; |
| @@ -1087,8 +1074,8 @@ static void arm_smmu_sync_ste_for_sid(struct arm_smmu_device *smmu, u32 sid) | |||
| 1087 | arm_smmu_cmdq_issue_sync(smmu); | 1074 | arm_smmu_cmdq_issue_sync(smmu); |
| 1088 | } | 1075 | } |
| 1089 | 1076 | ||
| 1090 | static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, | 1077 | static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid, |
| 1091 | __le64 *dst, struct arm_smmu_strtab_ent *ste) | 1078 | __le64 *dst) |
| 1092 | { | 1079 | { |
| 1093 | /* | 1080 | /* |
| 1094 | * This is hideously complicated, but we only really care about | 1081 | * This is hideously complicated, but we only really care about |
| @@ -1108,6 +1095,10 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, | |||
| 1108 | */ | 1095 | */ |
| 1109 | u64 val = le64_to_cpu(dst[0]); | 1096 | u64 val = le64_to_cpu(dst[0]); |
| 1110 | bool ste_live = false; | 1097 | bool ste_live = false; |
| 1098 | struct arm_smmu_device *smmu = NULL; | ||
| 1099 | struct arm_smmu_s1_cfg *s1_cfg = NULL; | ||
| 1100 | struct arm_smmu_s2_cfg *s2_cfg = NULL; | ||
| 1101 | struct arm_smmu_domain *smmu_domain = NULL; | ||
| 1111 | struct arm_smmu_cmdq_ent prefetch_cmd = { | 1102 | struct arm_smmu_cmdq_ent prefetch_cmd = { |
| 1112 | .opcode = CMDQ_OP_PREFETCH_CFG, | 1103 | .opcode = CMDQ_OP_PREFETCH_CFG, |
| 1113 | .prefetch = { | 1104 | .prefetch = { |
| @@ -1115,6 +1106,25 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, | |||
| 1115 | }, | 1106 | }, |
| 1116 | }; | 1107 | }; |
| 1117 | 1108 | ||
| 1109 | if (master) { | ||
| 1110 | smmu_domain = master->domain; | ||
| 1111 | smmu = master->smmu; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | if (smmu_domain) { | ||
| 1115 | switch (smmu_domain->stage) { | ||
| 1116 | case ARM_SMMU_DOMAIN_S1: | ||
| 1117 | s1_cfg = &smmu_domain->s1_cfg; | ||
| 1118 | break; | ||
| 1119 | case ARM_SMMU_DOMAIN_S2: | ||
| 1120 | case ARM_SMMU_DOMAIN_NESTED: | ||
| 1121 | s2_cfg = &smmu_domain->s2_cfg; | ||
| 1122 | break; | ||
| 1123 | default: | ||
| 1124 | break; | ||
| 1125 | } | ||
| 1126 | } | ||
| 1127 | |||
| 1118 | if (val & STRTAB_STE_0_V) { | 1128 | if (val & STRTAB_STE_0_V) { |
| 1119 | switch (FIELD_GET(STRTAB_STE_0_CFG, val)) { | 1129 | switch (FIELD_GET(STRTAB_STE_0_CFG, val)) { |
| 1120 | case STRTAB_STE_0_CFG_BYPASS: | 1130 | case STRTAB_STE_0_CFG_BYPASS: |
| @@ -1135,8 +1145,8 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, | |||
| 1135 | val = STRTAB_STE_0_V; | 1145 | val = STRTAB_STE_0_V; |
| 1136 | 1146 | ||
| 1137 | /* Bypass/fault */ | 1147 | /* Bypass/fault */ |
| 1138 | if (!ste->assigned || !(ste->s1_cfg || ste->s2_cfg)) { | 1148 | if (!smmu_domain || !(s1_cfg || s2_cfg)) { |
| 1139 | if (!ste->assigned && disable_bypass) | 1149 | if (!smmu_domain && disable_bypass) |
| 1140 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT); | 1150 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT); |
| 1141 | else | 1151 | else |
| 1142 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS); | 1152 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS); |
| @@ -1154,7 +1164,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, | |||
| 1154 | return; | 1164 | return; |
| 1155 | } | 1165 | } |
| 1156 | 1166 | ||
| 1157 | if (ste->s1_cfg) { | 1167 | if (s1_cfg) { |
| 1158 | BUG_ON(ste_live); | 1168 | BUG_ON(ste_live); |
| 1159 | dst[1] = cpu_to_le64( | 1169 | dst[1] = cpu_to_le64( |
| 1160 | FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | | 1170 | FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | |
| @@ -1169,22 +1179,22 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, | |||
| 1169 | !(smmu->features & ARM_SMMU_FEAT_STALL_FORCE)) | 1179 | !(smmu->features & ARM_SMMU_FEAT_STALL_FORCE)) |
| 1170 | dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD); | 1180 | dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD); |
| 1171 | 1181 | ||
| 1172 | val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK) | | 1182 | val |= (s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK) | |
| 1173 | FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS); | 1183 | FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS); |
| 1174 | } | 1184 | } |
| 1175 | 1185 | ||
| 1176 | if (ste->s2_cfg) { | 1186 | if (s2_cfg) { |
| 1177 | BUG_ON(ste_live); | 1187 | BUG_ON(ste_live); |
| 1178 | dst[2] = cpu_to_le64( | 1188 | dst[2] = cpu_to_le64( |
| 1179 | FIELD_PREP(STRTAB_STE_2_S2VMID, ste->s2_cfg->vmid) | | 1189 | FIELD_PREP(STRTAB_STE_2_S2VMID, s2_cfg->vmid) | |
| 1180 | FIELD_PREP(STRTAB_STE_2_VTCR, ste->s2_cfg->vtcr) | | 1190 | FIELD_PREP(STRTAB_STE_2_VTCR, s2_cfg->vtcr) | |
| 1181 | #ifdef __BIG_ENDIAN | 1191 | #ifdef __BIG_ENDIAN |
| 1182 | STRTAB_STE_2_S2ENDI | | 1192 | STRTAB_STE_2_S2ENDI | |
| 1183 | #endif | 1193 | #endif |
| 1184 | STRTAB_STE_2_S2PTW | STRTAB_STE_2_S2AA64 | | 1194 | STRTAB_STE_2_S2PTW | STRTAB_STE_2_S2AA64 | |
| 1185 | STRTAB_STE_2_S2R); | 1195 | STRTAB_STE_2_S2R); |
| 1186 | 1196 | ||
| 1187 | dst[3] = cpu_to_le64(ste->s2_cfg->vttbr & STRTAB_STE_3_S2TTB_MASK); | 1197 | dst[3] = cpu_to_le64(s2_cfg->vttbr & STRTAB_STE_3_S2TTB_MASK); |
| 1188 | 1198 | ||
| 1189 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S2_TRANS); | 1199 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S2_TRANS); |
| 1190 | } | 1200 | } |
| @@ -1201,10 +1211,9 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid, | |||
| 1201 | static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent) | 1211 | static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent) |
| 1202 | { | 1212 | { |
| 1203 | unsigned int i; | 1213 | unsigned int i; |
| 1204 | struct arm_smmu_strtab_ent ste = { .assigned = false }; | ||
| 1205 | 1214 | ||
| 1206 | for (i = 0; i < nent; ++i) { | 1215 | for (i = 0; i < nent; ++i) { |
| 1207 | arm_smmu_write_strtab_ent(NULL, -1, strtab, &ste); | 1216 | arm_smmu_write_strtab_ent(NULL, -1, strtab); |
| 1208 | strtab += STRTAB_STE_DWORDS; | 1217 | strtab += STRTAB_STE_DWORDS; |
| 1209 | } | 1218 | } |
| 1210 | } | 1219 | } |
| @@ -1706,13 +1715,16 @@ static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master) | |||
| 1706 | if (j < i) | 1715 | if (j < i) |
| 1707 | continue; | 1716 | continue; |
| 1708 | 1717 | ||
| 1709 | arm_smmu_write_strtab_ent(smmu, sid, step, &master->ste); | 1718 | arm_smmu_write_strtab_ent(master, sid, step); |
| 1710 | } | 1719 | } |
| 1711 | } | 1720 | } |
| 1712 | 1721 | ||
| 1713 | static void arm_smmu_detach_dev(struct arm_smmu_master *master) | 1722 | static void arm_smmu_detach_dev(struct arm_smmu_master *master) |
| 1714 | { | 1723 | { |
| 1715 | master->ste.assigned = false; | 1724 | if (!master->domain) |
| 1725 | return; | ||
| 1726 | |||
| 1727 | master->domain = NULL; | ||
| 1716 | arm_smmu_install_ste_for_dev(master); | 1728 | arm_smmu_install_ste_for_dev(master); |
| 1717 | } | 1729 | } |
| 1718 | 1730 | ||
| @@ -1723,18 +1735,14 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
| 1723 | struct arm_smmu_device *smmu; | 1735 | struct arm_smmu_device *smmu; |
| 1724 | struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); | 1736 | struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); |
| 1725 | struct arm_smmu_master *master; | 1737 | struct arm_smmu_master *master; |
| 1726 | struct arm_smmu_strtab_ent *ste; | ||
| 1727 | 1738 | ||
| 1728 | if (!fwspec) | 1739 | if (!fwspec) |
| 1729 | return -ENOENT; | 1740 | return -ENOENT; |
| 1730 | 1741 | ||
| 1731 | master = fwspec->iommu_priv; | 1742 | master = fwspec->iommu_priv; |
| 1732 | smmu = master->smmu; | 1743 | smmu = master->smmu; |
| 1733 | ste = &master->ste; | ||
| 1734 | 1744 | ||
| 1735 | /* Already attached to a different domain? */ | 1745 | arm_smmu_detach_dev(master); |
| 1736 | if (ste->assigned) | ||
| 1737 | arm_smmu_detach_dev(master); | ||
| 1738 | 1746 | ||
| 1739 | mutex_lock(&smmu_domain->init_mutex); | 1747 | mutex_lock(&smmu_domain->init_mutex); |
| 1740 | 1748 | ||
| @@ -1754,19 +1762,10 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
| 1754 | goto out_unlock; | 1762 | goto out_unlock; |
| 1755 | } | 1763 | } |
| 1756 | 1764 | ||
| 1757 | ste->assigned = true; | 1765 | master->domain = smmu_domain; |
| 1758 | 1766 | ||
| 1759 | if (smmu_domain->stage == ARM_SMMU_DOMAIN_BYPASS) { | 1767 | if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) |
| 1760 | ste->s1_cfg = NULL; | 1768 | arm_smmu_write_ctx_desc(smmu, &smmu_domain->s1_cfg); |
| 1761 | ste->s2_cfg = NULL; | ||
| 1762 | } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { | ||
| 1763 | ste->s1_cfg = &smmu_domain->s1_cfg; | ||
| 1764 | ste->s2_cfg = NULL; | ||
| 1765 | arm_smmu_write_ctx_desc(smmu, ste->s1_cfg); | ||
| 1766 | } else { | ||
| 1767 | ste->s1_cfg = NULL; | ||
| 1768 | ste->s2_cfg = &smmu_domain->s2_cfg; | ||
| 1769 | } | ||
| 1770 | 1769 | ||
| 1771 | arm_smmu_install_ste_for_dev(master); | 1770 | arm_smmu_install_ste_for_dev(master); |
| 1772 | out_unlock: | 1771 | out_unlock: |
| @@ -1921,8 +1920,7 @@ static void arm_smmu_remove_device(struct device *dev) | |||
| 1921 | 1920 | ||
| 1922 | master = fwspec->iommu_priv; | 1921 | master = fwspec->iommu_priv; |
| 1923 | smmu = master->smmu; | 1922 | smmu = master->smmu; |
| 1924 | if (master && master->ste.assigned) | 1923 | arm_smmu_detach_dev(master); |
| 1925 | arm_smmu_detach_dev(master); | ||
| 1926 | iommu_group_remove_device(dev); | 1924 | iommu_group_remove_device(dev); |
| 1927 | iommu_device_unlink(&smmu->iommu, dev); | 1925 | iommu_device_unlink(&smmu->iommu, dev); |
| 1928 | kfree(master); | 1926 | kfree(master); |
